1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-06 13:54:14 +01:00

[d3d11] Rework ReadFromSubresource and WriteToSubresource

Mainly changes the code to use existing helpers where possible, and
adds support for planar images, which was previously completely broken
for these functions.
This commit is contained in:
Philip Rebohle 2022-09-05 02:45:26 +02:00
parent ca833082b5
commit 1bed39f266
2 changed files with 76 additions and 72 deletions

View File

@ -1378,9 +1378,25 @@ namespace dxvk {
ID3D11Resource* pSrcResource, ID3D11Resource* pSrcResource,
UINT SrcSubresource, UINT SrcSubresource,
const D3D11_BOX* pSrcBox) { const D3D11_BOX* pSrcBox) {
auto texture = GetCommonTexture(pSrcResource);
if (!texture)
return;
if (texture->Desc()->Usage != D3D11_USAGE_DEFAULT
|| texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE
|| texture->CountSubresources() <= SrcSubresource)
return;
D3D11_MAP map = texture->GetMapType(SrcSubresource);
if (map != D3D11_MAP_READ
&& map != D3D11_MAP_READ_WRITE)
return;
CopySubresourceData( CopySubresourceData(
pDstData, DstRowPitch, DstDepthPitch, pDstData, DstRowPitch, DstDepthPitch,
pSrcResource, SrcSubresource, pSrcBox); texture, SrcSubresource, pSrcBox);
} }
@ -1391,9 +1407,26 @@ namespace dxvk {
const void* pSrcData, const void* pSrcData,
UINT SrcRowPitch, UINT SrcRowPitch,
UINT SrcDepthPitch) { UINT SrcDepthPitch) {
auto texture = GetCommonTexture(pDstResource);
if (!texture)
return;
if (texture->Desc()->Usage != D3D11_USAGE_DEFAULT
|| texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE
|| texture->CountSubresources() <= DstSubresource)
return;
D3D11_MAP map = texture->GetMapType(DstSubresource);
if (map != D3D11_MAP_WRITE
&& map != D3D11_MAP_WRITE_NO_OVERWRITE
&& map != D3D11_MAP_READ_WRITE)
return;
CopySubresourceData( CopySubresourceData(
pSrcData, SrcRowPitch, SrcRowPitch, pSrcData, SrcRowPitch, SrcRowPitch,
pDstResource, DstSubresource, pDstBox); texture, DstSubresource, pDstBox);
} }
@ -2240,36 +2273,16 @@ namespace dxvk {
Void* pData, Void* pData,
UINT RowPitch, UINT RowPitch,
UINT DepthPitch, UINT DepthPitch,
ID3D11Resource* pResource, D3D11CommonTexture* pTexture,
UINT Subresource, UINT Subresource,
const D3D11_BOX* pBox) { const D3D11_BOX* pBox) {
auto texture = GetCommonTexture(pResource);
if (!texture)
return;
// Validate texture state and skip invalid calls
if (texture->Desc()->Usage != D3D11_USAGE_DEFAULT
|| texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE
|| texture->CountSubresources() <= Subresource
|| texture->GetMapType(Subresource) == D3D11_MAP(~0u))
return;
// Retrieve image format information
VkFormat packedFormat = LookupPackedFormat(
texture->Desc()->Format,
texture->GetFormatMode()).Format;
auto formatInfo = lookupFormatInfo(packedFormat);
// Validate box against subresource dimensions // Validate box against subresource dimensions
Rc<DxvkImage> image = texture->GetImage(); auto formatInfo = lookupFormatInfo(pTexture->GetPackedFormat());
auto subresource = pTexture->GetSubresourceFromIndex(
auto subresource = texture->GetSubresourceFromIndex(
formatInfo->aspectMask, Subresource); formatInfo->aspectMask, Subresource);
VkOffset3D offset = { 0, 0, 0 }; VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = image->mipLevelExtent(subresource.mipLevel); VkExtent3D extent = pTexture->MipLevelExtent(subresource.mipLevel);
if (pBox) { if (pBox) {
if (pBox->left >= pBox->right if (pBox->left >= pBox->right
@ -2293,56 +2306,47 @@ namespace dxvk {
pBox->back - pBox->front }; pBox->back - pBox->front };
} }
// We can only operate on full blocks of compressed images // Copy image data, one plane at a time for multi-plane formats
offset = util::computeBlockOffset(offset, formatInfo->blockSize); Rc<DxvkImage> image = pTexture->GetImage();
extent = util::computeBlockCount(extent, formatInfo->blockSize); VkDeviceSize dataOffset = 0;
// Determine the memory layout of the image data for (uint32_t i = 0; i < pTexture->GetPlaneCount(); i++) {
D3D11_MAPPED_SUBRESOURCE subresourceData = { }; // Find current image aspects to process
VkImageAspectFlags aspect = formatInfo->aspectMask;
if (texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane))
VkSubresourceLayout layout = image->querySubresourceLayout(subresource); aspect = vk::getPlaneAspect(i);
subresourceData.pData = image->mapPtr(layout.offset);
subresourceData.RowPitch = layout.rowPitch; // Compute data layout of the current subresource
subresourceData.DepthPitch = layout.depthPitch; D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = pTexture->GetSubresourceLayout(aspect, Subresource);
} else {
subresourceData.pData = texture->GetMappedBuffer(Subresource)->mapPtr(0); // Compute actual map pointer, accounting for the region offset
subresourceData.RowPitch = formatInfo->elementSize * extent.width; VkDeviceSize mapOffset = pTexture->ComputeMappedOffset(Subresource, i, offset);
subresourceData.DepthPitch = formatInfo->elementSize * extent.width * extent.height;
} void* mapPtr = pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER
? pTexture->GetMappedBuffer(Subresource)->mapPtr(mapOffset)
: image->mapPtr(mapOffset);
if constexpr (std::is_const<Void>::value) { if constexpr (std::is_const<Void>::value) {
// WriteToSubresource // WriteToSubresource
auto src = reinterpret_cast<const char*>(pData); auto srcData = reinterpret_cast<const char*>(pData) + dataOffset;
auto dst = reinterpret_cast< char*>(subresourceData.pData);
for (uint32_t z = 0; z < extent.depth; z++) { util::packImageData(mapPtr, srcData, RowPitch, DepthPitch,
for (uint32_t y = 0; y < extent.height; y++) { layout.RowPitch, layout.DepthPitch, image->info().type,
std::memcpy( extent, 1, formatInfo, aspect);
dst + (offset.z + z) * subresourceData.DepthPitch
+ (offset.y + y) * subresourceData.RowPitch
+ (offset.x) * formatInfo->elementSize,
src + z * DepthPitch
+ y * RowPitch,
formatInfo->elementSize * extent.width);
}
}
} else { } else {
// ReadFromSubresource // ReadFromSubresource
auto src = reinterpret_cast<const char*>(subresourceData.pData); auto dstData = reinterpret_cast<char*>(pData) + dataOffset;
auto dst = reinterpret_cast< char*>(pData);
for (uint32_t z = 0; z < extent.depth; z++) { util::packImageData(dstData, mapPtr,
for (uint32_t y = 0; y < extent.height; y++) { layout.RowPitch, layout.DepthPitch,
std::memcpy( RowPitch, DepthPitch, image->info().type,
dst + z * DepthPitch extent, 1, formatInfo, aspect);
+ y * RowPitch,
src + (offset.z + z) * subresourceData.DepthPitch
+ (offset.y + y) * subresourceData.RowPitch
+ (offset.x) * formatInfo->elementSize,
formatInfo->elementSize * extent.width);
}
} }
// Advance linear data pointer by the size of the current aspect
dataOffset += util::computeImageDataSize(
pTexture->GetPackedFormat(), extent, aspect);
} }
} }

View File

@ -490,7 +490,7 @@ namespace dxvk {
Void* pData, Void* pData,
UINT RowPitch, UINT RowPitch,
UINT DepthPitch, UINT DepthPitch,
ID3D11Resource* pResource, D3D11CommonTexture* pTexture,
UINT Subresource, UINT Subresource,
const D3D11_BOX* pBox); const D3D11_BOX* pBox);