Pass RenderContext pointer in exposed API functions
							parent
							
								
									d4790a8d53
								
							
						
					
					
						commit
						1dbd924b8c
					
				| @ -0,0 +1,13 @@ | ||||
| #ifndef RENDER_H | ||||
| #define RENDER_H | ||||
| 
 | ||||
| #include "gpu.h" | ||||
| #include "ui.h" | ||||
| 
 | ||||
| VkResult draw_frame( | ||||
|     RenderContext* context, | ||||
|     UIContextStorage* ui_context, | ||||
|     UILayerStorage* ui_layers, | ||||
|     uint32_t ui_layer_count); | ||||
| 
 | ||||
| #endif | ||||
| @ -1,88 +0,0 @@ | ||||
| #include "command.h" | ||||
| 
 | ||||
| VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool) { | ||||
|   VkCommandBufferAllocateInfo command_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | ||||
|     .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, | ||||
|     .commandPool = transfer_pool, | ||||
|     .commandBufferCount = 1, | ||||
|   }; | ||||
| 
 | ||||
|   VkCommandBuffer command_buffer; | ||||
|   VkResult result = vkAllocateCommandBuffers(device, &command_info, &command_buffer); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return VK_NULL_HANDLE; | ||||
|   } | ||||
| 
 | ||||
|   VkCommandBufferBeginInfo begin_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||||
|     .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, | ||||
|   }; | ||||
| 
 | ||||
|   result = vkBeginCommandBuffer(command_buffer, &begin_info); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); | ||||
|     return VK_NULL_HANDLE; | ||||
|   } | ||||
| 
 | ||||
|   return command_buffer; | ||||
| } | ||||
| 
 | ||||
| VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue transfer_queue) { | ||||
|   VkResult result = vkEndCommandBuffer(command_buffer); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   VkSubmitInfo submit_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, | ||||
|     .commandBufferCount = 1, | ||||
|     .pCommandBuffers = &command_buffer, | ||||
|   }; | ||||
| 
 | ||||
|   result = vkQueueSubmit(transfer_queue.handle, 1, &submit_info, 0); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   result = vkQueueWaitIdle(transfer_queue.handle); | ||||
|   vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer dst, VkDeviceSize src_offset, VkDeviceSize dst_offset, VkDeviceSize size) { | ||||
|   VkBufferCopy copy = { | ||||
|     .srcOffset = src_offset, | ||||
|     .dstOffset = dst_offset, | ||||
|     .size = size, | ||||
|   }; | ||||
|   vkCmdCopyBuffer(command_buffer, src, dst, 1, ©); | ||||
| } | ||||
| 
 | ||||
| VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, Queue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags) { | ||||
|   VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); | ||||
| 
 | ||||
|   VkImageMemoryBarrier barrier = { | ||||
|     .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|     .oldLayout = old_layout, | ||||
|     .newLayout = new_layout, | ||||
|     .srcQueueFamilyIndex = source_family, | ||||
|     .dstQueueFamilyIndex = dest_family, | ||||
|     .image = image, | ||||
|     .subresourceRange = { | ||||
|       .aspectMask = aspect_flags, | ||||
|       .levelCount = 1, | ||||
|       .layerCount = 1, | ||||
|       .baseMipLevel = 0, | ||||
|       .baseArrayLayer = 0, | ||||
|     }, | ||||
|     .srcAccessMask = src_mask, | ||||
|     .dstAccessMask = dst_mask, | ||||
|   }; | ||||
|   vkCmdPipelineBarrier(command_buffer, source, dest, 0, 0, 0, 0, 0, 1, &barrier); | ||||
| 
 | ||||
|   return command_end_single(device, command_buffer, transfer_pool, transfer_queue); | ||||
| } | ||||
| 
 | ||||
| @ -0,0 +1,170 @@ | ||||
| #include "draw.h" | ||||
| 
 | ||||
| VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* layers, uint32_t layer_count) { | ||||
|   VkResult result; | ||||
| 
 | ||||
|   result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   result = vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   uint32_t image_index; | ||||
|   VkCommandBuffer command_buffer = context->swapchain_command_buffers[context->current_frame]; | ||||
|   result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, context->image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   result = vkResetCommandBuffer(command_buffer, 0); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   VkCommandBufferBeginInfo begin_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||||
|   };  | ||||
|   result = vkBeginCommandBuffer(command_buffer, &begin_info); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   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, | ||||
|   }; | ||||
| 
 | ||||
|   VkDeviceAddress push[2] = {ui_context->address, 0}; | ||||
|    | ||||
|   // Compute Pass
 | ||||
|   vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline); | ||||
|   for(uint32_t i = 0; i < layer_count; i++) { | ||||
|     push[1] = layers[i].address; | ||||
|     VkBufferMemoryBarrier draw_command_barrier_1 = { | ||||
|       .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | ||||
|       .buffer = layers[i].layer, | ||||
|       .offset = offsetof(UILayer, draw), | ||||
|       .size = sizeof(DrawCommand), | ||||
|       .srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, | ||||
|       .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|     }; | ||||
|     vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &draw_command_barrier_1, 0, NULL); | ||||
|     command_copy_buffer(command_buffer, layers[i].layer, layers[i].layer, offsetof(UILayer, num_drawables), offsetof(UILayer, draw) + offsetof(DrawCommand, instance_count), sizeof(uint32_t)); | ||||
|     VkBufferMemoryBarrier draw_command_barrier_2 = { | ||||
|       .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | ||||
|       .buffer = layers[i].layer, | ||||
|       .offset = offsetof(UILayer, draw), | ||||
|       .size = sizeof(DrawCommand), | ||||
|       .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|       .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); | ||||
|     vkCmdDispatchIndirect(command_buffer, layers[i].layer, offsetof(UILayer, dispatch_strings)); | ||||
|     VkBufferMemoryBarrier draw_command_barrier_3 = { | ||||
|       .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | ||||
|       .buffer = layers[i].layer, | ||||
|       .offset = offsetof(UILayer, draw), | ||||
|       .size = sizeof(DrawCommand), | ||||
|       .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||||
|       .dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, | ||||
|     }; | ||||
|     vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, 0, NULL, 1, &draw_command_barrier_3, 0, NULL); | ||||
| 
 | ||||
|     VkBufferMemoryBarrier drawables_barrier = { | ||||
|       .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, | ||||
|       .buffer = layers[i].drawables, | ||||
|       .offset = 0, | ||||
|       .size = sizeof(UIDrawable)*layers[i].data.max_drawables, | ||||
|       .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||||
|       .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, | ||||
|     }; | ||||
|     vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &drawables_barrier, 0, NULL); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   // Render Pass
 | ||||
|   vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); | ||||
|   // World subpass
 | ||||
|   vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); | ||||
|   // UI subpass
 | ||||
|   for(uint32_t i = 0; i < layer_count; i++) { | ||||
|     push[1] = layers[i].address; | ||||
|     vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push); | ||||
|     vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline); | ||||
|     if(i == 0) { | ||||
|       vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); | ||||
|       vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL); | ||||
|       vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 2, 1, &ui_context->samplers, 0, NULL); | ||||
|       vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 3, 1, &ui_context->textures, 0, NULL); | ||||
|     } | ||||
|     vkCmdDrawIndirect(command_buffer, layers[i].layer, offsetof(UILayer, draw), 1, 0); | ||||
|   } | ||||
| 
 | ||||
|   vkCmdEndRenderPass(command_buffer); | ||||
| 
 | ||||
|   result = vkEndCommandBuffer(command_buffer); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
|    | ||||
|   VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; | ||||
|   VkSubmitInfo submit_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, | ||||
|     .waitSemaphoreCount = 1, | ||||
|     .pWaitSemaphores = &context->image_available_semaphores[context->current_frame], | ||||
|     .pWaitDstStageMask = wait_stages, | ||||
|     .commandBufferCount = 1, | ||||
|     .pCommandBuffers = &command_buffer, | ||||
|     .signalSemaphoreCount = 1, | ||||
|     .pSignalSemaphores = &context->render_finished_semaphores[context->current_frame], | ||||
|   }; | ||||
| 
 | ||||
|   result = vkQueueSubmit(context->graphics_queue.handle, 1, &submit_info, context->in_flight_fences[context->current_frame]); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   VkPresentInfoKHR present_info = { | ||||
|     .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, | ||||
|     .waitSemaphoreCount = 1, | ||||
|     .pWaitSemaphores = &context->render_finished_semaphores[context->current_frame], | ||||
|     .swapchainCount = 1, | ||||
|     .pSwapchains = &context->swapchain, | ||||
|     .pImageIndices = &image_index, | ||||
|     .pResults = 0, | ||||
|   }; | ||||
| 
 | ||||
|   result = vkQueuePresentKHR(context->present_queue.handle, &present_info); | ||||
|   if(result != VK_SUCCESS) { | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   context->current_frame = (context->current_frame + 1) % MAX_FRAMES_IN_FLIGHT; | ||||
| 
 | ||||
|   return VK_SUCCESS; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue