summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.c7
-rw-r--r--src/platform.h7
-rw-r--r--src/platform_sdl.c10
-rw-r--r--src/renderer.c104
-rw-r--r--src/renderer.h4
5 files changed, 97 insertions, 35 deletions
diff --git a/src/main.c b/src/main.c
index edf5151..d2ea49d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -22,12 +22,15 @@ int main(void) {
(event.type == VGLTF_EVENT_KEY_DOWN &&
event.key.key == VGLTF_KEY_ESCAPE)) {
goto out_main_loop;
+ } else if (event.type == VGLTF_EVENT_WINDOW_RESIZED) {
+ vgltf_renderer_on_window_resized(
+ &renderer,
+ (struct vgltf_window_size){.width = event.window_resized.width,
+ .height = event.window_resized.height});
}
}
vgltf_renderer_triangle_pass(&renderer);
- renderer.current_frame =
- (renderer.current_frame + 1) % VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT;
}
out_main_loop:
vgltf_renderer_deinit(&renderer);
diff --git a/src/platform.h b/src/platform.h
index 2f8bc19..fe719d3 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -14,6 +14,7 @@
enum vgltf_event_type {
VGLTF_EVENT_QUIT,
VGLTF_EVENT_KEY_DOWN,
+ VGLTF_EVENT_WINDOW_RESIZED,
VGLTF_EVENT_UNKNOWN,
};
@@ -52,10 +53,16 @@ struct vgltf_key_event {
enum vgltf_key key;
};
+struct vgltf_window_resized_event {
+ int32_t width;
+ int32_t height;
+};
+
struct vgltf_event {
enum vgltf_event_type type;
union {
struct vgltf_key_event key;
+ struct vgltf_window_resized_event window_resized;
};
};
diff --git a/src/platform_sdl.c b/src/platform_sdl.c
index 281ccb5..5cc6032 100644
--- a/src/platform_sdl.c
+++ b/src/platform_sdl.c
@@ -12,8 +12,9 @@ bool vgltf_platform_init(struct vgltf_platform *platform) {
constexpr char WINDOW_TITLE[] = "VisibleGLTF";
constexpr int WINDOW_WIDTH = 800;
constexpr int WINDOW_HEIGHT = 600;
- SDL_Window *window = SDL_CreateWindow(WINDOW_TITLE, WINDOW_WIDTH,
- WINDOW_HEIGHT, SDL_WINDOW_VULKAN);
+ SDL_Window *window =
+ SDL_CreateWindow(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT,
+ SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
if (!window) {
VGLTF_LOG_ERR("SDL window creation failed: %s", SDL_GetError());
goto quit_sdl;
@@ -105,6 +106,11 @@ bool vgltf_platform_poll_event(struct vgltf_platform *platform,
event->type = VGLTF_EVENT_KEY_DOWN;
event->key.key = vgltf_key_from_sdl_keycode(sdl_event.key.key);
break;
+ case SDL_EVENT_WINDOW_RESIZED:
+ event->type = VGLTF_EVENT_WINDOW_RESIZED;
+ event->window_resized.width = sdl_event.display.data1;
+ event->window_resized.height = sdl_event.display.data2;
+ break;
default:
event->type = VGLTF_EVENT_UNKNOWN;
break;
diff --git a/src/renderer.c b/src/renderer.c
index d95cf99..7022af6 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -734,9 +734,7 @@ choose_swapchain_extent(const VkSurfaceCapabilitiesKHR *capabilities, int width,
}
}
-static bool vgltf_renderer_create_swapchain(struct vgltf_renderer *renderer,
- int window_width_px,
- int window_height_px) {
+static bool vgltf_renderer_create_swapchain(struct vgltf_renderer *renderer) {
struct swapchain_support_details swapchain_support_details = {};
swapchain_support_details_query_from_device(
&swapchain_support_details, renderer->physical_device, renderer->surface);
@@ -748,9 +746,9 @@ static bool vgltf_renderer_create_swapchain(struct vgltf_renderer *renderer,
swapchain_support_details.present_modes,
swapchain_support_details.present_mode_count);
- VkExtent2D extent =
- choose_swapchain_extent(&swapchain_support_details.capabilities,
- window_width_px, window_height_px);
+ VkExtent2D extent = choose_swapchain_extent(
+ &swapchain_support_details.capabilities, renderer->window_size.width,
+ renderer->window_size.height);
uint32_t image_count =
swapchain_support_details.capabilities.minImageCount + 1;
if (swapchain_support_details.capabilities.maxImageCount > 0 &&
@@ -1181,18 +1179,59 @@ err:
return false;
}
+static void vgltf_renderer_cleanup_swapchain(struct vgltf_renderer *renderer) {
+ for (uint32_t framebuffer_index = 0;
+ framebuffer_index < renderer->swapchain_image_count;
+ framebuffer_index++) {
+ vkDestroyFramebuffer(renderer->device,
+ renderer->swapchain_framebuffers[framebuffer_index],
+ nullptr);
+ }
+
+ for (uint32_t image_view_index = 0;
+ image_view_index < renderer->swapchain_image_count; image_view_index++) {
+ vkDestroyImageView(renderer->device,
+ renderer->swapchain_image_views[image_view_index],
+ nullptr);
+ }
+
+ vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr);
+}
+
+static bool vgltf_renderer_recreate_swapchain(struct vgltf_renderer *renderer) {
+ vkDeviceWaitIdle(renderer->device);
+ vgltf_renderer_cleanup_swapchain(renderer);
+
+ // TODO add error handling
+ vgltf_renderer_create_swapchain(renderer);
+ vgltf_renderer_create_image_views(renderer);
+ vgltf_renderer_create_framebuffers(renderer);
+ return true;
+}
+
bool vgltf_renderer_triangle_pass(struct vgltf_renderer *renderer) {
vkWaitForFences(renderer->device, 1,
&renderer->in_flight_fences[renderer->current_frame], VK_TRUE,
UINT64_MAX);
- vkResetFences(renderer->device, 1,
- &renderer->in_flight_fences[renderer->current_frame]);
uint32_t image_index;
- vkAcquireNextImageKHR(
+ VkResult acquire_swapchain_image_result = vkAcquireNextImageKHR(
renderer->device, renderer->swapchain, UINT64_MAX,
renderer->image_available_semaphores[renderer->current_frame],
VK_NULL_HANDLE, &image_index);
+ if (acquire_swapchain_image_result == VK_ERROR_OUT_OF_DATE_KHR ||
+ acquire_swapchain_image_result == VK_SUBOPTIMAL_KHR ||
+ renderer->framebuffer_resized) {
+ renderer->framebuffer_resized = false;
+ vgltf_renderer_recreate_swapchain(renderer);
+ return true;
+ } else if (acquire_swapchain_image_result != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Failed to acquire a swapchain image");
+ goto err;
+ }
+
+ vkResetFences(renderer->device, 1,
+ &renderer->in_flight_fences[renderer->current_frame]);
vkResetCommandBuffer(renderer->command_buffer[renderer->current_frame], 0);
VkCommandBufferBeginInfo begin_info = {
@@ -1277,7 +1316,15 @@ bool vgltf_renderer_triangle_pass(struct vgltf_renderer *renderer) {
present_info.swapchainCount = 1;
present_info.pSwapchains = swapchains;
present_info.pImageIndices = &image_index;
- vkQueuePresentKHR(renderer->present_queue, &present_info);
+ VkResult result = vkQueuePresentKHR(renderer->present_queue, &present_info);
+ if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
+ vgltf_renderer_recreate_swapchain(renderer);
+ } else if (acquire_swapchain_image_result != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Failed to acquire a swapchain image");
+ goto err;
+ }
+ renderer->current_frame =
+ (renderer->current_frame + 1) % VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT;
return true;
err:
return false;
@@ -1308,9 +1355,9 @@ bool vgltf_renderer_init(struct vgltf_renderer *renderer,
VGLTF_LOG_ERR("Couldn't get window size");
goto destroy_device;
}
+ renderer->window_size = window_size;
- if (!vgltf_renderer_create_swapchain(renderer, window_size.width,
- window_size.height)) {
+ if (!vgltf_renderer_create_swapchain(renderer)) {
VGLTF_LOG_ERR("Couldn't create swapchain");
goto destroy_device;
}
@@ -1392,6 +1439,10 @@ err:
}
void vgltf_renderer_deinit(struct vgltf_renderer *renderer) {
vkDeviceWaitIdle(renderer->device);
+ vgltf_renderer_cleanup_swapchain(renderer);
+ vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr);
+ vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr);
+ vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr);
for (int i = 0; i < VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT; i++) {
vkDestroySemaphore(renderer->device,
renderer->image_available_semaphores[i], nullptr);
@@ -1400,29 +1451,20 @@ void vgltf_renderer_deinit(struct vgltf_renderer *renderer) {
vkDestroyFence(renderer->device, renderer->in_flight_fences[i], nullptr);
}
vkDestroyCommandPool(renderer->device, renderer->command_pool, nullptr);
- for (uint32_t swapchain_framebuffer_index = 0;
- swapchain_framebuffer_index < renderer->swapchain_image_count;
- swapchain_framebuffer_index++) {
- vkDestroyFramebuffer(
- renderer->device,
- renderer->swapchain_framebuffers[swapchain_framebuffer_index], nullptr);
- }
- vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr);
- vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr);
- vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr);
- for (uint32_t swapchain_image_view_index = 0;
- swapchain_image_view_index < renderer->swapchain_image_count;
- swapchain_image_view_index++) {
- vkDestroyImageView(
- renderer->device,
- renderer->swapchain_image_views[swapchain_image_view_index], nullptr);
- }
- vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr);
vkDestroyDevice(renderer->device, nullptr);
- vkDestroySurfaceKHR(renderer->instance, renderer->surface, nullptr);
if (enable_validation_layers) {
destroy_debug_utils_messenger_ext(renderer->instance,
renderer->debug_messenger, nullptr);
}
+ vkDestroySurfaceKHR(renderer->instance, renderer->surface, nullptr);
vkDestroyInstance(renderer->instance, nullptr);
}
+void vgltf_renderer_on_window_resized(struct vgltf_renderer *renderer,
+ struct vgltf_window_size size) {
+ if (size.width > 0 && size.height > 0 &&
+ size.width != renderer->window_size.width &&
+ size.height != renderer->window_size.height) {
+ renderer->window_size = size;
+ renderer->framebuffer_resized = true;
+ }
+}
diff --git a/src/renderer.h b/src/renderer.h
index 17897b6..a0417aa 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -32,10 +32,14 @@ struct vgltf_renderer {
VkSemaphore
render_finished_semaphores[VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT];
VkFence in_flight_fences[VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT];
+ struct vgltf_window_size window_size;
uint32_t current_frame;
+ bool framebuffer_resized;
};
bool vgltf_renderer_init(struct vgltf_renderer *renderer,
struct vgltf_platform *platform);
void vgltf_renderer_deinit(struct vgltf_renderer *renderer);
bool vgltf_renderer_triangle_pass(struct vgltf_renderer *renderer);
+void vgltf_renderer_on_window_resized(struct vgltf_renderer *renderer,
+ struct vgltf_window_size size);
#endif // VGLTF_RENDERER_H
Go back to lisible.xyz