1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[d3d9] Only copy dirty parts of managed/sysmem resources

This commit is contained in:
Robin Kertels 2021-04-02 01:48:58 +02:00 committed by Joshie
parent 4261ff6ec1
commit b9512a4063

View File

@ -659,7 +659,7 @@ namespace dxvk {
VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource()); VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource());
VkExtent3D texLevelBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize); VkExtent3D texLevelBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize);
VkExtent3D copyExtent = srcTextureInfo->GetExtentMip(src->GetSubresource()); VkExtent3D copyExtent = texLevelExtent;
if (pSourceRect != nullptr) { if (pSourceRect != nullptr) {
srcBlockOffset = { pSourceRect->left / int32_t(formatInfo->blockSize.width), srcBlockOffset = { pSourceRect->left / int32_t(formatInfo->blockSize.width),
@ -677,38 +677,39 @@ namespace dxvk {
0u }; 0u };
} }
VkExtent3D copyBlockCount = util::computeBlockCount(copyExtent, formatInfo->blockSize);
const auto dstSubresource = vk::makeSubresourceLayers( const auto dstSubresource = vk::makeSubresourceLayers(
dstTextureInfo->GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT, dst->GetSubresource())); dstTextureInfo->GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT, dst->GetSubresource()));
DxvkBufferSliceHandle srcSlice = srcTextureInfo->GetMappedSlice(src->GetSubresource()); DxvkBufferSliceHandle srcSlice = srcTextureInfo->GetMappedSlice(src->GetSubresource());
D3D9BufferSlice slice = AllocTempBuffer<false>(srcSlice.length); VkDeviceSize dirtySize = copyBlockCount.width * copyBlockCount.height * formatInfo->elementSize;
D3D9BufferSlice slice = AllocTempBuffer<false>(dirtySize);
VkDeviceSize copySrcOffset = (srcBlockOffset.z * texLevelBlockCount.height * texLevelBlockCount.width
+ srcBlockOffset.y * texLevelBlockCount.width
+ srcBlockOffset.x)
* formatInfo->elementSize;
void* srcData = reinterpret_cast<uint8_t*>(srcSlice.mapPtr) + copySrcOffset;
util::packImageData( util::packImageData(
slice.mapPtr, srcSlice.mapPtr, texLevelBlockCount, formatInfo->elementSize, slice.mapPtr, srcData, copyBlockCount, formatInfo->elementSize,
texLevelBlockCount.width * formatInfo->elementSize, texLevelBlockCount.width * texLevelBlockCount.height * formatInfo->elementSize); texLevelBlockCount.width * formatInfo->elementSize, texLevelBlockCount.width * texLevelBlockCount.height * formatInfo->elementSize);
Rc<DxvkImage> dstImage = dstTextureInfo->GetImage(); Rc<DxvkImage> dstImage = dstTextureInfo->GetImage();
VkDeviceSize srcByteOffset = srcBlockOffset.y * formatInfo->elementSize * texLevelBlockCount.width
VkExtent3D levelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource());
VkExtent3D blockCount = util::computeBlockCount(levelExtent, formatInfo->blockSize);
VkDeviceSize srcByteOffset = srcBlockOffset.y * formatInfo->elementSize * blockCount.width
+ srcBlockOffset.x * formatInfo->elementSize; + srcBlockOffset.x * formatInfo->elementSize;
VkExtent2D fullSrcExtent = VkExtent2D{ blockCount.width * formatInfo->blockSize.width,
blockCount.height * formatInfo->blockSize.height };
EmitCs([ EmitCs([
cDstImage = std::move(dstImage), cDstImage = std::move(dstImage),
cSrcSlice = slice.slice, cSrcSlice = slice.slice,
cDstLayers = dstSubresource, cDstLayers = dstSubresource,
cDstOffset = dstOffset, cDstOffset = dstOffset,
cSrcOffset = srcByteOffset, cSrcOffset = srcByteOffset + slice.slice.offset(),
cCopyExtent = copyExtent, cCopyExtent = copyExtent
cSrcExtent = fullSrcExtent
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->copyBufferToImage( ctx->copyBufferToImage(
cDstImage, cDstLayers, cDstOffset, cCopyExtent, cDstImage, cDstLayers, cDstOffset, cCopyExtent,
cSrcSlice.buffer(), cSrcSlice.offset() + cSrcOffset, cSrcSlice.buffer(), cSrcSlice.offset() + cSrcOffset,
cSrcExtent); VkExtent2D { 0, 0 });
}); });
dstTextureInfo->SetWrittenByGPU(dst->GetSubresource(), true); dstTextureInfo->SetWrittenByGPU(dst->GetSubresource(), true);
@ -759,46 +760,48 @@ namespace dxvk {
int32_t(alignDown(box.Front >> m, formatInfo->blockSize.depth)) int32_t(alignDown(box.Front >> m, formatInfo->blockSize.depth))
}; };
VkExtent3D scaledBoxExtent = util::computeMipLevelExtent({ VkExtent3D scaledBoxExtent = util::computeMipLevelExtent({
uint32_t(box.Right - box.Left), uint32_t(box.Right - scaledBoxOffset.x),
uint32_t(box.Bottom - box.Top), uint32_t(box.Bottom - scaledBoxOffset.y),
uint32_t(box.Back - box.Front) uint32_t(box.Back - scaledBoxOffset.z)
}, m); }, m);
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(m);
VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize); VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize);
VkOffset3D boxOffsetBlockCount = util::computeBlockOffset(scaledBoxOffset, formatInfo->blockSize);
VkDeviceSize srcOffset = boxOffsetBlockCount.z * formatInfo->elementSize * texLevelExtentBlockCount.depth
+ boxOffsetBlockCount.y * formatInfo->elementSize * texLevelExtentBlockCount.width
+ boxOffsetBlockCount.x * formatInfo->elementSize;
VkExtent2D srcExtent = VkExtent2D{ texLevelExtentBlockCount.width * formatInfo->blockSize.width,
texLevelExtentBlockCount.height * formatInfo->blockSize.height };
scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width, scaledAlignedBoxExtent.width); scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width, scaledAlignedBoxExtent.width);
scaledAlignedBoxExtent.height = std::min<uint32_t>(texLevelExtent.height, scaledAlignedBoxExtent.height); scaledAlignedBoxExtent.height = std::min<uint32_t>(texLevelExtent.height, scaledAlignedBoxExtent.height);
scaledAlignedBoxExtent.depth = std::min<uint32_t>(texLevelExtent.depth, scaledAlignedBoxExtent.depth); scaledAlignedBoxExtent.depth = std::min<uint32_t>(texLevelExtent.depth, scaledAlignedBoxExtent.depth);
DxvkBufferSliceHandle srcSlice = srcTexInfo->GetMappedSlice(srcTexInfo->CalcSubresource(a, m)); VkDeviceSize dirtySize = scaledBoxExtentBlockCount.width * scaledBoxExtentBlockCount.height * scaledBoxExtentBlockCount.depth * formatInfo->elementSize;
D3D9BufferSlice slice = AllocTempBuffer<false>(srcSlice.length); D3D9BufferSlice slice = AllocTempBuffer<false>(dirtySize);
VkOffset3D boxOffsetBlockCount = util::computeBlockOffset(scaledBoxOffset, formatInfo->blockSize);
VkDeviceSize copySrcOffset = (boxOffsetBlockCount.z * texLevelExtentBlockCount.height * texLevelExtentBlockCount.width
+ boxOffsetBlockCount.y * texLevelExtentBlockCount.width
+ boxOffsetBlockCount.x)
* formatInfo->elementSize;
void* srcData = reinterpret_cast<uint8_t*>(srcTexInfo->GetMappedSlice(srcTexInfo->CalcSubresource(a, m)).mapPtr) + copySrcOffset;
util::packImageData( util::packImageData(
slice.mapPtr, srcSlice.mapPtr, texLevelExtentBlockCount, formatInfo->elementSize, slice.mapPtr, srcData, scaledBoxExtentBlockCount, formatInfo->elementSize,
texLevelExtentBlockCount.width * formatInfo->elementSize, texLevelExtentBlockCount.width * texLevelExtentBlockCount.height * formatInfo->elementSize); texLevelExtentBlockCount.width * formatInfo->elementSize, texLevelExtentBlockCount.width * texLevelExtentBlockCount.height * formatInfo->elementSize);
scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width, scaledAlignedBoxExtent.width);
scaledAlignedBoxExtent.height = std::min<uint32_t>(texLevelExtent.height, scaledAlignedBoxExtent.height);
scaledAlignedBoxExtent.depth = std::min<uint32_t>(texLevelExtent.depth, scaledAlignedBoxExtent.depth);
EmitCs([ EmitCs([
cDstImage = dstImage, cDstImage = dstImage,
cSrcSlice = slice.slice, cSrcSlice = slice.slice,
cDstLayers = dstLayers, cDstLayers = dstLayers,
cExtent = scaledAlignedBoxExtent, cExtent = scaledAlignedBoxExtent,
cOffset = scaledBoxOffset, cOffset = scaledBoxOffset
cSrcOffset = srcOffset,
cSrcExtent = srcExtent
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->copyBufferToImage( ctx->copyBufferToImage(
cDstImage, cDstLayers, cDstImage, cDstLayers,
cOffset, cExtent, cOffset, cExtent,
cSrcSlice.buffer(), cSrcSlice.offset() + cSrcOffset, cSrcSlice.buffer(), cSrcSlice.offset(),
cSrcExtent); VkExtent2D { 0, 0 });
}); });
dstTexInfo->SetWrittenByGPU(dstTexInfo->CalcSubresource(a, m), true); dstTexInfo->SetWrittenByGPU(dstTexInfo->CalcSubresource(a, m), true);
@ -3891,7 +3894,6 @@ namespace dxvk {
} }
} }
bool D3D9DeviceEx::ShouldRecord() { bool D3D9DeviceEx::ShouldRecord() {
return m_recorder != nullptr && !m_recorder->IsApplying(); return m_recorder != nullptr && !m_recorder->IsApplying();
} }
@ -4301,9 +4303,6 @@ namespace dxvk {
auto subresource = pResource->GetSubresourceFromIndex( auto subresource = pResource->GetSubresourceFromIndex(
formatInfo->aspectMask, Subresource); formatInfo->aspectMask, Subresource);
VkExtent3D levelExtent = image
->mipLevelExtent(subresource.mipLevel);
VkImageSubresourceLayers subresourceLayers = { VkImageSubresourceLayers subresourceLayers = {
subresource.aspectMask, subresource.aspectMask,
subresource.mipLevel, subresource.mipLevel,
@ -4312,21 +4311,54 @@ namespace dxvk {
auto convertFormat = pResource->GetFormatMapping().ConversionFormatInfo; auto convertFormat = pResource->GetFormatMapping().ConversionFormatInfo;
if (likely(convertFormat.FormatType == D3D9ConversionFormat_None)) { if (likely(convertFormat.FormatType == D3D9ConversionFormat_None)) {
VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(levelExtent, formatInfo->blockSize); const DxvkFormatInfo* formatInfo = imageFormatInfo(pResource->GetFormatMapping().FormatColor);
D3D9BufferSlice slice = AllocTempBuffer<false>(srcSlice.length); VkImageSubresourceLayers dstLayers = { VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel, subresource.arrayLayer, 1 };
const D3DBOX& box = pResource->GetDirtyBox(subresource.arrayLayer);
VkOffset3D scaledBoxOffset = {
int32_t(alignDown(box.Left >> subresource.mipLevel, formatInfo->blockSize.width)),
int32_t(alignDown(box.Top >> subresource.mipLevel, formatInfo->blockSize.height)),
int32_t(alignDown(box.Front >> subresource.mipLevel, formatInfo->blockSize.depth))
};
VkExtent3D scaledBoxExtent = util::computeMipLevelExtent({
uint32_t(box.Right - scaledBoxOffset.x),
uint32_t(box.Bottom - scaledBoxOffset.y),
uint32_t(box.Back - scaledBoxOffset.z)
}, subresource.mipLevel);
VkExtent3D scaledBoxExtentBlockCount = util::computeBlockCount(scaledBoxExtent, formatInfo->blockSize);
VkExtent3D scaledAlignedBoxExtent = util::computeBlockExtent(scaledBoxExtentBlockCount, formatInfo->blockSize);
VkExtent3D texLevelExtent = image->mipLevelExtent(subresource.mipLevel);
VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(texLevelExtent, formatInfo->blockSize);
scaledAlignedBoxExtent.width = std::min<uint32_t>(texLevelExtent.width, scaledAlignedBoxExtent.width);
scaledAlignedBoxExtent.height = std::min<uint32_t>(texLevelExtent.height, scaledAlignedBoxExtent.height);
scaledAlignedBoxExtent.depth = std::min<uint32_t>(texLevelExtent.depth, scaledAlignedBoxExtent.depth);
VkDeviceSize dirtySize = scaledBoxExtentBlockCount.width * scaledBoxExtentBlockCount.height * scaledBoxExtentBlockCount.depth * formatInfo->elementSize;
D3D9BufferSlice slice = AllocTempBuffer<false>(dirtySize);
VkOffset3D boxOffsetBlockCount = util::computeBlockOffset(scaledBoxOffset, formatInfo->blockSize);
VkDeviceSize copySrcOffset = (boxOffsetBlockCount.z * texLevelExtentBlockCount.height * texLevelExtentBlockCount.width
+ boxOffsetBlockCount.y * texLevelExtentBlockCount.width
+ boxOffsetBlockCount.x)
* formatInfo->elementSize;
void* srcData = reinterpret_cast<uint8_t*>(srcSlice.mapPtr) + copySrcOffset;
util::packImageData( util::packImageData(
slice.mapPtr, srcSlice.mapPtr, texLevelExtentBlockCount, formatInfo->elementSize, slice.mapPtr, srcData, scaledBoxExtentBlockCount, formatInfo->elementSize,
texLevelExtentBlockCount.width * formatInfo->elementSize, texLevelExtentBlockCount.width * texLevelExtentBlockCount.height * formatInfo->elementSize); texLevelExtentBlockCount.width * formatInfo->elementSize, texLevelExtentBlockCount.width * texLevelExtentBlockCount.height * formatInfo->elementSize);
EmitCs([ EmitCs([
cSrcSlice = slice.slice, cSrcSlice = slice.slice,
cDstImage = image, cDstImage = image,
cDstLayers = subresourceLayers, cDstLayers = dstLayers,
cDstLevelExtent = levelExtent cDstLevelExtent = scaledAlignedBoxExtent,
cOffset = scaledBoxOffset
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->copyBufferToImage(cDstImage, cDstLayers, ctx->copyBufferToImage(
VkOffset3D{ 0, 0, 0 }, cDstLevelExtent, cDstImage, cDstLayers,
cOffset, cDstLevelExtent,
cSrcSlice.buffer(), cSrcSlice.offset(), cSrcSlice.buffer(), cSrcSlice.offset(),
{ 0u, 0u }); VkExtent2D { 0, 0 });
}); });
} }
else { else {
@ -4512,16 +4544,22 @@ namespace dxvk {
auto dstBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>(); auto dstBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>();
auto srcBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_STAGING>(); auto srcBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_STAGING>();
D3D9Range& range = pResource->DirtyRange();
D3D9BufferSlice slice = AllocTempBuffer<false>(range.max - range.min);
memcpy(slice.mapPtr, srcBuffer.mapPtr(range.min), range.max - range.min);
EmitCs([ EmitCs([
cDstSlice = dstBuffer, cDstSlice = dstBuffer,
cSrcSlice = srcBuffer cSrcSlice = slice.slice,
cLength = range.max - range.min
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->copyBuffer( ctx->copyBuffer(
cDstSlice.buffer(), cDstSlice.buffer(),
cDstSlice.offset(), cDstSlice.offset(),
cSrcSlice.buffer(), cSrcSlice.buffer(),
cSrcSlice.offset(), cSrcSlice.offset(),
cSrcSlice.length()); cLength);
}); });
pResource->GPUReadingRange().Conjoin(pResource->DirtyRange()); pResource->GPUReadingRange().Conjoin(pResource->DirtyRange());
@ -7044,5 +7082,4 @@ namespace dxvk {
return D3D_OK; return D3D_OK;
} }
} }