Added window resizing

main
noah metz 2024-11-03 14:25:59 -07:00
parent 7538a57ed0
commit 530a034ed1
4 changed files with 251 additions and 39 deletions

@ -150,6 +150,8 @@ typedef struct RenderContextStruct {
uint32_t current_frame;
vec2 window_scale;
bool framebuffer_recreated;
} RenderContext;
GLFWwindow* init_window();
@ -229,6 +231,11 @@ VkResult command_transition_image_layout(
uint32_t dest_family,
VkImageAspectFlags aspect_flags);
VkShaderModule load_shader_file(const char* path, VkDevice device);
VkShaderModule load_shader_file(
const char* path,
VkDevice device);
VkResult recreate_framebuffer(
RenderContext* gpu);
#endif

@ -153,7 +153,12 @@ VkResult draw_frame(
}
uint32_t image_index;
VK_RESULT(vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, frame->image, VK_NULL_HANDLE, &image_index));
result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, frame->image, VK_NULL_HANDLE, &image_index);
if(result == VK_ERROR_OUT_OF_DATE_KHR) {
VK_RESULT(recreate_framebuffer(context));
} else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
return result;
}
VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index];
VK_RESULT(vkResetCommandBuffer(command_buffer, 0));
@ -227,7 +232,12 @@ VkResult draw_frame(
.pResults = 0,
};
VK_RESULT(vkQueuePresentKHR(context->present_queue.handle, &present_info));
result = vkQueuePresentKHR(context->present_queue.handle, &present_info);
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
VK_RESULT(recreate_framebuffer(context));
} else if(result != VK_SUCCESS) {
return result;
}
context->current_frame = (context->current_frame + 1) % MAX_FRAMES_IN_FLIGHT;

@ -52,7 +52,6 @@ GLFWwindow* init_window() {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
// TODO: recreate the framebuffer on resize
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT, "roleplay", 0, 0);
@ -61,7 +60,9 @@ GLFWwindow* init_window() {
return window;
}
VkShaderModule load_shader_file(const char* path, VkDevice device) {
VkShaderModule load_shader_file(
const char* path,
VkDevice device) {
FILE* file;
file = fopen(path, "rb");
if(file == 0) {
@ -104,7 +105,9 @@ VkShaderModule load_shader_file(const char* path, VkDevice device) {
}
bool check_validation_layers(const char ** layers, uint32_t num_layers) {
bool check_validation_layers(
const char ** layers,
uint32_t num_layers) {
uint32_t layer_count;
VkResult result;
@ -195,7 +198,9 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
return VK_FALSE;
}
VkResult create_debug_messenger(VkInstance instance, VkDebugUtilsMessengerEXT* debug_messenger) {
VkResult create_debug_messenger(
VkInstance instance,
VkDebugUtilsMessengerEXT* debug_messenger) {
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
@ -212,7 +217,9 @@ VkResult create_debug_messenger(VkInstance instance, VkDebugUtilsMessengerEXT* d
return VK_SUCCESS;
}
VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device) {
VkResult get_best_physical_device(
VkInstance instance,
VkPhysicalDevice* device) {
uint32_t device_count = 0;
VkResult result;
VK_RESULT(vkEnumeratePhysicalDevices(instance, &device_count, 0));
@ -262,7 +269,13 @@ VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device)
return VK_SUCCESS;
}
VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR surface, GPUQueue* graphics_queue, GPUQueue* present_queue, GPUQueue* transfer_queue, VkDevice* device) {
VkResult create_logical_device(
VkPhysicalDevice physical_device,
VkSurfaceKHR surface,
GPUQueue* graphics_queue,
GPUQueue* present_queue,
GPUQueue* transfer_queue,
VkDevice* device) {
if(graphics_queue == NULL || present_queue == NULL || transfer_queue == NULL || device == NULL) {
return VK_ERROR_VALIDATION_FAILED_EXT;
}
@ -422,7 +435,11 @@ VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR su
return VK_SUCCESS;
}
VkResult create_memory_allocator(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, VmaAllocator* allocator) {
VkResult create_memory_allocator(
VkInstance instance,
VkPhysicalDevice physical_device,
VkDevice device,
VmaAllocator* allocator) {
VmaAllocatorCreateInfo allocator_create_info = {
.vulkanApiVersion = VK_API_VERSION_1_2,
.instance = instance,
@ -437,7 +454,10 @@ VkResult create_memory_allocator(VkInstance instance, VkPhysicalDevice physical_
return VK_SUCCESS;
}
VkResult get_swapchain_details(VkPhysicalDevice physical_device, VkSurfaceKHR surface, SwapchainDetails* details) {
VkResult get_swapchain_details(
VkPhysicalDevice physical_device,
VkSurfaceKHR surface,
SwapchainDetails* details) {
details->formats = 0;
details->present_modes = 0;
@ -495,13 +515,24 @@ VkExtent2D choose_swapchain_extent(SwapchainDetails swapchain_details) {
return swapchain_details.capabilities.currentExtent;
}
VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentModeKHR present_mode, VkExtent2D extent, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR capabilities, uint32_t graphics_family_index, uint32_t present_family_index, VkSwapchainKHR* swapchain) {
VkResult create_swapchain(
VkDevice device,
VkSurfaceFormatKHR format,
VkPresentModeKHR present_mode,
VkExtent2D extent,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR capabilities,
uint32_t graphics_family_index,
uint32_t present_family_index,
VkSwapchainKHR* swapchain) {
uint32_t image_count = capabilities.minImageCount + 1;
uint32_t max_images = capabilities.maxImageCount;
if((max_images > 0) && (image_count > max_images)) {
image_count = max_images;
}
VkSwapchainKHR old_swapchain = *swapchain;
VkSwapchainCreateInfoKHR swapchain_info = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.surface = surface,
@ -515,7 +546,7 @@ VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentM
.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
.presentMode = present_mode,
.clipped = VK_TRUE,
.oldSwapchain = *swapchain,
.oldSwapchain = old_swapchain,
};
uint32_t queue_families[2] = {graphics_family_index, present_family_index};
@ -536,7 +567,11 @@ VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentM
return VK_SUCCESS;
}
VkResult get_swapchain_images(VkDevice device, VkSwapchainKHR swapchain, VkImage** images, uint32_t* image_count) {
VkResult get_swapchain_images(
VkDevice device,
VkSwapchainKHR swapchain,
VkImage** images,
uint32_t* image_count) {
VkResult result;
VK_RESULT(vkGetSwapchainImagesKHR(device, swapchain, image_count, 0));
@ -554,7 +589,12 @@ VkResult get_swapchain_images(VkDevice device, VkSwapchainKHR swapchain, VkImage
return VK_SUCCESS;
}
VkResult create_image_views(VkDevice device, uint32_t image_count, VkImage* images, VkSurfaceFormatKHR format, VkImageView** image_views) {
VkResult create_image_views(
VkDevice device,
uint32_t image_count,
VkImage* images,
VkSurfaceFormatKHR format,
VkImageView** image_views) {
*image_views = malloc(sizeof(VkImageView)*image_count);
if(*image_views == 0) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
@ -591,7 +631,11 @@ VkResult create_image_views(VkDevice device, uint32_t image_count, VkImage* imag
return VK_SUCCESS;
}
VkResult find_depth_format(VkPhysicalDevice physical_device, VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat* format) {
VkResult find_depth_format(
VkPhysicalDevice physical_device,
VkImageTiling tiling,
VkFormatFeatureFlags features,
VkFormat* format) {
for(uint32_t i = 0; i < depth_format_count; i++) {
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(physical_device, depth_formats[i], &properties);
@ -607,7 +651,11 @@ VkResult find_depth_format(VkPhysicalDevice physical_device, VkImageTiling tilin
return VK_ERROR_VALIDATION_FAILED_EXT;
}
VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format, VkRenderPass* render_pass) {
VkResult create_render_pass(
VkDevice device,
VkSurfaceFormatKHR format,
VkFormat depth_format,
VkRenderPass* render_pass) {
VkAttachmentDescription attachments[] = {
{
.format = format.format,
@ -710,7 +758,14 @@ VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat
return VK_SUCCESS;
}
VkResult create_swapchain_framebuffers(VkDevice device, uint32_t image_count, VkImageView* image_views, VkImageView depth_image_view, VkRenderPass render_pass, VkExtent2D extent, VkFramebuffer** framebuffers) {
VkResult create_swapchain_framebuffers(
VkDevice device,
uint32_t image_count,
VkImageView* image_views,
VkImageView depth_image_view,
VkRenderPass render_pass,
VkExtent2D extent,
VkFramebuffer** framebuffers) {
*framebuffers = malloc(sizeof(VkFramebuffer)*image_count);
if(*framebuffers == 0) {
return 0;
@ -778,7 +833,9 @@ VkSemaphore create_semaphore(VkDevice device) {
return semaphore;
}
VkFence create_fence(VkDevice device, VkFenceCreateFlags flags) {
VkFence create_fence(
VkDevice device,
VkFenceCreateFlags flags) {
VkFenceCreateInfo fence_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = flags,
@ -793,7 +850,10 @@ VkFence create_fence(VkDevice device, VkFenceCreateFlags flags) {
return fence;
}
VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_pool, uint32_t image_count) {
VkCommandBuffer* create_command_buffers(
VkDevice device,
VkCommandPool command_pool,
uint32_t image_count) {
VkCommandBufferAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = command_pool,
@ -814,7 +874,11 @@ VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_p
return command_buffers;
}
VkResult create_frame_context(VkDevice device, VmaAllocator allocator, VkCommandPool transfer_pool, FrameContext* frame) {
VkResult create_frame_context(
VkDevice device,
VmaAllocator allocator,
VkCommandPool transfer_pool,
FrameContext* frame) {
VkResult result;
frame->ready = create_fence(device, VK_FENCE_CREATE_SIGNALED_BIT);
@ -852,7 +916,16 @@ VkResult create_frame_context(VkDevice device, VmaAllocator allocator, VkCommand
return VK_SUCCESS;
}
VkResult create_depth_image(VkDevice device, VkFormat depth_format, VkExtent2D swapchain_extent, VmaAllocator allocator, VkCommandPool extra_graphics_pool, GPUQueue graphics_queue, VkImage* depth_image, VmaAllocation* depth_image_memory, VkImageView* depth_image_view) {
VkResult create_depth_image(
VkDevice device,
VkFormat depth_format,
VkExtent2D swapchain_extent,
VmaAllocator allocator,
VkCommandPool extra_graphics_pool,
GPUQueue graphics_queue,
VkImage* depth_image,
VmaAllocation* depth_image_memory,
VkImageView* depth_image_view) {
VkExtent3D depth_extent = {
.width = swapchain_extent.width,
@ -956,30 +1029,76 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
VK_RESULT(create_frame_context(context->device, context->allocator, context->transfer_pool, &context->frame[i]));
}
VK_RESULT(get_swapchain_details(context->physical_device, context->surface, &context->swapchain_details));
VK_RESULT(get_swapchain_details(
context->physical_device,
context->surface,
&context->swapchain_details));
context->swapchain_format = choose_swapchain_format(context->swapchain_details);
context->swapchain_present_mode = choose_present_mode(context->swapchain_details);
context->swapchain_extent = choose_swapchain_extent(context->swapchain_details);
context->framebuffer_recreated = true;
context->swapchain = VK_NULL_HANDLE;
VK_RESULT(create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->graphics_queue.family, context->present_queue.family, &context->swapchain));
VK_RESULT(get_swapchain_images(context->device, context->swapchain, &context->swapchain_images, &context->swapchain_image_count));
VK_RESULT(create_swapchain(
context->device,
context->swapchain_format,
context->swapchain_present_mode,
context->swapchain_extent,
context->surface,
context->swapchain_details.capabilities,
context->graphics_queue.family,
context->present_queue.family,
&context->swapchain));
VK_RESULT(get_swapchain_images(
context->device,
context->swapchain,
&context->swapchain_images,
&context->swapchain_image_count));
context->swapchain_command_buffers = create_command_buffers(context->device, context->graphics_pool, context->swapchain_image_count);
if(context->swapchain_command_buffers == NULL) {
return VK_ERROR_VALIDATION_FAILED_EXT;
}
VK_RESULT(create_image_views(context->device, context->swapchain_image_count, context->swapchain_images, context->swapchain_format, &context->swapchain_image_views));
VK_RESULT(find_depth_format(context->physical_device, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, &context->depth_format));
VK_RESULT(create_render_pass(context->device, context->swapchain_format, context->depth_format, &context->render_pass));
VK_RESULT(create_depth_image(context->device, context->depth_format, context->swapchain_extent, context->allocator, context->extra_graphics_pool, context->graphics_queue, &context->depth_image, &context->depth_image_memory, &context->depth_image_view));
VK_RESULT(create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent, &context->swapchain_framebuffers));
VK_RESULT(create_image_views(
context->device,
context->swapchain_image_count,
context->swapchain_images,
context->swapchain_format,
&context->swapchain_image_views));
VK_RESULT(find_depth_format(
context->physical_device,
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
&context->depth_format));
VK_RESULT(create_render_pass(
context->device,
context->swapchain_format,
context->depth_format,
&context->render_pass));
VK_RESULT(create_depth_image(
context->device,
context->depth_format,
context->swapchain_extent,
context->allocator,
context->extra_graphics_pool,
context->graphics_queue,
&context->depth_image,
&context->depth_image_memory,
&context->depth_image_view));
VK_RESULT(create_swapchain_framebuffers(
context->device,
context->swapchain_image_count,
context->swapchain_image_views,
context->depth_image_view,
context->render_pass,
context->swapchain_extent,
&context->swapchain_framebuffers));
context->current_frame = 0;
return VK_SUCCESS;
@ -1211,3 +1330,76 @@ VkResult add_transfer(
return VK_SUCCESS;
}
VkResult recreate_framebuffer(RenderContext* gpu) {
VkResult result;
vkDeviceWaitIdle(gpu->device);
for(uint32_t i = 0; i < gpu->swapchain_image_count; i++) {
vkDestroyFramebuffer(gpu->device, gpu->swapchain_framebuffers[i], NULL);
vkDestroyImageView(gpu->device, gpu->swapchain_image_views[i], NULL);
}
vkDestroyImageView(gpu->device, gpu->depth_image_view, NULL);
vmaDestroyImage(gpu->allocator, gpu->depth_image, gpu->depth_image_memory);
free(gpu->swapchain_images);
free(gpu->swapchain_image_views);
free(gpu->swapchain_framebuffers);
VK_RESULT(get_swapchain_details(
gpu->physical_device,
gpu->surface,
&gpu->swapchain_details))
gpu->swapchain_format = choose_swapchain_format(gpu->swapchain_details);
gpu->swapchain_present_mode = choose_present_mode(gpu->swapchain_details);
gpu->swapchain_extent = choose_swapchain_extent(gpu->swapchain_details);
VK_RESULT(create_swapchain(
gpu->device,
gpu->swapchain_format,
gpu->swapchain_present_mode,
gpu->swapchain_extent,
gpu->surface,
gpu->swapchain_details.capabilities,
gpu->graphics_queue.family,
gpu->present_queue.family,
&gpu->swapchain));
VK_RESULT(get_swapchain_images(
gpu->device,
gpu->swapchain,
&gpu->swapchain_images,
&gpu->swapchain_image_count));
VK_RESULT(create_image_views(
gpu->device,
gpu->swapchain_image_count,
gpu->swapchain_images,
gpu->swapchain_format,
&gpu->swapchain_image_views));
VK_RESULT(create_depth_image(
gpu->device,
gpu->depth_format,
gpu->swapchain_extent,
gpu->allocator,
gpu->extra_graphics_pool,
gpu->graphics_queue,
&gpu->depth_image,
&gpu->depth_image_memory,
&gpu->depth_image_view));
VK_RESULT(create_swapchain_framebuffers(
gpu->device,
gpu->swapchain_image_count,
gpu->swapchain_image_views,
gpu->depth_image_view,
gpu->render_pass,
gpu->swapchain_extent,
&gpu->swapchain_framebuffers));
gpu->framebuffer_recreated = true;
return VK_SUCCESS;
}

@ -136,8 +136,8 @@ VkResult main_thread(ClientContext* context) {
GPUString* mapped_string = context->ui.containers[0].layers[0].strings_buffer;
char str[51];
double last_frame_time = 0;
int frame = 0;
double last_frame_time = 0;
while(glfwWindowShouldClose(context->window) == 0) {
double frame_time = glfwGetTime();
double delta_time = (frame_time - last_frame_time);
@ -152,9 +152,12 @@ VkResult main_thread(ClientContext* context) {
glfwPollEvents();
if(context->key_spin[0] != 0 || context->key_spin[1] != 0 ||
if((context->key_spin[0] != 0 || context->key_spin[1] != 0 ||
context->zoom != 0 ||
context->cur_spin[0] != 0 || context->cur_spin[1] != 0 || frame == 1) {
context->cur_spin[0] != 0 || context->cur_spin[1] != 0 ||
context->render.framebuffer_recreated == true) && frame > 0) {
// signal it as handled
context->render.framebuffer_recreated = false;
context->rotation[0] += (float)context->key_spin[0]*delta_time*context->key_spin_speed;
context->rotation[0] += (float)context->cur_spin[0]*delta_time*context->cur_spin_speed;
@ -214,7 +217,6 @@ VkResult main_thread(ClientContext* context) {
&context->render));
}
frame += 1;
//
VkResult result = draw_frame(&context->render, &context->ui, &context->hex, frame_time);
@ -222,6 +224,7 @@ VkResult main_thread(ClientContext* context) {
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
glfwDestroyWindow(context->window);
}
frame += 1;
last_frame_time = frame_time;
}