1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 23:52:20 +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,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
const Rc<DxvkImage> mappedImage = pResource->GetImage();
const Rc<DxvkBuffer> 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<DxvkImage> 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<DxvkBuffer> 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<char*>(mapPtr) + layout.Offset;
pMappedResource->pData = pResource->GetMapPtr(Subresource, layout.Offset);
pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch;
}

View File

@ -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<Void>::value) {
// WriteToSubresource

View File

@ -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();
}

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
*
@ -504,6 +529,8 @@ namespace dxvk {
std::vector<MappedBuffer> m_buffers;
std::vector<MappedInfo> m_mapInfo;
void* m_mapPtr = nullptr;
MappedBuffer CreateMappedBuffer(
UINT MipLevel) const;