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

[d3d11] Add GetMapPtr method to D3D11CommonTexture

Fixes a bug in Read/WriteSubresource where discards result in the wrong
pointer being passed to the app.
This commit is contained in:
Philip Rebohle 2024-10-29 22:00:20 +01:00 committed by Philip Rebohle
parent 81bdf191cb
commit 1832332d6d
4 changed files with 40 additions and 20 deletions

View File

@ -417,9 +417,6 @@ namespace dxvk {
D3D11_MAP MapType, D3D11_MAP MapType,
UINT MapFlags, UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
const Rc<DxvkImage> mappedImage = pResource->GetImage();
const Rc<DxvkBuffer> mappedBuffer = pResource->GetMappedBuffer(Subresource);
auto mapMode = pResource->GetMapMode(); auto mapMode = pResource->GetMapMode();
if (pMappedResource) if (pMappedResource)
@ -449,9 +446,10 @@ namespace dxvk {
uint64_t sequenceNumber = pResource->GetSequenceNumber(Subresource); uint64_t sequenceNumber = pResource->GetSequenceNumber(Subresource);
auto formatInfo = lookupFormatInfo(packedFormat); auto formatInfo = lookupFormatInfo(packedFormat);
void* mapPtr;
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
Rc<DxvkImage> mappedImage = pResource->GetImage();
// Wait for the resource to become available. We do not // Wait for the resource to become available. We do not
// support image renaming, so stall on DISCARD instead. // support image renaming, so stall on DISCARD instead.
if (MapType == D3D11_MAP_WRITE_DISCARD) if (MapType == D3D11_MAP_WRITE_DISCARD)
@ -461,11 +459,9 @@ namespace dxvk {
if (!WaitForResource(*mappedImage, sequenceNumber, MapType, MapFlags)) if (!WaitForResource(*mappedImage, sequenceNumber, MapType, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING; 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 { } else {
Rc<DxvkBuffer> mappedBuffer = pResource->GetMappedBuffer(Subresource);
constexpr uint32_t DoInvalidate = (1u << 0); constexpr uint32_t DoInvalidate = (1u << 0);
constexpr uint32_t DoPreserve = (1u << 1); constexpr uint32_t DoPreserve = (1u << 1);
constexpr uint32_t DoWait = (1u << 2); constexpr uint32_t DoWait = (1u << 2);
@ -536,17 +532,17 @@ namespace dxvk {
auto dstSlice = pResource->DiscardSlice(Subresource); auto dstSlice = pResource->DiscardSlice(Subresource);
auto srcPtr = srcSlice->mapPtr(); auto srcPtr = srcSlice->mapPtr();
mapPtr = dstSlice->mapPtr(); auto dstPtr = dstSlice->mapPtr();
EmitCs([ EmitCs([
cImageBuffer = mappedBuffer, cImageBuffer = std::move(mappedBuffer),
cImageBufferSlice = std::move(dstSlice) cImageBufferSlice = std::move(dstSlice)
] (DxvkContext* ctx) mutable { ] (DxvkContext* ctx) mutable {
ctx->invalidateBuffer(cImageBuffer, std::move(cImageBufferSlice)); ctx->invalidateBuffer(cImageBuffer, std::move(cImageBufferSlice));
}); });
if (doFlags & DoPreserve) if (doFlags & DoPreserve)
std::memcpy(mapPtr, srcPtr, bufferSize); std::memcpy(dstPtr, srcPtr, bufferSize);
ThrottleDiscard(bufferSize); ThrottleDiscard(bufferSize);
} else { } else {
@ -560,8 +556,6 @@ namespace dxvk {
if (!WaitForResource(*mappedBuffer, sequenceNumber, MapType, MapFlags)) if (!WaitForResource(*mappedBuffer, sequenceNumber, MapType, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING; return DXGI_ERROR_WAS_STILL_DRAWING;
} }
mapPtr = pResource->GetMappedSlice(Subresource)->mapPtr();
} }
} }
@ -570,7 +564,7 @@ namespace dxvk {
if (pMappedResource) { if (pMappedResource) {
auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource); auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
pMappedResource->pData = reinterpret_cast<char*>(mapPtr) + layout.Offset; pMappedResource->pData = pResource->GetMapPtr(Subresource, layout.Offset);
pMappedResource->RowPitch = layout.RowPitch; pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch; pMappedResource->DepthPitch = layout.DepthPitch;
} }

View File

@ -2435,11 +2435,7 @@ namespace dxvk {
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = pTexture->GetSubresourceLayout(aspect, Subresource); D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = pTexture->GetSubresourceLayout(aspect, Subresource);
// Compute actual map pointer, accounting for the region offset // Compute actual map pointer, accounting for the region offset
VkDeviceSize mapOffset = pTexture->ComputeMappedOffset(Subresource, i, offset); void* mapPtr = pTexture->GetMapPtr(Subresource, pTexture->ComputeMappedOffset(Subresource, i, offset));
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

View File

@ -244,6 +244,9 @@ namespace dxvk {
else else
m_image = m_device->GetDXVKDevice()->importImage(imageInfo, vkImage, memoryProperties); 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) if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export)
ExportImageInfo(); ExportImageInfo();
} }

View File

@ -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<char*>(m_mapPtr) + Offset;
case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER:
case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING:
return reinterpret_cast<char*>(m_buffers[Subresource].slice->mapPtr()) + Offset;
case D3D11_COMMON_TEXTURE_MAP_MODE_NONE:
return nullptr;
}
return nullptr;
}
/** /**
* \brief Adds a dirty region * \brief Adds a dirty region
* *
@ -504,6 +529,8 @@ namespace dxvk {
std::vector<MappedBuffer> m_buffers; std::vector<MappedBuffer> m_buffers;
std::vector<MappedInfo> m_mapInfo; std::vector<MappedInfo> m_mapInfo;
void* m_mapPtr = nullptr;
MappedBuffer CreateMappedBuffer( MappedBuffer CreateMappedBuffer(
UINT MipLevel) const; UINT MipLevel) const;