Improve Vulkan demo (#717)

* 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
This commit is contained in:
Antti Keränen 2024-10-19 11:04:28 +03:00 committed by GitHub
parent b2ffce5131
commit 6566d9075d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 19 deletions

View File

@ -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);
}
@ -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++) {
@ -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;
@ -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;
@ -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;
@ -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)) {
@ -1862,6 +1882,8 @@ bool create_vulkan_demo(struct vulkan_demo *demo) {
return false;
}
demo->framebuffer_resized = false;
return true;
}
@ -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;
}
@ -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);
@ -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");
@ -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) {

View File

@ -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;
@ -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,
@ -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);
@ -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);

View File

@ -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
@ -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
@ -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 {
@ -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,
@ -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);
@ -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);