|
|
|
@@ -12,8 +12,10 @@ const uint32_t kWidth = 256; |
|
|
|
const uint32_t kHeight = 256; |
|
|
|
const VkFormat kVulkanFormat = VK_FORMAT_A8B8G8R8_UNORM_PACK32; |
|
|
|
const VkFormat kVulkanDepthFormat = VK_FORMAT_D32_SFLOAT; |
|
|
|
const std::string kVertexShaderPath = "subpass.vert.spv"; |
|
|
|
const std::string kFragmentShaderPath = "subpass.frag.spv"; |
|
|
|
const std::string kDrawVertexShaderPath = "draw.vert.spv"; |
|
|
|
const std::string kDrawFragmentShaderPath = "draw.frag.spv"; |
|
|
|
const std::string kDarkenVertexShaderPath = "darken.vert.spv"; |
|
|
|
const std::string kDarkenFragmentShaderPath = "darken.frag.spv"; |
|
|
|
|
|
|
|
#define ERROR(message) \ |
|
|
|
std::cerr << message << std::endl; \ |
|
|
|
@@ -118,6 +120,34 @@ VkDevice CreateVkDevice(VkPhysicalDevice physical_device, uint32_t device_queue_ |
|
|
|
return device; |
|
|
|
} |
|
|
|
|
|
|
|
VkDescriptorPool CreateAttachmentVkDescriptorPool(VkDevice device) { |
|
|
|
VkDescriptorPoolSize pool_size = {}; |
|
|
|
pool_size.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; |
|
|
|
pool_size.descriptorCount = 1; |
|
|
|
|
|
|
|
VkDescriptorPoolCreateInfo pool_create_info = {}; |
|
|
|
pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |
|
|
|
pool_create_info.poolSizeCount = 1; |
|
|
|
pool_create_info.pPoolSizes = &pool_size; |
|
|
|
pool_create_info.maxSets = 1; |
|
|
|
|
|
|
|
VkDescriptorPool pool; |
|
|
|
VkResult result = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &pool); |
|
|
|
if (result != VK_SUCCESS) { |
|
|
|
ERROR("Unable to create descriptor pool: " << result); |
|
|
|
} |
|
|
|
return pool; |
|
|
|
} |
|
|
|
|
|
|
|
VkDescriptorSet CreateAttachmentVkDescriptorSet(VkDevice device, VkDescriptorPool pool) { |
|
|
|
std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout); |
|
|
|
VkDescriptorSetAllocateInfo allocInfo = {}; |
|
|
|
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; |
|
|
|
allocInfo.descriptorPool = descriptorPool; |
|
|
|
allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size()); |
|
|
|
allocInfo.pSetLayouts = layouts.data(); |
|
|
|
} |
|
|
|
|
|
|
|
VkQueue GetVkQueue(VkDevice device, uint32_t device_queue_family_index) { |
|
|
|
VkQueue queue; |
|
|
|
vkGetDeviceQueue(device, device_queue_family_index, /*queueIndex*/ 0, &queue); |
|
|
|
@@ -183,29 +213,50 @@ VkRenderPass CreateVkRenderPass(VkDevice device) { |
|
|
|
depth_attachment_reference.attachment = 1; |
|
|
|
depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
|
|
|
|
|
|
|
VkSubpassDescription subpass_description = {}; |
|
|
|
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
|
|
|
subpass_description.colorAttachmentCount = 1; |
|
|
|
subpass_description.pColorAttachments = &color_attachment_reference; |
|
|
|
subpass_description.pDepthStencilAttachment = &depth_attachment_reference; |
|
|
|
|
|
|
|
VkSubpassDependency subpass_dependency = {}; |
|
|
|
subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL; |
|
|
|
subpass_dependency.dstSubpass = 0; |
|
|
|
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
|
|
|
subpass_dependency.srcAccessMask = 0; |
|
|
|
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
|
|
|
subpass_dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | |
|
|
|
std::array<VkSubpassDescription, 2> subpass_descriptions = {}; |
|
|
|
VkSubpassDescription* draw_subpass_description = &subpass_descriptions[0]; |
|
|
|
draw_subpass_description->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
|
|
|
draw_subpass_description->colorAttachmentCount = 1; |
|
|
|
draw_subpass_description->pColorAttachments = &color_attachment_reference; |
|
|
|
draw_subpass_description->pDepthStencilAttachment = &depth_attachment_reference; |
|
|
|
|
|
|
|
VkSubpassDescription* darken_subpass_description = &subpass_descriptions[1]; |
|
|
|
darken_subpass_description->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
|
|
|
darken_subpass_description->colorAttachmentCount = 1; |
|
|
|
darken_subpass_description->pColorAttachments = &color_attachment_reference; |
|
|
|
darken_subpass_description->pDepthStencilAttachment = &depth_attachment_reference; |
|
|
|
darken_subpass_description->inputAttachmentCount = 1; |
|
|
|
darken_subpass_description->pInputAttachments = &color_attachment_reference; |
|
|
|
|
|
|
|
std::array<VkSubpassDependency, 2> subpass_dependencies = {}; |
|
|
|
VkSubpassDependency* color_subpass_dependency = &subpass_dependencies[0]; |
|
|
|
color_subpass_dependency->srcSubpass = VK_SUBPASS_EXTERNAL; |
|
|
|
color_subpass_dependency->dstSubpass = 0; |
|
|
|
color_subpass_dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
|
|
|
color_subpass_dependency->dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
|
|
|
color_subpass_dependency->srcAccessMask = 0; |
|
|
|
color_subpass_dependency->dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | |
|
|
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
|
|
|
color_subpass_dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; |
|
|
|
|
|
|
|
VkSubpassDependency* darken_subpass_dependency = &subpass_dependencies[1]; |
|
|
|
darken_subpass_dependency->srcSubpass = 0; |
|
|
|
darken_subpass_dependency->dstSubpass = 1; |
|
|
|
darken_subpass_dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
|
|
|
darken_subpass_dependency->dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; |
|
|
|
darken_subpass_dependency->srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
|
|
|
darken_subpass_dependency->dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | |
|
|
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
|
|
|
darken_subpass_dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; |
|
|
|
|
|
|
|
VkRenderPassCreateInfo render_pass_info = {}; |
|
|
|
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; |
|
|
|
render_pass_info.attachmentCount = attachment_descriptions.size(); |
|
|
|
render_pass_info.pAttachments = attachment_descriptions.data(); |
|
|
|
render_pass_info.subpassCount = 1; |
|
|
|
render_pass_info.pSubpasses = &subpass_description; |
|
|
|
render_pass_info.dependencyCount = 1; |
|
|
|
render_pass_info.pDependencies = &subpass_dependency; |
|
|
|
render_pass_info.subpassCount = subpass_descriptions.size(); |
|
|
|
render_pass_info.pSubpasses = subpass_descriptions.data(); |
|
|
|
render_pass_info.dependencyCount = subpass_dependencies.size(); |
|
|
|
render_pass_info.pDependencies = subpass_dependencies.data(); |
|
|
|
|
|
|
|
VkRenderPass render_pass; |
|
|
|
VkResult result = vkCreateRenderPass(device, &render_pass_info, nullptr, &render_pass); |
|
|
|
@@ -237,10 +288,8 @@ VkShaderModule CreateVkShaderModule(VkDevice device, std::string path) { |
|
|
|
return shader_module; |
|
|
|
} |
|
|
|
|
|
|
|
VkPipeline CreateVkPipeline(VkDevice device, VkRenderPass render_pass) { |
|
|
|
VkShaderModule vertex_shader_module = CreateVkShaderModule(device, kVertexShaderPath); |
|
|
|
VkShaderModule fragment_shader_module = CreateVkShaderModule(device, kFragmentShaderPath); |
|
|
|
|
|
|
|
VkPipeline CreateVkPipeline(VkDevice device, VkShaderModule vertex_shader_module, |
|
|
|
VkShaderModule fragment_shader_module, VkRenderPass render_pass, uint32_t subpass) { |
|
|
|
VkPipelineShaderStageCreateInfo vertex_shader_stage_info = {}; |
|
|
|
vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
|
|
|
vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; |
|
|
|
@@ -351,7 +400,7 @@ VkPipeline CreateVkPipeline(VkDevice device, VkRenderPass render_pass) { |
|
|
|
pipeline_create_info.pDynamicState = nullptr; |
|
|
|
pipeline_create_info.layout = pipeline_layout; |
|
|
|
pipeline_create_info.renderPass = render_pass; |
|
|
|
pipeline_create_info.subpass = 0; |
|
|
|
pipeline_create_info.subpass = subpass; |
|
|
|
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; |
|
|
|
pipeline_create_info.basePipelineIndex = -1; |
|
|
|
|
|
|
|
@@ -560,8 +609,8 @@ void WaitForIdle(VkQueue queue) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void Draw(VkDevice device, VkQueue queue, VkRenderPass render_pass, VkPipeline pipeline, |
|
|
|
VkFramebuffer framebuffer, VkCommandBuffer command_buffer) { |
|
|
|
void Draw(VkDevice device, VkQueue queue, VkRenderPass render_pass, VkPipeline draw_pipeline, |
|
|
|
VkPipeline darken_pipeline, VkFramebuffer framebuffer, VkCommandBuffer command_buffer) { |
|
|
|
BeginCommandBuffer(command_buffer); |
|
|
|
VkRenderPassBeginInfo render_pass_begin_info = {}; |
|
|
|
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |
|
|
|
@@ -584,9 +633,14 @@ void Draw(VkDevice device, VkQueue queue, VkRenderPass render_pass, VkPipeline p |
|
|
|
render_pass_begin_info.pClearValues = clear_values.data(); |
|
|
|
vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); |
|
|
|
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); |
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, draw_pipeline); |
|
|
|
vkCmdDraw(command_buffer, 3, 1, 0, 0); |
|
|
|
vkCmdDraw(command_buffer, 3, 1, 3, 0); |
|
|
|
|
|
|
|
vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); |
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, darken_pipeline); |
|
|
|
vkCmdDraw(command_buffer, 6, 1, 0, 0); |
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -671,12 +725,24 @@ int main() { |
|
|
|
VkPhysicalDevice physical_device = ChooseVkPhysicalDevice(instance); |
|
|
|
uint32_t device_queue_family_index = ChooseDeviceQueueFamilyIndex(physical_device); |
|
|
|
VkDevice device = CreateVkDevice(physical_device, device_queue_family_index); |
|
|
|
VkDescriptorPool descriptor_pool = CreateAttachmentVkDescriptorPool(device); |
|
|
|
VkQueue queue = GetVkQueue(device, device_queue_family_index); |
|
|
|
VkCommandPool command_pool = CreateVkCommandPool(device, device_queue_family_index); |
|
|
|
VkCommandBuffer command_buffer = CreateVkCommandBuffer(device, command_pool); |
|
|
|
|
|
|
|
VkRenderPass render_pass = CreateVkRenderPass(device); |
|
|
|
VkPipeline pipeline = CreateVkPipeline(device, render_pass); |
|
|
|
VkShaderModule draw_vertex_shader_module = |
|
|
|
CreateVkShaderModule(device, kDrawVertexShaderPath); |
|
|
|
VkShaderModule draw_fragment_shader_module = |
|
|
|
CreateVkShaderModule(device, kDrawFragmentShaderPath); |
|
|
|
VkPipeline draw_pipeline = CreateVkPipeline(device, draw_vertex_shader_module, |
|
|
|
draw_fragment_shader_module, render_pass, 0 /* subpass */); |
|
|
|
VkShaderModule darken_vertex_shader_module = |
|
|
|
CreateVkShaderModule(device, kDarkenVertexShaderPath); |
|
|
|
VkShaderModule darken_fragment_shader_module = |
|
|
|
CreateVkShaderModule(device, kDarkenFragmentShaderPath); |
|
|
|
VkPipeline darken_pipeline = CreateVkPipeline(device, darken_vertex_shader_module, |
|
|
|
darken_fragment_shader_module, render_pass, 1 /* subpass */); |
|
|
|
|
|
|
|
VkImage render_image = CreateRenderVkImage(device); |
|
|
|
AllocateAndBindRenderMemory(physical_device, device, render_image); |
|
|
|
@@ -691,7 +757,7 @@ int main() { |
|
|
|
VkDeviceMemory scanout_image_memory = |
|
|
|
AllocateAndBindScanoutMemory(physical_device, device, scanout_image); |
|
|
|
|
|
|
|
Draw(device, queue, render_pass, pipeline, framebuffer, command_buffer); |
|
|
|
Draw(device, queue, render_pass, draw_pipeline, darken_pipeline, framebuffer, command_buffer); |
|
|
|
// Since the render target is created with VK_IMAGE_TILING_OPTIMAL, we need to copy it to a linear |
|
|
|
// format before scanning out. |
|
|
|
BlitToScanoutImage(queue, command_buffer, render_image, scanout_image); |