From 1832332d6df1e830f5c437a9eabaff42b9f25f5d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 29 Oct 2024 22:00:20 +0100 Subject: [PATCH] [d3d11] Add GetMapPtr method to D3D11CommonTexture Fixes a bug in Read/WriteSubresource where discards result in the wrong pointer being passed to the app. --- src/d3d11/d3d11_context_imm.cpp | 22 ++++++++-------------- src/d3d11/d3d11_device.cpp | 6 +----- src/d3d11/d3d11_texture.cpp | 3 +++ src/d3d11/d3d11_texture.h | 29 ++++++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index a97df7222..0231c4a02 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -417,9 +417,6 @@ namespace dxvk { D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - const Rc mappedImage = pResource->GetImage(); - const Rc mappedBuffer = pResource->GetMappedBuffer(Subresource); - auto mapMode = pResource->GetMapMode(); if (pMappedResource) @@ -449,9 +446,10 @@ namespace dxvk { uint64_t sequenceNumber = pResource->GetSequenceNumber(Subresource); auto formatInfo = lookupFormatInfo(packedFormat); - void* mapPtr; if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { + Rc mappedImage = pResource->GetImage(); + // Wait for the resource to become available. We do not // support image renaming, so stall on DISCARD instead. if (MapType == D3D11_MAP_WRITE_DISCARD) @@ -461,11 +459,9 @@ namespace dxvk { if (!WaitForResource(*mappedImage, sequenceNumber, MapType, MapFlags)) return DXGI_ERROR_WAS_STILL_DRAWING; } - - // Query the subresource's memory layout and hope that - // the application respects the returned pitch values. - mapPtr = mappedImage->mapPtr(0); } else { + Rc mappedBuffer = pResource->GetMappedBuffer(Subresource); + constexpr uint32_t DoInvalidate = (1u << 0); constexpr uint32_t DoPreserve = (1u << 1); constexpr uint32_t DoWait = (1u << 2); @@ -536,17 +532,17 @@ namespace dxvk { auto dstSlice = pResource->DiscardSlice(Subresource); auto srcPtr = srcSlice->mapPtr(); - mapPtr = dstSlice->mapPtr(); + auto dstPtr = dstSlice->mapPtr(); EmitCs([ - cImageBuffer = mappedBuffer, + cImageBuffer = std::move(mappedBuffer), cImageBufferSlice = std::move(dstSlice) ] (DxvkContext* ctx) mutable { ctx->invalidateBuffer(cImageBuffer, std::move(cImageBufferSlice)); }); if (doFlags & DoPreserve) - std::memcpy(mapPtr, srcPtr, bufferSize); + std::memcpy(dstPtr, srcPtr, bufferSize); ThrottleDiscard(bufferSize); } else { @@ -560,8 +556,6 @@ namespace dxvk { if (!WaitForResource(*mappedBuffer, sequenceNumber, MapType, MapFlags)) return DXGI_ERROR_WAS_STILL_DRAWING; } - - mapPtr = pResource->GetMappedSlice(Subresource)->mapPtr(); } } @@ -570,7 +564,7 @@ namespace dxvk { if (pMappedResource) { auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource); - pMappedResource->pData = reinterpret_cast(mapPtr) + layout.Offset; + pMappedResource->pData = pResource->GetMapPtr(Subresource, layout.Offset); pMappedResource->RowPitch = layout.RowPitch; pMappedResource->DepthPitch = layout.DepthPitch; } diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 4bd8731d5..5535dd3bd 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -2435,11 +2435,7 @@ namespace dxvk { D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = pTexture->GetSubresourceLayout(aspect, Subresource); // Compute actual map pointer, accounting for the region offset - VkDeviceSize mapOffset = pTexture->ComputeMappedOffset(Subresource, i, offset); - - void* mapPtr = pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER - ? pTexture->GetMappedBuffer(Subresource)->mapPtr(mapOffset) - : image->mapPtr(mapOffset); + void* mapPtr = pTexture->GetMapPtr(Subresource, pTexture->ComputeMappedOffset(Subresource, i, offset)); if constexpr (std::is_const::value) { // WriteToSubresource diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index f35a03513..e70dfef08 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -244,6 +244,9 @@ namespace dxvk { else m_image = m_device->GetDXVKDevice()->importImage(imageInfo, vkImage, memoryProperties); + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) + m_mapPtr = m_image->mapPtr(0); + if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export) ExportImageInfo(); } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index a3134ed69..de4f1c774 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -303,6 +303,31 @@ namespace dxvk { } } + /** + * \brief Queries map pointer of the raw image + * + * If the image is mapped directly, the returned pointer will + * point directly to the image, otherwise it will point to a + * buffer that contains image data. + * \param [in] Subresource Subresource index + * \param [in] Offset Offset derived from the subresource layout + */ + void* GetMapPtr(uint32_t Subresource, size_t Offset) const { + switch (m_mapMode) { + case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT: + return reinterpret_cast(m_mapPtr) + Offset; + + case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER: + case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: + return reinterpret_cast(m_buffers[Subresource].slice->mapPtr()) + Offset; + + case D3D11_COMMON_TEXTURE_MAP_MODE_NONE: + return nullptr; + } + + return nullptr; + } + /** * \brief Adds a dirty region * @@ -503,7 +528,9 @@ namespace dxvk { Rc m_image; std::vector m_buffers; std::vector m_mapInfo; - + + void* m_mapPtr = nullptr; + MappedBuffer CreateMappedBuffer( UINT MipLevel) const;