Texture2D* FramebufferManager::ResolveEFBColorTexture(const VkRect2D& region) { // Return the normal EFB texture if multisampling is off. if (m_efb_samples == VK_SAMPLE_COUNT_1_BIT) return m_efb_color_texture.get(); // Can't resolve within a render pass. StateTracker::GetInstance()->EndRenderPass(); // Resolving is considered to be a transfer operation. m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); m_efb_resolve_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Resolve to our already-created texture. VkImageResolve resolve = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, m_efb_layers }, // VkImageSubresourceLayers srcSubresource { region.offset.x, region.offset.y, 0 }, // VkOffset3D srcOffset { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, m_efb_layers }, // VkImageSubresourceLayers dstSubresource { region.offset.x, region.offset.y, 0 }, // VkOffset3D dstOffset { region.extent.width, region.extent.height, m_efb_layers } // VkExtent3D extent }; vkCmdResolveImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_color_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_efb_resolve_color_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve); // Restore MSAA texture ready for rendering again m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); return m_efb_resolve_color_texture.get(); }
Texture2D* FramebufferManager::ResolveEFBColorTexture(const VkRect2D& region) { // Return the normal EFB texture if multisampling is off. if (GetEFBSamples() == VK_SAMPLE_COUNT_1_BIT) return m_efb_color_texture.get(); // Can't resolve within a render pass. StateTracker::GetInstance()->EndRenderPass(); // It's not valid to resolve out-of-bounds coordinates. // Ensuring the region is within the image is the caller's responsibility. _assert_(region.offset.x >= 0 && region.offset.y >= 0 && (static_cast<u32>(region.offset.x) + region.extent.width) <= GetEFBWidth() && (static_cast<u32>(region.offset.y) + region.extent.height) <= GetEFBHeight()); // Resolving is considered to be a transfer operation. m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); m_efb_resolve_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Resolve to our already-created texture. VkImageResolve resolve = { {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, GetEFBLayers()}, // VkImageSubresourceLayers srcSubresource {region.offset.x, region.offset.y, 0}, // VkOffset3D srcOffset {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, GetEFBLayers()}, // VkImageSubresourceLayers dstSubresource {region.offset.x, region.offset.y, 0}, // VkOffset3D dstOffset {region.extent.width, region.extent.height, GetEFBLayers()} // VkExtent3D extent }; vkCmdResolveImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_color_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_efb_resolve_color_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve); // Restore MSAA texture ready for rendering again m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); return m_efb_resolve_color_texture.get(); }
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"); }
void VulkanTexture::copyImpl(const SPtr<Texture>& target, const TEXTURE_COPY_DESC& desc, const SPtr<CommandBuffer>& commandBuffer) { VulkanTexture* other = static_cast<VulkanTexture*>(target.get()); const TextureProperties& srcProps = mProperties; const TextureProperties& dstProps = other->getProperties(); bool srcHasMultisample = srcProps.getNumSamples() > 1; bool destHasMultisample = dstProps.getNumSamples() > 1; if ((srcProps.getUsage() & TU_DEPTHSTENCIL) != 0 || (dstProps.getUsage() & TU_DEPTHSTENCIL) != 0) { LOGERR("Texture copy/resolve isn't supported for depth-stencil textures."); return; } bool needsResolve = srcHasMultisample && !destHasMultisample; bool isMSCopy = srcHasMultisample || destHasMultisample; if (!needsResolve && isMSCopy) { if (srcProps.getNumSamples() != dstProps.getNumSamples()) { LOGERR("When copying textures their multisample counts must match. Ignoring copy."); return; } } VkImageLayout transferSrcLayout = mDirectlyMappable ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; VkImageLayout transferDstLayout = other->mDirectlyMappable ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; UINT32 mipWidth, mipHeight, mipDepth; bool copyEntireSurface = desc.srcVolume.getWidth() == 0 || desc.srcVolume.getHeight() == 0 || desc.srcVolume.getDepth() == 0; if(copyEntireSurface) { PixelUtil::getSizeForMipLevel( srcProps.getWidth(), srcProps.getHeight(), srcProps.getDepth(), desc.srcMip, mipWidth, mipHeight, mipDepth); } else { mipWidth = desc.srcVolume.getWidth(); mipHeight = desc.srcVolume.getHeight(); mipDepth = desc.srcVolume.getDepth(); } VkImageResolve resolveRegion; resolveRegion.srcOffset = { (INT32)desc.srcVolume.left, (INT32)desc.srcVolume.top, (INT32)desc.srcVolume.front }; resolveRegion.dstOffset = { desc.dstPosition.x, desc.dstPosition.y, desc.dstPosition.z }; resolveRegion.extent = { mipWidth, mipHeight, mipDepth }; resolveRegion.srcSubresource.baseArrayLayer = desc.srcFace; resolveRegion.srcSubresource.layerCount = 1; resolveRegion.srcSubresource.mipLevel = desc.srcMip; resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; resolveRegion.dstSubresource.baseArrayLayer = desc.dstFace; resolveRegion.dstSubresource.layerCount = 1; resolveRegion.dstSubresource.mipLevel = desc.dstMip; resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; VkImageCopy imageRegion; imageRegion.srcOffset = { (INT32)desc.srcVolume.left, (INT32)desc.srcVolume.top, (INT32)desc.srcVolume.front }; imageRegion.dstOffset = { desc.dstPosition.x, desc.dstPosition.y, desc.dstPosition.z }; imageRegion.extent = { mipWidth, mipHeight, mipDepth }; imageRegion.srcSubresource.baseArrayLayer = desc.srcFace; imageRegion.srcSubresource.layerCount = 1; imageRegion.srcSubresource.mipLevel = desc.srcMip; imageRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageRegion.dstSubresource.baseArrayLayer = desc.dstFace; imageRegion.dstSubresource.layerCount = 1; imageRegion.dstSubresource.mipLevel = desc.dstMip; imageRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; VkImageSubresourceRange srcRange; srcRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; srcRange.baseArrayLayer = desc.srcFace; srcRange.layerCount = 1; srcRange.baseMipLevel = desc.srcMip; srcRange.levelCount = 1; VkImageSubresourceRange dstRange; dstRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; dstRange.baseArrayLayer = desc.dstFace; dstRange.layerCount = 1; dstRange.baseMipLevel = desc.dstMip; dstRange.levelCount = 1; VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance()); VulkanCmdBuffer* vkCB; if (commandBuffer != nullptr) vkCB = static_cast<VulkanCommandBuffer*>(commandBuffer.get())->getInternal(); else vkCB = rapi._getMainCommandBuffer()->getInternal(); UINT32 deviceIdx = vkCB->getDeviceIdx(); VulkanImage* srcImage = mImages[deviceIdx]; VulkanImage* dstImage = other->getResource(deviceIdx); if (srcImage == nullptr || dstImage == nullptr) return; VkImageLayout srcLayout = vkCB->getCurrentLayout(srcImage, srcRange, false); VkImageLayout dstLayout = vkCB->getCurrentLayout(dstImage, dstRange, false); VkCommandBuffer vkCmdBuf = vkCB->getHandle(); VkAccessFlags srcAccessMask = srcImage->getAccessFlags(srcLayout); VkAccessFlags dstAccessMask = dstImage->getAccessFlags(dstLayout); if (vkCB->isInRenderPass()) vkCB->endRenderPass(); // Transfer textures to a valid layout vkCB->setLayout(srcImage->getHandle(), srcAccessMask, VK_ACCESS_TRANSFER_READ_BIT, srcLayout, transferSrcLayout, srcRange); vkCB->setLayout(dstImage->getHandle(), dstAccessMask, VK_ACCESS_TRANSFER_WRITE_BIT, dstLayout, transferDstLayout, dstRange); if (srcHasMultisample && !destHasMultisample) // Resolving from MS to non-MS texture { vkCmdResolveImage(vkCmdBuf, srcImage->getHandle(), transferSrcLayout, dstImage->getHandle(), transferDstLayout, 1, &resolveRegion); } else // Just a normal copy { vkCmdCopyImage(vkCmdBuf, srcImage->getHandle(), transferSrcLayout, dstImage->getHandle(), transferDstLayout, 1, &imageRegion); } // Transfer back to optimal layouts srcLayout = srcImage->getOptimalLayout(); // Notify the command buffer that these resources are being used on it vkCB->registerResource(srcImage, srcRange, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VulkanUseFlag::Read, ResourceUsage::Transfer); vkCB->registerResource(dstImage, dstRange, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VulkanUseFlag::Write, ResourceUsage::Transfer); }