Skip to content

Commit

Permalink
Improve Vulkan demo (#717)
Browse files Browse the repository at this point in the history
* demo: fix errors and warnings in GLFW Vulkan demo

* demo: improve resize handling in GLFW Vulkan demo

On my machine (x86_64 Linux, Wayland) VK_SUBOPTIMAL or
VK_OUT_OF_DATE_KHR were never returned so the resizing of the swapchain
never happened.

Fix by using GLFW's resize callback to detect a window resize and a
swapchain recreation. Vulkan tutorial uses the same approach.

fb_scale was never used in the Vulkan backend, so it was removed.

* demo: fix copy&paste typo in GLFW Vulkan demo

* demo: sync nuklear_glfw_vulkan.in.h with nuklear_glfw_vulkan.h

Over time people have not been noticing that the expected workflow is to
build nuklear_glfw_vulkan.h from nuklear_glfw_vulkan.in.h
  • Loading branch information
Detegr authored Oct 19, 2024
1 parent b2ffce5 commit 6566d90
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
47 changes: 39 additions & 8 deletions demo/glfw_vulkan/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,19 @@ struct vulkan_demo {
VkDeviceMemory demo_texture_memory;

VkFence render_fence;

bool framebuffer_resized;
};

static void glfw_framebuffer_resize_callback(GLFWwindow* window, int width, int height) {
struct vulkan_demo* demo;

(void)width;
(void)height;
demo = glfwGetWindowUserPointer(window);
demo->framebuffer_resized = true;
}

static void glfw_error_callback(int e, const char *d) {
fprintf(stderr, "Error %d: %s\n", e, d);
}
Expand Down Expand Up @@ -299,7 +310,7 @@ bool create_instance(struct vulkan_demo *demo) {
if (i > 0) {
printf(", ");
}
printf(enabled_extensions[i]);
printf("%s\n", enabled_extensions[i]);
}
printf("\n");
for (i = 0; i < enabled_extension_count; i++) {
Expand Down Expand Up @@ -1227,8 +1238,8 @@ bool create_graphics_pipeline(struct vulkan_demo *demo) {
bool ret = false;
char *vert_shader_code = NULL;
char *frag_shader_code = NULL;
VkShaderModule vert_shader_module;
VkShaderModule frag_shader_module;
VkShaderModule vert_shader_module = VK_NULL_HANDLE;
VkShaderModule frag_shader_module = VK_NULL_HANDLE;
FILE *fp;
size_t file_len;
VkPipelineShaderStageCreateInfo vert_shader_stage_info;
Expand All @@ -1246,8 +1257,9 @@ bool create_graphics_pipeline(struct vulkan_demo *demo) {
VkPipelineLayoutCreateInfo pipeline_layout_info;
VkResult result;
VkGraphicsPipelineCreateInfo pipeline_info;
size_t read_result;

fp = fopen("shaders/demo.vert.spv", "r");
fp = fopen("shaders/demo.vert.spv", "rb");
if (!fp) {
fprintf(stderr, "Couldn't open shaders/demo.vert.spv\n");
return false;
Expand All @@ -1256,15 +1268,19 @@ bool create_graphics_pipeline(struct vulkan_demo *demo) {
file_len = ftell(fp);
vert_shader_code = malloc(file_len);
fseek(fp, 0, 0);
fread(vert_shader_code, 1, file_len, fp);
read_result = fread(vert_shader_code, file_len, 1, fp);
fclose(fp);
if (read_result != 1) {
fprintf(stderr, "Could not read fragment shader\n");
goto cleanup;
}

if (!create_shader_module(demo->device, vert_shader_code, file_len,
&vert_shader_module)) {
goto cleanup;
}

fp = fopen("shaders/demo.frag.spv", "r");
fp = fopen("shaders/demo.frag.spv", "rb");
if (!fp) {
fprintf(stderr, "Couldn't open shaders/demo.frag.spv\n");
return false;
Expand All @@ -1273,8 +1289,12 @@ bool create_graphics_pipeline(struct vulkan_demo *demo) {
file_len = ftell(fp);
frag_shader_code = malloc(file_len);
fseek(fp, 0, 0);
fread(frag_shader_code, 1, file_len, fp);
read_result = fread(frag_shader_code, file_len, 1, fp);
fclose(fp);
if (read_result != 1) {
fprintf(stderr, "Could not read fragment shader\n");
goto cleanup;
}

if (!create_shader_module(demo->device, frag_shader_code, file_len,
&frag_shader_module)) {
Expand Down Expand Up @@ -1862,6 +1882,8 @@ bool create_vulkan_demo(struct vulkan_demo *demo) {
return false;
}

demo->framebuffer_resized = false;

return true;
}

Expand All @@ -1876,6 +1898,9 @@ bool recreate_swap_chain(struct vulkan_demo *demo) {
update_descriptor_sets(demo);
nk_glfw3_resize(demo->swap_chain_image_extent.width,
demo->swap_chain_image_extent.height);

demo->framebuffer_resized = false;

return true;
}

Expand Down Expand Up @@ -1961,7 +1986,7 @@ bool render(struct vulkan_demo *demo, struct nk_colorf *bg,

result = vkQueuePresentKHR(demo->present_queue, &present_info);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || demo->framebuffer_resized) {
recreate_swap_chain(demo);
} else if (result != VK_SUCCESS) {
fprintf(stderr, "vkQueuePresentKHR failed: %d\n", result);
Expand Down Expand Up @@ -2073,6 +2098,8 @@ int main(void) {
memset(&demo, 0, sizeof(struct vulkan_demo));
demo.win =
glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
glfwSetWindowUserPointer(demo.win, &demo);
glfwSetFramebufferSizeCallback(demo.win, glfw_framebuffer_resize_callback);

if (!create_vulkan_demo(&demo)) {
fprintf(stderr, "failed to create vulkan demo!\n");
Expand Down Expand Up @@ -2192,6 +2219,10 @@ int main(void) {
demo.image_available, NULL, &image_index);

if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreate_swap_chain(&demo);

/* If vkAcquireNextImageKHR does not successfully acquire an image,
* semaphore and fence are unaffected. */
continue;
}
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
Expand Down
7 changes: 2 additions & 5 deletions demo/glfw_vulkan/nuklear_glfw_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,6 @@ static struct nk_glfw {
struct nk_glfw_device vulkan;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
Expand Down Expand Up @@ -1179,8 +1178,6 @@ NK_API void nk_glfw3_resize(uint32_t framebuffer_width,
struct nk_glfw_device *dev = &glfw.vulkan;
glfwGetWindowSize(glfw.win, &glfw.width, &glfw.height);
glfwGetFramebufferSize(glfw.win, &glfw.display_width, &glfw.display_height);
glfw.fb_scale.x = (float)glfw.display_width / (float)glfw.width;
glfw.fb_scale.y = (float)glfw.display_height / (float)glfw.height;

nk_glfw3_destroy_render_resources(dev);
nk_glfw3_create_render_resources(dev, framebuffer_width,
Expand Down Expand Up @@ -1264,7 +1261,7 @@ NK_API void nk_glfw3_new_frame(void) {
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);

#ifdef NK_GLFW_GL4_MOUSE_GRABBING
#ifdef NK_GLFW_VULKAN_MOUSE_GRABBING
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
Expand Down Expand Up @@ -1332,7 +1329,7 @@ NK_API void nk_glfw3_new_frame(void) {

glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
#ifdef NK_GLFW_GL4_MOUSE_GRABBING
#ifdef NK_GLFW_VULKAN_MOUSE_GRABBING
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x,
ctx->input.mouse.prev.y);
Expand Down
15 changes: 9 additions & 6 deletions demo/glfw_vulkan/src/nuklear_glfw_vulkan.in.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ unsigned char nuklearshaders_nuklear_frag_spv[] = {};
unsigned int nuklearshaders_nuklear_frag_spv_len = 0;
// NUKLEAR_SHADERS_END

#include <assert.h>
#include <stddef.h>
#include <string.h>
#define GLFW_INCLUDE_VULKAN
Expand Down Expand Up @@ -71,7 +72,6 @@ NK_API void nk_glfw3_mouse_button_callback(GLFWwindow *win, int button,
*/
#ifdef NK_GLFW_VULKAN_IMPLEMENTATION
#undef NK_GLFW_VULKAN_IMPLEMENTATION
#include <assert.h>
#include <stdlib.h>

#ifndef NK_GLFW_TEXT_MAX
Expand Down Expand Up @@ -149,13 +149,13 @@ static struct nk_glfw {
struct nk_glfw_device vulkan;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
int is_double_click_down;
struct nk_vec2 double_click_pos;
float delta_time_seconds_last;
} glfw;

struct Mat4f {
Expand Down Expand Up @@ -955,8 +955,6 @@ NK_API void nk_glfw3_resize(uint32_t framebuffer_width,
struct nk_glfw_device *dev = &glfw.vulkan;
glfwGetWindowSize(glfw.win, &glfw.width, &glfw.height);
glfwGetFramebufferSize(glfw.win, &glfw.display_width, &glfw.display_height);
glfw.fb_scale.x = (float)glfw.display_width / (float)glfw.width;
glfw.fb_scale.y = (float)glfw.display_height / (float)glfw.height;

nk_glfw3_destroy_render_resources(dev);
nk_glfw3_create_render_resources(dev, framebuffer_width,
Expand Down Expand Up @@ -1031,11 +1029,16 @@ NK_API void nk_glfw3_new_frame(void) {
struct nk_context *ctx = &glfw.ctx;
struct GLFWwindow *win = glfw.win;

/* update the timer */
float delta_time_now = (float)glfwGetTime();
glfw.ctx.delta_time_seconds = delta_time_now - glfw.delta_time_seconds_last;
glfw.delta_time_seconds_last = delta_time_now;

nk_input_begin(ctx);
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);

#ifdef NK_GLFW_GL4_MOUSE_GRABBING
#ifdef NK_GLFW_VULKAN_MOUSE_GRABBING
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
Expand Down Expand Up @@ -1103,7 +1106,7 @@ NK_API void nk_glfw3_new_frame(void) {

glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
#ifdef NK_GLFW_GL4_MOUSE_GRABBING
#ifdef NK_GLFW_VULKAN_MOUSE_GRABBING
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x,
ctx->input.mouse.prev.y);
Expand Down

0 comments on commit 6566d90

Please sign in to comment.