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