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

[d3d9] Handle different mip chain lengths in UpdateTexture

This commit is contained in:
Robin Kertels 2022-02-02 19:39:46 +01:00 committed by Joshie
parent 80f744549f
commit c12cd1952c

View File

@ -775,11 +775,23 @@ namespace dxvk {
if (unlikely(srcTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM || dstTexInfo->Desc()->Pool != D3DPOOL_DEFAULT)) if (unlikely(srcTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM || dstTexInfo->Desc()->Pool != D3DPOOL_DEFAULT))
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
if (srcTexInfo->Desc()->MipLevels < dstTexInfo->Desc()->MipLevels)
return D3DERR_INVALIDCALL;
if (dstTexInfo->Desc()->Format != srcTexInfo->Desc()->Format)
return D3DERR_INVALIDCALL;
const Rc<DxvkImage> dstImage = dstTexInfo->GetImage(); const Rc<DxvkImage> dstImage = dstTexInfo->GetImage();
const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTexInfo->GetFormatMapping().FormatColor); const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTexInfo->GetFormatMapping().FormatColor);
uint32_t mipLevels = std::min(srcTexInfo->Desc()->MipLevels, dstTexInfo->Desc()->MipLevels); uint32_t mipLevels = dstTexInfo->Desc()->MipLevels;
uint32_t arraySlices = std::min(srcTexInfo->Desc()->ArraySize, dstTexInfo->Desc()->ArraySize); uint32_t arraySlices = std::min(srcTexInfo->Desc()->ArraySize, dstTexInfo->Desc()->ArraySize);
uint32_t srcMipOffset = srcTexInfo->Desc()->MipLevels - mipLevels;
VkExtent3D srcFirstMipExtent = util::computeMipLevelExtent(srcTexInfo->GetExtent(), srcMipOffset);
VkExtent3D dstFirstMipExtent = dstTexInfo->GetExtent();
if (srcFirstMipExtent != dstFirstMipExtent)
return D3DERR_INVALIDCALL;
if (unlikely(srcTexInfo->IsAutomaticMip() && !dstTexInfo->IsAutomaticMip())) if (unlikely(srcTexInfo->IsAutomaticMip() && !dstTexInfo->IsAutomaticMip()))
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
@ -791,23 +803,24 @@ namespace dxvk {
if (box.Left >= box.Right || box.Top >= box.Bottom || box.Front >= box.Back) if (box.Left >= box.Right || box.Top >= box.Bottom || box.Front >= box.Back)
continue; continue;
for (uint32_t m = 0; m < mipLevels; m++) { for (uint32_t dstMip = 0; dstMip < mipLevels; dstMip++) {
VkImageSubresourceLayers dstLayers = { VK_IMAGE_ASPECT_COLOR_BIT, m, a, 1 }; uint32_t srcMip = dstMip + srcMipOffset;
VkImageSubresourceLayers dstLayers = { VK_IMAGE_ASPECT_COLOR_BIT, dstMip, a, 1 };
VkOffset3D scaledBoxOffset = { VkOffset3D scaledBoxOffset = {
int32_t(alignDown(box.Left >> m, formatInfo->blockSize.width)), int32_t(alignDown(box.Left >> srcMip, formatInfo->blockSize.width)),
int32_t(alignDown(box.Top >> m, formatInfo->blockSize.height)), int32_t(alignDown(box.Top >> srcMip, formatInfo->blockSize.height)),
int32_t(alignDown(box.Front >> m, formatInfo->blockSize.depth)) int32_t(alignDown(box.Front >> srcMip, formatInfo->blockSize.depth))
}; };
VkExtent3D scaledBoxExtent = util::computeMipLevelExtent({ VkExtent3D scaledBoxExtent = util::computeMipLevelExtent({
uint32_t(box.Right - int32_t(alignDown(box.Left, formatInfo->blockSize.width))), uint32_t(box.Right - int32_t(alignDown(box.Left, formatInfo->blockSize.width))),
uint32_t(box.Bottom - int32_t(alignDown(box.Top, formatInfo->blockSize.height))), uint32_t(box.Bottom - int32_t(alignDown(box.Top, formatInfo->blockSize.height))),
uint32_t(box.Back - int32_t(alignDown(box.Front, formatInfo->blockSize.depth))) uint32_t(box.Back - int32_t(alignDown(box.Front, formatInfo->blockSize.depth)))
}, m); }, srcMip);
VkExtent3D scaledBoxExtentBlockCount = util::computeBlockCount(scaledBoxExtent, formatInfo->blockSize); VkExtent3D scaledBoxExtentBlockCount = util::computeBlockCount(scaledBoxExtent, formatInfo->blockSize);
VkExtent3D scaledAlignedBoxExtent = util::computeBlockExtent(scaledBoxExtentBlockCount, formatInfo->blockSize); VkExtent3D scaledAlignedBoxExtent = util::computeBlockExtent(scaledBoxExtentBlockCount, formatInfo->blockSize);
VkExtent3D texLevelExtent = dstImage->mipLevelExtent(m); VkExtent3D texLevelExtent = dstImage->mipLevelExtent(dstMip);
VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize); VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize);
scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width - scaledBoxOffset.x, scaledAlignedBoxExtent.width); scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width - scaledBoxOffset.x, scaledAlignedBoxExtent.width);
@ -822,7 +835,7 @@ namespace dxvk {
+ boxOffsetBlockCount.y * pitch + boxOffsetBlockCount.y * pitch
+ boxOffsetBlockCount.x * formatInfo->elementSize; + boxOffsetBlockCount.x * formatInfo->elementSize;
void* srcData = reinterpret_cast<uint8_t*>(srcTexInfo->GetMappedSlice(srcTexInfo->CalcSubresource(a, m)).mapPtr) + copySrcOffset; void* srcData = reinterpret_cast<uint8_t*>(srcTexInfo->GetMappedSlice(srcTexInfo->CalcSubresource(a, srcMip)).mapPtr) + copySrcOffset;
util::packImageData( util::packImageData(
slice.mapPtr, srcData, scaledBoxExtentBlockCount, formatInfo->elementSize, slice.mapPtr, srcData, scaledBoxExtentBlockCount, formatInfo->elementSize,
pitch, pitch * texLevelExtentBlockCount.height); pitch, pitch * texLevelExtentBlockCount.height);
@ -844,7 +857,7 @@ namespace dxvk {
cSrcSlice.buffer(), cSrcSlice.offset(), 0, 0); cSrcSlice.buffer(), cSrcSlice.offset(), 0, 0);
}); });
dstTexInfo->SetWrittenByGPU(dstTexInfo->CalcSubresource(a, m), true); dstTexInfo->SetWrittenByGPU(dstTexInfo->CalcSubresource(a, dstMip), true);
} }
} }