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:
parent
b2ffce5131
commit
6566d9075d
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user