diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 8fd6fc4f..c9ecf245 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -327,7 +327,82 @@ namespace dxvk { ID3D11Resource* pSrcResource, UINT SrcSubresource, const D3D11_BOX* pSrcBox) { - Logger::err("D3D11DeviceContext::CopySubresourceRegion: Not implemented"); + D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + + pDstResource->GetType(&dstResourceDim); + pSrcResource->GetType(&srcResourceDim); + + if (dstResourceDim != srcResourceDim) { + Logger::err("D3D11DeviceContext: CopySubresourceRegion: Mismatched resource types"); + return; + } + + if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + Logger::err("D3D11DeviceContext::CopySubresourceRegion: Buffers not supported"); + } else { + D3D11TextureInfo dstTextureInfo; + D3D11TextureInfo srcTextureInfo; + + if (FAILED(GetCommonTextureInfo(pDstResource, &dstTextureInfo)) + || FAILED(GetCommonTextureInfo(pSrcResource, &srcTextureInfo))) { + Logger::err("D3D11DeviceContext: Failed to retrieve DXVK images"); + return; + } + + VkOffset3D srcOffset = { 0, 0, 0 }; + VkOffset3D dstOffset = { + static_cast(DstX), + static_cast(DstY), + static_cast(DstZ) }; + + VkExtent3D extent = srcTextureInfo.image->info().extent; + + if (pSrcBox != nullptr) { + if (pSrcBox->left >= pSrcBox->right + || pSrcBox->top >= pSrcBox->bottom + || pSrcBox->front >= pSrcBox->back) + return; // no-op, but legal + + srcOffset.x = pSrcBox->left; + srcOffset.y = pSrcBox->top; + srcOffset.z = pSrcBox->front; + + extent.width = pSrcBox->right - pSrcBox->left; + extent.height = pSrcBox->bottom - pSrcBox->top; + extent.depth = pSrcBox->back - pSrcBox->front; + } + + const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstTextureInfo.image->info().format); + const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcTextureInfo.image->info().format); + + const VkImageSubresource dstSubresource = + GetSubresourceFromIndex( + dstFormatInfo->aspectMask & srcFormatInfo->aspectMask, + dstTextureInfo.image->info().mipLevels, DstSubresource); + + const VkImageSubresource srcSubresource = + GetSubresourceFromIndex( + dstFormatInfo->aspectMask & srcFormatInfo->aspectMask, + srcTextureInfo.image->info().mipLevels, SrcSubresource); + + VkImageSubresourceLayers dstLayers; + dstLayers.aspectMask = dstSubresource.aspectMask; + dstLayers.mipLevel = dstSubresource.mipLevel; + dstLayers.baseArrayLayer = dstSubresource.arrayLayer; + dstLayers.layerCount = 1; + + VkImageSubresourceLayers srcLayers; + srcLayers.aspectMask = srcSubresource.aspectMask; + srcLayers.mipLevel = srcSubresource.mipLevel; + srcLayers.baseArrayLayer = srcSubresource.arrayLayer; + srcLayers.layerCount = 1; + + m_context->copyImage( + dstTextureInfo.image, dstLayers, dstOffset, + srcTextureInfo.image, srcLayers, srcOffset, + extent); + } } diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index de5eadd9..cc87b50a 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -217,6 +217,20 @@ namespace dxvk { } + void DxvkCommandList::cmdCopyImage( + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions) { + m_vkd->vkCmdCopyImage(m_buffer, + srcImage, srcImageLayout, + dstImage, dstImageLayout, + regionCount, pRegions); + } + + void DxvkCommandList::cmdDispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index e71064c4..b74167de 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -133,6 +133,14 @@ namespace dxvk { uint32_t regionCount, const VkBufferCopy* pRegions); + void cmdCopyImage( + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + void cmdDispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index e156b54e..d63df1d0 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -252,6 +252,8 @@ namespace dxvk { VkDeviceSize srcOffset, VkDeviceSize numBytes) { if (numBytes != 0) { + this->renderPassEnd(); + VkBufferCopy bufferRegion; bufferRegion.srcOffset = srcOffset; bufferRegion.dstOffset = dstOffset; @@ -284,6 +286,89 @@ namespace dxvk { } + void DxvkContext::copyImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent) { + this->renderPassEnd(); + + VkImageSubresourceRange dstSubresourceRange; + dstSubresourceRange.aspectMask = dstSubresource.aspectMask; + dstSubresourceRange.baseMipLevel = dstSubresource.mipLevel; + dstSubresourceRange.levelCount = 1; + dstSubresourceRange.baseArrayLayer = dstSubresource.baseArrayLayer; + dstSubresourceRange.layerCount = dstSubresource.layerCount; + + VkImageSubresourceRange srcSubresourceRange; + srcSubresourceRange.aspectMask = srcSubresource.aspectMask; + srcSubresourceRange.baseMipLevel = srcSubresource.mipLevel; + srcSubresourceRange.levelCount = 1; + srcSubresourceRange.baseArrayLayer = srcSubresource.baseArrayLayer; + srcSubresourceRange.layerCount = srcSubresource.layerCount; + + // TODO if the entire destination resource + // gets overwritten, discard the contents. + m_barriers.accessImage( + dstImage, dstSubresourceRange, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + m_barriers.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + + m_barriers.recordCommands(m_cmd); + + VkImageCopy imageRegion; + imageRegion.srcSubresource = srcSubresource; + imageRegion.srcOffset = srcOffset; + imageRegion.dstSubresource = dstSubresource; + imageRegion.dstOffset = dstOffset; + imageRegion.extent = extent; + + m_cmd->cmdCopyImage( + srcImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dstImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &imageRegion); + + m_barriers.accessImage( + dstImage, dstSubresourceRange, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_barriers.accessImage( + srcImage, srcSubresourceRange, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_barriers.recordCommands(m_cmd); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + } + + void DxvkContext::dispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 32725fd1..7c1fa879 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -185,6 +185,26 @@ namespace dxvk { VkDeviceSize srcOffset, VkDeviceSize numBytes); + /** + * \brief Copies data from one image to another + * + * \param [in] dstImage Destination image + * \param [in] dstSubresource Destination subresource + * \param [in] dstOffset Destination area offset + * \param [in] srcImage Source image + * \param [in] srcSubresource Source subresource + * \param [in] srcOffset Source area offset + * \param [in] extent Size of the area to copy + */ + void copyImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent); + /** * \brief Starts compute jobs *