void buildCommandBuffers() { VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; clearValues[0].color = defaultClearColor; clearValues[1].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); renderPassBeginInfo.renderPass = renderPass; renderPassBeginInfo.renderArea.offset.x = 0; renderPassBeginInfo.renderArea.offset.y = 0; renderPassBeginInfo.renderArea.extent.width = width; renderPassBeginInfo.renderArea.extent.height = height; renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = clearValues; VkResult err; for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { // Set target frame buffer renderPassBeginInfo.framebuffer = frameBuffers[i]; err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo); assert(!err); // The primary command buffer does not contain any rendering commands // These are stored (and retrieved) from the secondary command buffers vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); // Execute secondary command buffers for (auto& renderThread : renderThreads) { // todo : Make sure threads are finished before accessing their command buffers vkCmdExecuteCommands(drawCmdBuffers[i], 1, &renderThread.cmdBuffers[i]); } vkCmdEndRenderPass(drawCmdBuffers[i]); VkImageMemoryBarrier prePresentBarrier = vkTools::prePresentBarrier(swapChain.buffers[i].image); vkCmdPipelineBarrier( drawCmdBuffers[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_FLAGS_NONE, 0, nullptr, 0, nullptr, 1, &prePresentBarrier); err = vkEndCommandBuffer(drawCmdBuffers[i]); assert(!err); } }
int sample_main(int argc, char *argv[]) { VkResult U_ASSERT_ONLY res; struct sample_info info = {}; char sample_title[] = "Secondary command buffers"; const bool depthPresent = true; process_command_line_args(info, argc, argv); init_global_layer_properties(info); init_instance_extension_names(info); init_device_extension_names(info); init_instance(info, sample_title); init_enumerate_device(info); init_window_size(info, 500, 500); init_connection(info); init_window(info); init_swapchain_extension(info); init_device(info); init_command_pool(info); init_command_buffer(info); execute_begin_command_buffer(info); init_device_queue(info); init_swap_chain(info); init_depth_buffer(info); init_uniform_buffer(info); init_descriptor_and_pipeline_layouts(info, true); init_renderpass(info, depthPresent, true, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); init_shaders(info, vertShaderText, fragShaderText); init_framebuffers(info, depthPresent); init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true); init_pipeline_cache(info); init_pipeline(info, depthPresent); // we have to set up a couple of things by hand, but this // isn't any different to other examples // get two different textures init_texture(info, "green.ppm"); VkDescriptorImageInfo greenTex = info.texture_data.image_info; init_texture(info, "lunarg.ppm"); VkDescriptorImageInfo lunargTex = info.texture_data.image_info; // create two identical descriptor sets, each with a different texture but // identical UBOa VkDescriptorPoolSize pool_size[2]; pool_size[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; pool_size[0].descriptorCount = 2; pool_size[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; pool_size[1].descriptorCount = 2; VkDescriptorPoolCreateInfo descriptor_pool = {}; descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptor_pool.pNext = NULL; descriptor_pool.flags = 0; descriptor_pool.maxSets = 2; descriptor_pool.poolSizeCount = 2; descriptor_pool.pPoolSizes = pool_size; res = vkCreateDescriptorPool(info.device, &descriptor_pool, NULL, &info.desc_pool); assert(res == VK_SUCCESS); VkDescriptorSetLayout layouts[] = {info.desc_layout[0], info.desc_layout[0]}; VkDescriptorSetAllocateInfo alloc_info[1]; alloc_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info[0].pNext = NULL; alloc_info[0].descriptorPool = info.desc_pool; alloc_info[0].descriptorSetCount = 2; alloc_info[0].pSetLayouts = layouts; info.desc_set.resize(2); res = vkAllocateDescriptorSets(info.device, alloc_info, info.desc_set.data()); assert(res == VK_SUCCESS); VkWriteDescriptorSet writes[2]; writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[0].pNext = NULL; writes[0].dstSet = info.desc_set[0]; writes[0].descriptorCount = 1; writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; writes[0].pBufferInfo = &info.uniform_data.buffer_info; writes[0].dstArrayElement = 0; writes[0].dstBinding = 0; writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[1].pNext = NULL; writes[1].dstSet = info.desc_set[0]; writes[1].dstBinding = 1; writes[1].descriptorCount = 1; writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; writes[1].pImageInfo = &greenTex; writes[1].dstArrayElement = 0; vkUpdateDescriptorSets(info.device, 2, writes, 0, NULL); writes[0].dstSet = writes[1].dstSet = info.desc_set[1]; writes[1].pImageInfo = &lunargTex; vkUpdateDescriptorSets(info.device, 2, writes, 0, NULL); /* VULKAN_KEY_START */ // create four secondary command buffers, for each quadrant of the screen VkCommandBufferAllocateInfo cmdalloc = {}; cmdalloc.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; cmdalloc.pNext = NULL; cmdalloc.commandPool = info.cmd_pool; cmdalloc.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; cmdalloc.commandBufferCount = 4; VkCommandBuffer secondary_cmds[4]; res = vkAllocateCommandBuffers(info.device, &cmdalloc, secondary_cmds); assert(res == VK_SUCCESS); VkClearValue clear_values[2]; clear_values[0].color.float32[0] = 0.2f; clear_values[0].color.float32[1] = 0.2f; clear_values[0].color.float32[2] = 0.2f; clear_values[0].color.float32[3] = 0.2f; clear_values[1].depthStencil.depth = 1.0f; clear_values[1].depthStencil.stencil = 0; VkSemaphore imageAcquiredSemaphore; VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo; imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; imageAcquiredSemaphoreCreateInfo.pNext = NULL; imageAcquiredSemaphoreCreateInfo.flags = 0; res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo, NULL, &imageAcquiredSemaphore); assert(res == VK_SUCCESS); // Get the index of the next available swapchain image: res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &info.current_buffer); // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR // return codes assert(res == VK_SUCCESS); set_image_layout(info, info.buffers[info.current_buffer].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); const VkDeviceSize offsets[1] = {0}; VkViewport viewport; viewport.height = 200.0f; viewport.width = 200.0f; viewport.minDepth = (float)0.0f; viewport.maxDepth = (float)1.0f; viewport.x = 0; viewport.y = 0; VkRect2D scissor; scissor.extent.width = info.width; scissor.extent.height = info.height; scissor.offset.x = 0; scissor.offset.y = 0; // now we record four separate command buffers, one for each quadrant of the // screen VkCommandBufferInheritanceInfo cmd_buf_inheritance_info = {}; cmd_buf_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, cmd_buf_inheritance_info.pNext = NULL; cmd_buf_inheritance_info.renderPass = info.render_pass; cmd_buf_inheritance_info.subpass = 0; cmd_buf_inheritance_info.framebuffer = info.framebuffers[info.current_buffer]; cmd_buf_inheritance_info.occlusionQueryEnable = VK_FALSE; cmd_buf_inheritance_info.queryFlags = 0; cmd_buf_inheritance_info.pipelineStatistics = 0; VkCommandBufferBeginInfo secondary_begin = {}; secondary_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; secondary_begin.pNext = NULL; secondary_begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; secondary_begin.pInheritanceInfo = &cmd_buf_inheritance_info; for (int i = 0; i < 4; i++) { vkBeginCommandBuffer(secondary_cmds[i], &secondary_begin); vkCmdBindPipeline(secondary_cmds[i], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline); vkCmdBindDescriptorSets(secondary_cmds[i], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, 1, &info.desc_set[i == 0 || i == 3], 0, NULL); vkCmdBindVertexBuffers(secondary_cmds[i], 0, 1, &info.vertex_buffer.buf, offsets); viewport.x = 25.0f + 250.0f * (i % 2); viewport.y = 25.0f + 250.0f * (i / 2); vkCmdSetViewport(secondary_cmds[i], 0, NUM_VIEWPORTS, &viewport); vkCmdSetScissor(secondary_cmds[i], 0, NUM_SCISSORS, &scissor); vkCmdDraw(secondary_cmds[i], 12 * 3, 1, 0, 0); vkEndCommandBuffer(secondary_cmds[i]); } VkRenderPassBeginInfo rp_begin; rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_begin.pNext = NULL; rp_begin.renderPass = info.render_pass; rp_begin.framebuffer = info.framebuffers[info.current_buffer]; rp_begin.renderArea.offset.x = 0; rp_begin.renderArea.offset.y = 0; rp_begin.renderArea.extent.width = info.width; rp_begin.renderArea.extent.height = info.height; rp_begin.clearValueCount = 2; rp_begin.pClearValues = clear_values; // specifying VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS means this // render pass may // ONLY call vkCmdExecuteCommands vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); vkCmdExecuteCommands(info.cmd, 4, secondary_cmds); vkCmdEndRenderPass(info.cmd); VkImageMemoryBarrier prePresentBarrier = {}; prePresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; prePresentBarrier.pNext = NULL; prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; prePresentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; prePresentBarrier.subresourceRange.baseMipLevel = 0; prePresentBarrier.subresourceRange.levelCount = 1; prePresentBarrier.subresourceRange.baseArrayLayer = 0; prePresentBarrier.subresourceRange.layerCount = 1; prePresentBarrier.image = info.buffers[info.current_buffer].image; vkCmdPipelineBarrier(info.cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &prePresentBarrier); res = vkEndCommandBuffer(info.cmd); assert(res == VK_SUCCESS); const VkCommandBuffer cmd_bufs[] = {info.cmd}; VkFenceCreateInfo fenceInfo; VkFence drawFence; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.pNext = NULL; fenceInfo.flags = 0; vkCreateFence(info.device, &fenceInfo, NULL, &drawFence); VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submit_info[1] = {}; submit_info[0].pNext = NULL; submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info[0].waitSemaphoreCount = 1; submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore; submit_info[0].pWaitDstStageMask = &pipe_stage_flags; submit_info[0].commandBufferCount = 1; submit_info[0].pCommandBuffers = cmd_bufs; submit_info[0].signalSemaphoreCount = 0; submit_info[0].pSignalSemaphores = NULL; /* Queue the command buffer for execution */ res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence); assert(res == VK_SUCCESS); /* Now present the image in the window */ VkPresentInfoKHR present; present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present.pNext = NULL; present.swapchainCount = 1; present.pSwapchains = &info.swap_chain; present.pImageIndices = &info.current_buffer; present.pWaitSemaphores = NULL; present.waitSemaphoreCount = 0; present.pResults = NULL; /* Make sure command buffer is finished before presenting */ do { res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT); } while (res == VK_TIMEOUT); assert(res == VK_SUCCESS); res = vkQueuePresentKHR(info.present_queue, &present); assert(res == VK_SUCCESS); wait_seconds(1); if (info.save_images) write_ppm(info, "secondary_command_buffer"); vkFreeCommandBuffers(info.device, info.cmd_pool, 4, secondary_cmds); /* VULKAN_KEY_END */ vkDestroyFence(info.device, drawFence, NULL); vkDestroySemaphore(info.device, imageAcquiredSemaphore, NULL); destroy_pipeline(info); destroy_pipeline_cache(info); destroy_textures(info); destroy_descriptor_pool(info); destroy_vertex_buffer(info); destroy_framebuffers(info); destroy_shaders(info); destroy_renderpass(info); destroy_descriptor_and_pipeline_layouts(info); destroy_uniform_buffer(info); destroy_depth_buffer(info); destroy_swap_chain(info); destroy_command_buffer(info); destroy_command_pool(info); destroy_device(info); destroy_window(info); destroy_instance(info); return 0; }
void vkeGameRendererDynamic::generateDrawCommands(){ //Start generating draw commands. VulkanDC *dc = VulkanDC::Get(); VulkanDC::Device *device = dc->getDefaultDevice(); VkClearValue clearValues[3]; colorClearValues(&clearValues[0], 1.0, 1.0, 1.0); depthStencilClearValues(&clearValues[1]);//default# colorClearValues(&clearValues[2], 0.0, 0.0, 0.0); /* Dispatch threads to create the secondary command buffers. */ m_calls_generated = 0; for (uint32_t i = 0; i < m_max_draw_calls; ++i){ m_draw_calls[i]->initDrawCommands(m_node_data->count(), m_current_buffer_index); } /* Begin setting up the primary command buffer. */ VkCommandBufferBeginInfo cmdBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; VKA_CHECK_ERROR(vkResetCommandBuffer(m_primary_commands[m_current_buffer_index], 0),"Could not reset primary command buffer"); VKA_CHECK_ERROR(vkBeginCommandBuffer(m_primary_commands[m_current_buffer_index], &cmdBeginInfo), "Could not begin primary command buffer.\n"); uint32_t cnt = m_node_data->count(); VkDeviceSize sz = (sizeof(VkeNodeUniform) * cnt) + (m_instance_count * 64); vkCmdUpdateBuffer(m_primary_commands[m_current_buffer_index], m_uniforms_buffer, 0, sz, (const uint32_t *)m_uniforms_local); m_camera->updateCameraCmd(m_primary_commands[m_current_buffer_index]); renderPassBegin(&m_primary_commands[m_current_buffer_index], m_render_pass, m_framebuffers[m_current_buffer_index], 0, 0, m_width, m_height, clearValues, 3, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); VkViewport vp; VkRect2D sc; vp.x = 0; vp.y = 0; vp.height = (float)(m_height); vp.width = (float)(m_width); vp.minDepth = 0.0f; vp.maxDepth = 1.0f; sc.offset.x = 0; sc.offset.y = 0; sc.extent.width = vp.width; sc.extent.height = vp.height; vkCmdSetViewport(m_primary_commands[m_current_buffer_index], 0, 1, &vp); vkCmdSetScissor(m_primary_commands[m_current_buffer_index], 0, 1, &sc); /* Wait here until the secondary commands are ready. */ VkCommandBuffer secondaryCommands[11]; secondaryCommands[0] = m_terrain_command[m_current_buffer_index]; for (uint32_t i = 0; i < m_max_draw_calls; ++i){ secondaryCommands[i+1] = m_draw_calls[i]->getDrawCommand(m_current_buffer_index); } vkCmdExecuteCommands(m_primary_commands[m_current_buffer_index], 1+m_max_draw_calls, secondaryCommands); vkCmdEndRenderPass(m_primary_commands[m_current_buffer_index]); VkImageResolve blitInfo; blitInfo.srcOffset.x = 0; blitInfo.srcOffset.y = 0; blitInfo.srcOffset.z = 0; blitInfo.dstOffset.x = 0; blitInfo.dstOffset.y = 0; blitInfo.dstOffset.z = 0; blitInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blitInfo.srcSubresource.mipLevel = 0; blitInfo.srcSubresource.baseArrayLayer = 0; blitInfo.srcSubresource.layerCount = 1; blitInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blitInfo.dstSubresource.mipLevel = 0; blitInfo.dstSubresource.baseArrayLayer = 0; blitInfo.dstSubresource.layerCount = 1; blitInfo.extent.width = m_width; blitInfo.extent.height = m_height; blitInfo.extent.depth = 1; vkCmdResolveImage( m_primary_commands[m_current_buffer_index], m_color_attachment.image, VK_IMAGE_LAYOUT_GENERAL, m_resolve_attachment[m_current_buffer_index].image, VK_IMAGE_LAYOUT_GENERAL, 1, &blitInfo); VKA_CHECK_ERROR(vkEndCommandBuffer(m_primary_commands[m_current_buffer_index]), "Could not end command buffer for draw command.\n"); }
void vkeGameRendererDynamic::generateDrawCommands(){ //Start generating draw commands. VulkanDC *dc = VulkanDC::Get(); VulkanDC::Device *device = dc->getDefaultDevice(); VkClearValue clearValues[3]; /* Dispatch threads to create the secondary command buffers. */ m_calls_generated = 0; for (uint32_t i = 0; i < m_max_draw_calls; ++i){ m_draw_calls[i]->initDrawCommands(m_node_data->count(), m_current_buffer_index); } /* Begin setting up the primary command buffer. */ VkCommandBufferBeginInfo cmdBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; vkResetCommandBuffer(m_primary_commands[m_current_buffer_index], 0); vkResetCommandBuffer(m_update_commands[m_current_buffer_index], 0); VKA_CHECK_ERROR(vkBeginCommandBuffer(m_update_commands[m_current_buffer_index], &cmdBeginInfo), "Could not begin primary command buffer.\n"); VkBufferMemoryBarrier bufBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER }; bufBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; bufBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; bufBarrier.dstQueueFamilyIndex = 0; bufBarrier.offset = 0; bufBarrier.buffer = m_uniforms_buffer; bufBarrier.srcQueueFamilyIndex = 0; colorClearValues(&clearValues[0], 1.0, 1.0, 1.0); depthStencilClearValues(&clearValues[1]);//default# colorClearValues(&clearValues[2], 0.0, 0.0, 0.0); uint32_t sz = (sizeof(VkeNodeUniform) * 100) + (64 * 64); VkBufferCopy bufCopy; bufCopy.dstOffset = 0; bufCopy.srcOffset = 0; bufCopy.size = sz; vkCmdCopyBuffer(m_update_commands[m_current_buffer_index], m_uniforms_buffer_staging, m_uniforms_buffer, 1, &bufCopy); vkCmdPipelineBarrier( m_update_commands[m_current_buffer_index], VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &bufBarrier, 0, NULL); VKA_CHECK_ERROR(vkEndCommandBuffer(m_update_commands[m_current_buffer_index]), "Could not end command buffer for draw command.\n"); VKA_CHECK_ERROR(vkBeginCommandBuffer(m_primary_commands[m_current_buffer_index], &cmdBeginInfo), "Could not begin primary command buffer.\n"); renderPassBegin(&m_primary_commands[m_current_buffer_index], m_render_pass, m_framebuffers[m_current_buffer_index], 0, 0, m_width, m_height, clearValues, 3, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); VkViewport vp; VkRect2D sc; vp.x = 0; vp.y = 0; vp.height = (float)(m_height); vp.width = (float)(m_width); vp.minDepth = 0.0f; vp.maxDepth = 1.0f; sc.offset.x = 0; sc.offset.y = 0; sc.extent.width = vp.width; sc.extent.height = vp.height; vkCmdSetViewport(m_primary_commands[m_current_buffer_index], 0, 1, &vp); vkCmdSetScissor(m_primary_commands[m_current_buffer_index], 0, 1, &sc); /* Wait here until the secondary commands are ready. */ VkCommandBuffer secondaryCommands[11]; secondaryCommands[0] = m_terrain_command[m_current_buffer_index]; for (uint32_t i = 0; i < m_max_draw_calls; ++i){ secondaryCommands[i + 1] = m_draw_calls[i]->getDrawCommand(m_current_buffer_index); } vkCmdExecuteCommands(m_primary_commands[m_current_buffer_index], 1 + m_max_draw_calls, secondaryCommands); vkCmdEndRenderPass(m_primary_commands[m_current_buffer_index]); VkImageResolve blitInfo; blitInfo.srcOffset.x = 0; blitInfo.srcOffset.y = 0; blitInfo.srcOffset.z = 0; blitInfo.dstOffset.x = 0; blitInfo.dstOffset.y = 0; blitInfo.dstOffset.z = 0; blitInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blitInfo.srcSubresource.mipLevel = 0; blitInfo.srcSubresource.baseArrayLayer = 0; blitInfo.srcSubresource.layerCount = 1; blitInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blitInfo.dstSubresource.mipLevel = 0; blitInfo.dstSubresource.baseArrayLayer = 0; blitInfo.dstSubresource.layerCount = 1; blitInfo.extent.width = m_width; blitInfo.extent.height = m_height; blitInfo.extent.depth = 1; vkCmdResolveImage( m_primary_commands[m_current_buffer_index], m_color_attachment.image, VK_IMAGE_LAYOUT_GENERAL, m_resolve_attachment[m_current_buffer_index].image, VK_IMAGE_LAYOUT_GENERAL, 1, &blitInfo); VKA_CHECK_ERROR(vkEndCommandBuffer(m_primary_commands[m_current_buffer_index]), "Could not end command buffer for draw command.\n"); }
// Updates the secondary command buffers using a thread pool // and puts them into the primary command buffer that's // lat submitted to the queue for rendering void updateCommandBuffers(VkFramebuffer frameBuffer) { VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; clearValues[0].color = defaultClearColor; clearValues[0].color = { {0.0f, 0.0f, 0.2f, 0.0f} }; clearValues[1].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); renderPassBeginInfo.renderPass = renderPass; renderPassBeginInfo.renderArea.offset.x = 0; renderPassBeginInfo.renderArea.offset.y = 0; renderPassBeginInfo.renderArea.extent.width = width; renderPassBeginInfo.renderArea.extent.height = height; renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.framebuffer = frameBuffer; // Set target frame buffer VK_CHECK_RESULT(vkBeginCommandBuffer(primaryCommandBuffer, &cmdBufInfo)); // The primary command buffer does not contain any rendering commands // These are stored (and retrieved) from the secondary command buffers vkCmdBeginRenderPass(primaryCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); // Inheritance info for the secondary command buffers VkCommandBufferInheritanceInfo inheritanceInfo = vkTools::initializers::commandBufferInheritanceInfo(); inheritanceInfo.renderPass = renderPass; // Secondary command buffer also use the currently active framebuffer inheritanceInfo.framebuffer = frameBuffer; // Contains the list of secondary command buffers to be executed std::vector<VkCommandBuffer> commandBuffers; // Secondary command buffer with star background sphere updateSecondaryCommandBuffer(inheritanceInfo); commandBuffers.push_back(secondaryCommandBuffer); // Add a job to the thread's queue for each object to be rendered for (uint32_t t = 0; t < numThreads; t++) { for (uint32_t i = 0; i < numObjectsPerThread; i++) { threadPool.threads[t]->addJob([=] { threadRenderCode(t, i, inheritanceInfo); }); } } threadPool.wait(); // Only submit if object is within the current view frustum for (uint32_t t = 0; t < numThreads; t++) { for (uint32_t i = 0; i < numObjectsPerThread; i++) { if (threadData[t].objectData[i].visible) { commandBuffers.push_back(threadData[t].commandBuffer[i]); } } } // Execute render commands from the secondary command buffer vkCmdExecuteCommands(primaryCommandBuffer, commandBuffers.size(), commandBuffers.data()); vkCmdEndRenderPass(primaryCommandBuffer); VK_CHECK_RESULT(vkEndCommandBuffer(primaryCommandBuffer)); }