Commit: 9011f7a3136ffa3d72c60471c500c459a7f2a65f
Parent: 7455a1e17c31ec3561c15ec2a86f8c861d0bd84b
Author: Randy Palamar
Date: Thu, 21 Aug 2025 15:49:53 -0600
core: don't crash on invalid shader reload
unfortunately vulkan doesn't have a 0 pipeline so some other way
of indicating that a shader is broken is needed
Diffstat:
M | common.c | | | 84 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 49 insertions(+), 35 deletions(-)
diff --git a/common.c b/common.c
@@ -262,16 +262,30 @@ vulkan_pipeline_from_shader_text(VulkanPipeline *vp, VkDevice device, OS *os, Ar
.subpass = 0,
};
- vkDestroyPipeline(device, vp->pipeline, 0);
-
if (valid) {
- vkCreateGraphicsPipelines(device, 0, 1, &pipeline_info, 0, &vp->pipeline);
+ /* TODO(rnp): have a set of default shaders for when compilation fails.
+ * Vulkan has no concept of a 0 shader which does nothing. Visual indication
+ * of brokeness is desirable for debugging */
+
+ /* NOTE(rnp): this could be fancier to avoid it but for now we are okay
+ * with a stall when shaders are reloading */
+ switch (vp->kind) {
+ case VulkanPipelineKind_Render:{
+ vkWaitForFences(device, countof(vp->render.command_buffer_fences),
+ vp->render.command_buffer_fences, 1, U64_MAX);
+ }break;
+ case VulkanPipelineKind_Compute:{
+ vkWaitForFences(device, countof(vp->compute.command_buffer_fences),
+ vp->compute.command_buffer_fences, 1, U64_MAX);
+ }break;
+ InvalidDefaultCase;
+ }
+ vkDestroyPipeline(device, vp->pipeline, 0);
+ vkCreateGraphicsPipelines(device, 0, 1, &pipeline_info, 0, &vp->pipeline);
Stream sb = arena_stream(arena);
stream_append_str8s(&sb, str8("loaded: "), name, str8("\n"));
os_write_file(os->error_handle, stream_to_str8(&sb));
- } else {
- vp->pipeline = 0;
}
for (s32 i = 0; i < count; i++)
@@ -756,6 +770,36 @@ init_viewer(ViewerContext *ctx)
surface_info.capabilities.currentTransform, image_count, &ctx->arena);
}
+ VkCommandPoolCreateInfo command_pool_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+ .queueFamilyIndex = queue_family_index,
+ };
+
+ vkCreateCommandPool(v->device, &command_pool_info, 0, &v->command_pool);
+
+ VkCommandBufferAllocateInfo command_buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandPool = v->command_pool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = countof(rp->render.command_buffers),
+ };
+ vkAllocateCommandBuffers(v->device, &command_buffer_info, rp->render.command_buffers);
+
+ VkSemaphoreCreateInfo semaphore_info = {.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ VkFenceCreateInfo fence_info = {
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ .flags = VK_FENCE_CREATE_SIGNALED_BIT,
+ };
+
+ for (u32 i = 0; i < sc->image_count; i++)
+ vkCreateSemaphore(v->device, &semaphore_info, 0, sc->render_complete_semaphores + i);
+
+ for EachElement(rp->render.command_buffer_fences, it) {
+ vkCreateSemaphore(v->device, &semaphore_info, 0, sc->image_available_semaphores + it);
+ vkCreateFence(v->device, &fence_info, 0, rp->render.command_buffer_fences + it);
+ }
+
ShaderReloadContext *render = push_struct(&ctx->arena, typeof(*render));
render->pipeline = rp;
render->device = v->device;
@@ -793,36 +837,6 @@ init_viewer(ViewerContext *ctx)
reload_shader(&ctx->os, render->path, (sptr)render, ctx->arena);
os_add_file_watch(&ctx->os, &ctx->arena, render->path, reload_shader, (sptr)render);
- VkCommandPoolCreateInfo command_pool_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
- .queueFamilyIndex = queue_family_index,
- };
-
- vkCreateCommandPool(v->device, &command_pool_info, 0, &v->command_pool);
-
- VkCommandBufferAllocateInfo command_buffer_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .commandPool = v->command_pool,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .commandBufferCount = countof(rp->render.command_buffers),
- };
- vkAllocateCommandBuffers(v->device, &command_buffer_info, rp->render.command_buffers);
-
- VkSemaphoreCreateInfo semaphore_info = {.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- VkFenceCreateInfo fence_info = {
- .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
- .flags = VK_FENCE_CREATE_SIGNALED_BIT,
- };
-
- for (u32 i = 0; i < sc->image_count; i++)
- vkCreateSemaphore(v->device, &semaphore_info, 0, sc->render_complete_semaphores + i);
-
- for EachElement(rp->render.command_buffer_fences, it) {
- vkCreateSemaphore(v->device, &semaphore_info, 0, sc->image_available_semaphores + it);
- vkCreateFence(v->device, &fence_info, 0, rp->render.command_buffer_fences + it);
- }
-
glfwSetWindowUserPointer(ctx->window, ctx);
glfwSetKeyCallback(ctx->window, key_callback);