From 7ed9f36769c4e686134b0cea8ee83ed4f39fcbb2 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 7 Nov 2018 18:31:01 +0100 Subject: [PATCH] [dxvk] Add clearCompressedColorImage method Since we can't use regular clears for compressed formats, we need a new method to zero image memory. --- src/dxvk/dxvk_context.cpp | 60 +++++++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_context.h | 10 +++++++ 2 files changed, 70 insertions(+) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index ec671761..bf2c87be 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -421,6 +421,66 @@ namespace dxvk { m_cmd->trackResource(image); } + + + void DxvkContext::clearCompressedColorImage( + const Rc& image, + const VkImageSubresourceRange& subresources) { + this->spillRenderPass(); + + // Allocate enough staging buffer memory to fit one + // single subresource, then dispatch multiple copies + VkDeviceSize dataSize = util::computeImageDataSize( + image->info().format, + image->mipLevelExtent(subresources.baseMipLevel)); + + DxvkStagingBufferSlice slice = m_cmd->stagedAlloc(dataSize); + std::memset(slice.mapPtr, 0, dataSize); + + if (m_barriers.isImageDirty(image, subresources, DxvkAccess::Write)) + m_barriers.recordCommands(m_cmd); + + m_transitions.accessImage( + image, subresources, + VK_IMAGE_LAYOUT_UNDEFINED, 0, 0, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + m_transitions.recordCommands(m_cmd); + + for (uint32_t level = 0; level < subresources.levelCount; level++) { + VkOffset3D offset = VkOffset3D { 0, 0, 0 }; + VkExtent3D extent = image->mipLevelExtent(subresources.baseMipLevel + level); + + for (uint32_t layer = 0; layer < subresources.layerCount; layer++) { + VkBufferImageCopy region; + region.bufferOffset = slice.offset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource = vk::makeSubresourceLayers( + vk::pickSubresource(subresources, level, layer)); + region.imageOffset = offset; + region.imageExtent = extent; + + m_cmd->cmdCopyBufferToImage( + slice.buffer, image->handle(), + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + 1, ®ion); + } + } + + m_barriers.accessImage( + image, subresources, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + image->info().layout, + image->info().stages, + image->info().access); + + m_cmd->trackResource(image); + } void DxvkContext::clearRenderTarget( diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 01e0d146..4f2b1918 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -250,6 +250,16 @@ namespace dxvk { const VkClearDepthStencilValue& value, const VkImageSubresourceRange& subresources); + /** + * \brief Clears a compressed image to black + * + * \param [in] image The image to clear + * \param [in] subresources Subresources to clear + */ + void clearCompressedColorImage( + const Rc& image, + const VkImageSubresourceRange& subresources); + /** * \brief Clears an active render target *