1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-14 04:29:15 +01:00

[d3d11] Introduce UpdateImage

This commit is contained in:
Philip Rebohle 2021-06-24 01:41:48 +02:00
parent 5e4ed2d929
commit 6ba1746d46
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 111 additions and 42 deletions

View File

@ -992,20 +992,18 @@ namespace dxvk {
});
}
} else {
const D3D11CommonTexture* textureInfo = GetCommonTexture(pDstResource);
D3D11CommonTexture* dstTexture = GetCommonTexture(pDstResource);
if (DstSubresource >= textureInfo->CountSubresources())
if (DstSubresource >= dstTexture->CountSubresources())
return;
VkFormat packedFormat = m_parent->LookupPackedFormat(
textureInfo->Desc()->Format,
textureInfo->GetFormatMode()).Format;
VkFormat packedFormat = dstTexture->GetPackedFormat();
auto formatInfo = imageFormatInfo(packedFormat);
auto subresource = textureInfo->GetSubresourceFromIndex(
auto subresource = dstTexture->GetSubresourceFromIndex(
formatInfo->aspectMask, DstSubresource);
VkExtent3D mipExtent = textureInfo->GetImage()->mipLevelExtent(subresource.mipLevel);
VkExtent3D mipExtent = dstTexture->MipLevelExtent(subresource.mipLevel);
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = mipExtent;
@ -1025,51 +1023,23 @@ namespace dxvk {
extent.depth = pDstBox->back - pDstBox->front;
}
const VkImageSubresourceLayers layers = {
subresource.aspectMask,
subresource.mipLevel,
subresource.arrayLayer, 1 };
if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) {
Logger::err("D3D11: UpdateSubresource1: Unaligned region");
return;
}
auto image = textureInfo->GetImage();
auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent));
util::packImageData(stagingSlice.mapPtr(0),
pSrcData, SrcRowPitch, SrcDepthPitch,
image->info().type, extent, 1,
dstTexture->GetVkImageType(), extent, 1,
formatInfo, formatInfo->aspectMask);
EmitCs([
cDstImage = std::move(image),
cDstLayers = layers,
cDstOffset = offset,
cDstExtent = extent,
cStagingSlice = std::move(stagingSlice),
cPackedFormat = packedFormat
] (DxvkContext* ctx) {
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyBufferToImage(cDstImage,
cDstLayers, cDstOffset, cDstExtent,
cStagingSlice.buffer(),
cStagingSlice.offset(), 0, 0);
} else {
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cStagingSlice.buffer(),
cStagingSlice.offset(),
VkOffset2D { 0, 0 },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cPackedFormat);
}
});
if (textureInfo->CanUpdateMappedBufferEarly())
UpdateMappedBuffer(textureInfo, subresource);
UpdateImage(dstTexture, &subresource,
offset, extent, std::move(stagingSlice));
if (dstTexture->CanUpdateMappedBufferEarly())
UpdateMappedBuffer(dstTexture, subresource);
}
}
@ -3701,6 +3671,98 @@ namespace dxvk {
}
void D3D11DeviceContext::UpdateImage(
D3D11CommonTexture* pDstTexture,
const VkImageSubresource* pDstSubresource,
VkOffset3D DstOffset,
VkExtent3D DstExtent,
DxvkBufferSlice StagingBuffer) {
bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
if (dstIsImage) {
EmitCs([
cDstImage = pDstTexture->GetImage(),
cDstLayers = vk::makeSubresourceLayers(*pDstSubresource),
cDstOffset = DstOffset,
cDstExtent = DstExtent,
cStagingSlice = std::move(StagingBuffer),
cPackedFormat = pDstTexture->GetPackedFormat()
] (DxvkContext* ctx) {
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyBufferToImage(cDstImage,
cDstLayers, cDstOffset, cDstExtent,
cStagingSlice.buffer(),
cStagingSlice.offset(), 0, 0);
} else {
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cStagingSlice.buffer(),
cStagingSlice.offset(),
VkOffset2D { 0, 0 },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cPackedFormat);
}
});
} else {
// If the destination image is backed only by a buffer, we need to use
// the packed buffer copy function which does not know about planes and
// format metadata, so deal with it manually here.
VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel);
uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel,
pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels);
auto dstFormat = pDstTexture->GetPackedFormat();
auto dstFormatInfo = imageFormatInfo(dstFormat);
uint32_t planeCount = 1;
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane))
planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask);
// The source data isn't stored in an image so we'll also need to
// track the offset for that while iterating over the planes.
VkDeviceSize srcPlaneOffset = 0;
for (uint32_t i = 0; i < planeCount; i++) {
VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
VkDeviceSize elementSize = dstFormatInfo->elementSize;
VkExtent3D blockSize = dstFormatInfo->blockSize;
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
dstAspectMask = vk::getPlaneAspect(i);
auto plane = &dstFormatInfo->planes[i];
blockSize.width *= plane->blockSize.width;
blockSize.height *= plane->blockSize.height;
elementSize = plane->elementSize;
}
VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize);
EmitCs([
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
cDstOffset = util::computeBlockOffset(DstOffset, blockSize),
cDstSize = util::computeBlockCount(dstMipExtent, blockSize),
cDstExtent = blockCount,
cSrcBuffer = StagingBuffer.buffer(),
cSrcStart = StagingBuffer.offset() + srcPlaneOffset,
cPixelSize = elementSize
] (DxvkContext* ctx) {
ctx->copyPackedBufferImage(
cDstBuffer, cDstStart, cDstOffset, cDstSize,
cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent,
cDstExtent, cPixelSize);
});
srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize;
}
}
}
void D3D11DeviceContext::SetDrawBuffers(
ID3D11Buffer* pBufferForArgs,
ID3D11Buffer* pBufferForCount) {

View File

@ -803,7 +803,14 @@ namespace dxvk {
void DiscardTexture(
ID3D11Resource* pResource,
UINT Subresource);
void UpdateImage(
D3D11CommonTexture* pDstTexture,
const VkImageSubresource* pDstSubresource,
VkOffset3D DstOffset,
VkExtent3D DstExtent,
DxvkBufferSlice StagingBuffer);
void SetDrawBuffers(
ID3D11Buffer* pBufferForArgs,
ID3D11Buffer* pBufferForCount);