|  |  |  | @ -8,14 +8,17 @@ | 
		
	
		
			
				|  |  |  |  |  * - ui_context->containers[*].layers[*].address <- device address | 
		
	
		
			
				|  |  |  |  |  * Basically, needs to be re-run whenever the number of layers/containers changes | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |   VkDeviceAddress push[2] = {ui_context->address, 0}; | 
		
	
		
			
				|  |  |  |  | void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context, double time) { | 
		
	
		
			
				|  |  |  |  |   UIPushConstant push = { | 
		
	
		
			
				|  |  |  |  |     .time = (float)time, | 
		
	
		
			
				|  |  |  |  |     .layer = 0, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline); | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < ui_context->max_containers; i++) { | 
		
	
		
			
				|  |  |  |  |     if(ui_context->containers[i].id != 0x00000000) { | 
		
	
		
			
				|  |  |  |  |       for(uint32_t j = 0; j < ui_context->containers[i].layer_count; j++) { | 
		
	
		
			
				|  |  |  |  |         push[1] = ui_context->containers[i].layers[j].address; | 
		
	
		
			
				|  |  |  |  |         push.layer = ui_context->containers[i].layers[j].address; | 
		
	
		
			
				|  |  |  |  |         VkBufferMemoryBarrier draw_command_barrier_1 = { | 
		
	
		
			
				|  |  |  |  |           .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | 
		
	
		
			
				|  |  |  |  |           .buffer = ui_context->containers[i].layers[j].layer, | 
		
	
	
		
			
				
					|  |  |  | @ -35,7 +38,7 @@ void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |           .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | 
		
	
		
			
				|  |  |  |  |         }; | 
		
	
		
			
				|  |  |  |  |         vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 1, &draw_command_barrier_2, 0, NULL); | 
		
	
		
			
				|  |  |  |  |         vkCmdPushConstants(command_buffer, ui_context->string_pipeline.layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, push); | 
		
	
		
			
				|  |  |  |  |         vkCmdPushConstants(command_buffer, ui_context->string_pipeline.layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, &push); | 
		
	
		
			
				|  |  |  |  |         vkCmdDispatchIndirect(command_buffer, ui_context->containers[i].layers[j].layer, offsetof(GPULayer, dispatch_strings)); | 
		
	
		
			
				|  |  |  |  |         VkBufferMemoryBarrier draw_command_barrier_3 = { | 
		
	
		
			
				|  |  |  |  |           .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | 
		
	
	
		
			
				
					|  |  |  | @ -68,8 +71,11 @@ void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |  * - ui_context->containers[*].layers[*].address <- device address | 
		
	
		
			
				|  |  |  |  |  * Basically, needs to be re-run whenever the number of layers/containers changes | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |   VkDeviceAddress push[2] = {ui_context->address, 0}; | 
		
	
		
			
				|  |  |  |  | void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context, double time) { | 
		
	
		
			
				|  |  |  |  |   UIPushConstant push = { | 
		
	
		
			
				|  |  |  |  |     .time = (float)time, | 
		
	
		
			
				|  |  |  |  |     .layer = 0, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline); | 
		
	
		
			
				|  |  |  |  |   vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); | 
		
	
	
		
			
				
					|  |  |  | @ -79,71 +85,18 @@ void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < ui_context->max_containers; i++) { | 
		
	
		
			
				|  |  |  |  |     if(ui_context->containers[i].id != 0x00000000) { | 
		
	
		
			
				|  |  |  |  |       for(uint32_t j = 0; j < ui_context->containers[i].layer_count; j++) { | 
		
	
		
			
				|  |  |  |  |         push[1] = ui_context->containers[i].layers[j].address; | 
		
	
		
			
				|  |  |  |  |         vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push); | 
		
	
		
			
				|  |  |  |  |         push.layer = ui_context->containers[i].layers[j].address; | 
		
	
		
			
				|  |  |  |  |         vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, &push); | 
		
	
		
			
				|  |  |  |  |         vkCmdDrawIndirect(command_buffer, ui_context->containers[i].layers[j].layer, offsetof(GPULayer, draw), 1, 0); | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult record_draw_commands( | 
		
	
		
			
				|  |  |  |  |     RenderContext* context, | 
		
	
		
			
				|  |  |  |  |     UIContext* ui_context) { | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |   for(uint32_t image_index = 0; image_index < context->swapchain_image_count; image_index++) { | 
		
	
		
			
				|  |  |  |  |     VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index]; | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(vkResetCommandBuffer(command_buffer, 0)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkCommandBufferBeginInfo begin_info = { | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 
		
	
		
			
				|  |  |  |  |     };  | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(vkBeginCommandBuffer(command_buffer, &begin_info)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkViewport viewport = { | 
		
	
		
			
				|  |  |  |  |       .width = context->swapchain_extent.width, | 
		
	
		
			
				|  |  |  |  |       .height = context->swapchain_extent.height, | 
		
	
		
			
				|  |  |  |  |       .maxDepth = 1.0f, | 
		
	
		
			
				|  |  |  |  |       .minDepth = 0.0f, | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |     vkCmdSetViewport(command_buffer, 0, 1, &viewport); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkRect2D scissor = { | 
		
	
		
			
				|  |  |  |  |       .extent = context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |     vkCmdSetScissor(command_buffer, 0, 1, &scissor); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 0.0f}}}, {.depthStencil={1.0f, 0.0f}}}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkRenderPassBeginInfo render_pass_begin = { | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | 
		
	
		
			
				|  |  |  |  |       .renderPass = context->render_pass, | 
		
	
		
			
				|  |  |  |  |       .framebuffer = context->swapchain_framebuffers[image_index], | 
		
	
		
			
				|  |  |  |  |       .renderArea.offset = {0, 0}, | 
		
	
		
			
				|  |  |  |  |       .renderArea.extent = context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |       .clearValueCount = 2, | 
		
	
		
			
				|  |  |  |  |       .pClearValues = clear_values, | 
		
	
		
			
				|  |  |  |  |     };  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     record_ui_compute(command_buffer, ui_context); | 
		
	
		
			
				|  |  |  |  |     vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); | 
		
	
		
			
				|  |  |  |  |     // Render World
 | 
		
	
		
			
				|  |  |  |  |     vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); | 
		
	
		
			
				|  |  |  |  |     // Render UI
 | 
		
	
		
			
				|  |  |  |  |     record_ui_draw(command_buffer, ui_context); | 
		
	
		
			
				|  |  |  |  |     vkCmdEndRenderPass(command_buffer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(vkEndCommandBuffer(command_buffer)); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult draw_frame( | 
		
	
		
			
				|  |  |  |  |     RenderContext* context, | 
		
	
		
			
				|  |  |  |  |     UIContext* ui, | 
		
	
		
			
				|  |  |  |  |     double time) { | 
		
	
		
			
				|  |  |  |  |   (void)time; | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); | 
		
	
	
		
			
				
					|  |  |  | @ -162,6 +115,50 @@ VkResult draw_frame( | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index]; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkResetCommandBuffer(command_buffer, 0)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkCommandBufferBeginInfo begin_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 
		
	
		
			
				|  |  |  |  |   };  | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkBeginCommandBuffer(command_buffer, &begin_info)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkViewport viewport = { | 
		
	
		
			
				|  |  |  |  |     .width = context->swapchain_extent.width, | 
		
	
		
			
				|  |  |  |  |     .height = context->swapchain_extent.height, | 
		
	
		
			
				|  |  |  |  |     .maxDepth = 1.0f, | 
		
	
		
			
				|  |  |  |  |     .minDepth = 0.0f, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   vkCmdSetViewport(command_buffer, 0, 1, &viewport); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkRect2D scissor = { | 
		
	
		
			
				|  |  |  |  |     .extent = context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   vkCmdSetScissor(command_buffer, 0, 1, &scissor); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 0.0f}}}, {.depthStencil={1.0f, 0.0f}}}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkRenderPassBeginInfo render_pass_begin = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | 
		
	
		
			
				|  |  |  |  |     .renderPass = context->render_pass, | 
		
	
		
			
				|  |  |  |  |     .framebuffer = context->swapchain_framebuffers[image_index], | 
		
	
		
			
				|  |  |  |  |     .renderArea.offset = {0, 0}, | 
		
	
		
			
				|  |  |  |  |     .renderArea.extent = context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |     .clearValueCount = 2, | 
		
	
		
			
				|  |  |  |  |     .pClearValues = clear_values, | 
		
	
		
			
				|  |  |  |  |   };  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   record_ui_compute(command_buffer, ui, time); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); | 
		
	
		
			
				|  |  |  |  |   // Render World
 | 
		
	
		
			
				|  |  |  |  |   vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); | 
		
	
		
			
				|  |  |  |  |   // Render UI
 | 
		
	
		
			
				|  |  |  |  |   record_ui_draw(command_buffer, ui, time); | 
		
	
		
			
				|  |  |  |  |   vkCmdEndRenderPass(command_buffer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkEndCommandBuffer(command_buffer)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; | 
		
	
		
			
				|  |  |  |  |   VkSubmitInfo submit_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, | 
		
	
	
		
			
				
					|  |  |  | 
 |