mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +01:00
[d3d11] Implement dirty trackig for default-mapped images
Avoids GPU synchronization when using WriteToSubresource, and also reduces bandwidth.
This commit is contained in:
parent
40ffac72d9
commit
fdcbdeb28f
@ -481,9 +481,16 @@ namespace dxvk {
|
|||||||
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) {
|
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) {
|
||||||
// If the image can be written by the GPU, we need to update the
|
// If the image can be written by the GPU, we need to update the
|
||||||
// mapped staging buffer to reflect the current image contents.
|
// mapped staging buffer to reflect the current image contents.
|
||||||
if (pResource->Desc()->Usage == D3D11_USAGE_DEFAULT)
|
if (pResource->Desc()->Usage == D3D11_USAGE_DEFAULT) {
|
||||||
|
bool needsReadback = !pResource->NeedsDirtyRegionTracking();
|
||||||
|
|
||||||
|
needsReadback |= MapType == D3D11_MAP_READ
|
||||||
|
|| MapType == D3D11_MAP_READ_WRITE;
|
||||||
|
|
||||||
|
if (needsReadback)
|
||||||
ReadbackImageBuffer(pResource, Subresource);
|
ReadbackImageBuffer(pResource, Subresource);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MapType == D3D11_MAP_READ) {
|
if (MapType == D3D11_MAP_READ) {
|
||||||
// Reads will not change the image content, so we only need
|
// Reads will not change the image content, so we only need
|
||||||
@ -591,14 +598,16 @@ namespace dxvk {
|
|||||||
m_mappedImageCount -= 1;
|
m_mappedImageCount -= 1;
|
||||||
|
|
||||||
if ((mapType != D3D11_MAP_READ) && (pResource->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER)) {
|
if ((mapType != D3D11_MAP_READ) && (pResource->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER)) {
|
||||||
// Now that data has been written into the buffer,
|
if (pResource->NeedsDirtyRegionTracking()) {
|
||||||
// we need to copy its contents into the image
|
for (uint32_t i = 0; i < pResource->GetDirtyRegionCount(Subresource); i++) {
|
||||||
VkImageAspectFlags aspectMask = lookupFormatInfo(pResource->GetPackedFormat())->aspectMask;
|
D3D11_COMMON_TEXTURE_REGION region = pResource->GetDirtyRegion(Subresource, i);
|
||||||
VkImageSubresource subresource = pResource->GetSubresourceFromIndex(aspectMask, Subresource);
|
UpdateDirtyImageRegion(pResource, Subresource, ®ion);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateImage(pResource, &subresource, VkOffset3D { 0, 0, 0 },
|
pResource->ClearDirtyRegions(Subresource);
|
||||||
pResource->MipLevelExtent(subresource.mipLevel),
|
} else {
|
||||||
DxvkBufferSlice(pResource->GetMappedBuffer(Subresource)));
|
UpdateDirtyImageRegion(pResource, Subresource, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,6 +646,67 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11ImmediateContext::UpdateDirtyImageRegion(
|
||||||
|
D3D11CommonTexture* pResource,
|
||||||
|
UINT Subresource,
|
||||||
|
const D3D11_COMMON_TEXTURE_REGION* pRegion) {
|
||||||
|
auto formatInfo = lookupFormatInfo(pResource->GetPackedFormat());
|
||||||
|
auto subresource = vk::makeSubresourceLayers(
|
||||||
|
pResource->GetSubresourceFromIndex(formatInfo->aspectMask, Subresource));
|
||||||
|
|
||||||
|
// Update the entire image if no dirty region was specified
|
||||||
|
D3D11_COMMON_TEXTURE_REGION region;
|
||||||
|
|
||||||
|
if (pRegion) {
|
||||||
|
region = *pRegion;
|
||||||
|
} else {
|
||||||
|
region.Offset = VkOffset3D { 0, 0, 0 };
|
||||||
|
region.Extent = pResource->MipLevelExtent(subresource.mipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto subresourceLayout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
|
||||||
|
|
||||||
|
// Update dirty region one aspect at a time, due to
|
||||||
|
// how the data is laid out in the staging buffer.
|
||||||
|
for (uint32_t i = 0; i < pResource->GetPlaneCount(); i++) {
|
||||||
|
subresource.aspectMask = formatInfo->aspectMask;
|
||||||
|
|
||||||
|
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane))
|
||||||
|
subresource.aspectMask = vk::getPlaneAspect(i);
|
||||||
|
|
||||||
|
EmitCs([
|
||||||
|
cDstImage = pResource->GetImage(),
|
||||||
|
cDstSubresource = subresource,
|
||||||
|
cDstOffset = region.Offset,
|
||||||
|
cDstExtent = region.Extent,
|
||||||
|
cSrcBuffer = pResource->GetMappedBuffer(Subresource),
|
||||||
|
cSrcOffset = pResource->ComputeMappedOffset(Subresource, i, region.Offset),
|
||||||
|
cSrcRowPitch = subresourceLayout.RowPitch,
|
||||||
|
cSrcDepthPitch = subresourceLayout.DepthPitch,
|
||||||
|
cPackedFormat = pResource->GetPackedFormat()
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
if (cDstSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||||
|
ctx->copyBufferToImage(
|
||||||
|
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
|
||||||
|
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch);
|
||||||
|
} else {
|
||||||
|
ctx->copyPackedBufferToDepthStencilImage(
|
||||||
|
cDstImage, cDstSubresource,
|
||||||
|
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||||
|
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||||
|
cSrcBuffer, 0,
|
||||||
|
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||||
|
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||||
|
cPackedFormat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pResource->HasSequenceNumber())
|
||||||
|
TrackTextureSequenceNumber(pResource, Subresource);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11ImmediateContext::UpdateMappedBuffer(
|
void D3D11ImmediateContext::UpdateMappedBuffer(
|
||||||
D3D11Buffer* pDstBuffer,
|
D3D11Buffer* pDstBuffer,
|
||||||
UINT Offset,
|
UINT Offset,
|
||||||
|
@ -124,6 +124,11 @@ namespace dxvk {
|
|||||||
D3D11CommonTexture* pResource,
|
D3D11CommonTexture* pResource,
|
||||||
UINT Subresource);
|
UINT Subresource);
|
||||||
|
|
||||||
|
void UpdateDirtyImageRegion(
|
||||||
|
D3D11CommonTexture* pResource,
|
||||||
|
UINT Subresource,
|
||||||
|
const D3D11_COMMON_TEXTURE_REGION* pRegion);
|
||||||
|
|
||||||
void UpdateMappedBuffer(
|
void UpdateMappedBuffer(
|
||||||
D3D11Buffer* pDstBuffer,
|
D3D11Buffer* pDstBuffer,
|
||||||
UINT Offset,
|
UINT Offset,
|
||||||
|
@ -2348,6 +2348,10 @@ namespace dxvk {
|
|||||||
dataOffset += util::computeImageDataSize(
|
dataOffset += util::computeImageDataSize(
|
||||||
pTexture->GetPackedFormat(), extent, aspect);
|
pTexture->GetPackedFormat(), extent, aspect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track dirty texture region if necessary
|
||||||
|
if constexpr (std::is_const<Void>::value)
|
||||||
|
pTexture->AddDirtyRegion(Subresource, offset, extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -342,13 +342,13 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves dirty regions
|
* \brief Queries a dirty regions
|
||||||
*
|
*
|
||||||
* \param [in] Subresource Subresource index
|
* \param [in] Subresource Subresource index
|
||||||
* \param [in] Region Region index
|
* \param [in] Region Region index
|
||||||
* \returns Dirty region
|
* \returns Dirty region
|
||||||
*/
|
*/
|
||||||
D3D11_COMMON_TEXTURE_REGION GetDirtyRegionCount(UINT Subresource, UINT Region) {
|
D3D11_COMMON_TEXTURE_REGION GetDirtyRegion(UINT Subresource, UINT Region) {
|
||||||
return m_buffers[Subresource].dirtyRegions[Region];
|
return m_buffers[Subresource].dirtyRegions[Region];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user