1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-13 19:29:14 +01:00

[d3d11] Update mapped buffers of staging textures immediately

Improves performance in Lords of the Fallen and The Surge.
Closes #1049.

Co-authored-by: Robin <robin.kertels@outlook.com>
This commit is contained in:
Philip Rebohle 2019-05-17 12:44:36 +02:00
parent 905f3fe520
commit 8e9e7963a2
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 78 additions and 26 deletions

View File

@ -554,6 +554,9 @@ namespace dxvk {
cExtent);
}
});
if (dstTextureInfo->CanUpdateMappedBufferEarly())
UpdateMappedBuffer(dstTextureInfo, dstSubresource);
}
}
@ -604,8 +607,11 @@ namespace dxvk {
cSrcBuffer.length());
});
} else {
const Rc<DxvkImage> dstImage = GetCommonTexture(pDstResource)->GetImage();
const Rc<DxvkImage> srcImage = GetCommonTexture(pSrcResource)->GetImage();
auto dstTexture = GetCommonTexture(pDstResource);
auto srcTexture = GetCommonTexture(pSrcResource);
const Rc<DxvkImage> dstImage = dstTexture->GetImage();
const Rc<DxvkImage> srcImage = srcTexture->GetImage();
const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstImage->info().format);
const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcImage->info().format);
@ -652,6 +658,11 @@ namespace dxvk {
cSrcImage, cSrcLayers, VkOffset3D { 0, 0, 0 },
cExtent);
});
if (dstTexture->CanUpdateMappedBufferEarly()) {
for (uint32_t j = 0; j < dstImage->info().numLayers; j++)
UpdateMappedBuffer(dstTexture, { dstLayers.aspectMask, i, j });
}
}
}
}
@ -1229,6 +1240,9 @@ namespace dxvk {
cPackedFormat);
}
});
if (textureInfo->CanUpdateMappedBufferEarly())
UpdateMappedBuffer(textureInfo, subresource);
}
}
@ -3667,6 +3681,40 @@ namespace dxvk {
ctrSlotId + i, ~0u);
}
}
void D3D11DeviceContext::UpdateMappedBuffer(
const D3D11CommonTexture* pTexture,
VkImageSubresource Subresource) {
Rc<DxvkImage> mappedImage = pTexture->GetImage();
Rc<DxvkBuffer> mappedBuffer = pTexture->GetMappedBuffer();
VkFormat packedFormat = m_parent->LookupPackedFormat(
pTexture->Desc()->Format, pTexture->GetFormatMode()).Format;
VkExtent3D levelExtent = mappedImage->mipLevelExtent(Subresource.mipLevel);
EmitCs([
cImageBuffer = std::move(mappedBuffer),
cImage = std::move(mappedImage),
cSubresources = vk::makeSubresourceLayers(Subresource),
cLevelExtent = levelExtent,
cPackedFormat = packedFormat
] (DxvkContext* ctx) {
if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyImageToBuffer(
cImageBuffer, 0, VkExtent2D { 0u, 0u },
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
cLevelExtent);
} else {
ctx->copyDepthStencilImageToPackedBuffer(
cImageBuffer, 0, cImage, cSubresources,
VkOffset2D { 0, 0 },
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
cPackedFormat);
}
});
}
bool D3D11DeviceContext::ValidateRenderTargets(

View File

@ -803,6 +803,10 @@ namespace dxvk {
DxbcProgramType Stage,
D3D11UnorderedAccessBindings& Bindings);
void UpdateMappedBuffer(
const D3D11CommonTexture* pTexture,
VkImageSubresource Subresource);
bool ValidateRenderTargets(
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,

View File

@ -383,32 +383,16 @@ namespace dxvk {
// When using any map mode which requires the image contents
// to be preserved, and if the GPU has write access to the
// image, copy the current image contents into the buffer.
if (pResource->Desc()->Usage == D3D11_USAGE_STAGING) {
auto subresourceLayers = vk::makeSubresourceLayers(subresource);
EmitCs([
cImageBuffer = mappedBuffer,
cImage = mappedImage,
cSubresources = subresourceLayers,
cLevelExtent = levelExtent,
cPackedFormat = packedFormat
] (DxvkContext* ctx) {
if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyImageToBuffer(
cImageBuffer, 0, VkExtent2D { 0u, 0u },
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
cLevelExtent);
} else {
ctx->copyDepthStencilImageToPackedBuffer(
cImageBuffer, 0, cImage, cSubresources,
VkOffset2D { 0, 0 },
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
cPackedFormat);
}
});
if (pResource->Desc()->Usage == D3D11_USAGE_STAGING
&& !pResource->CanUpdateMappedBufferEarly()) {
UpdateMappedBuffer(pResource, subresource);
MapFlags &= ~D3D11_MAP_FLAG_DO_NOT_WAIT;
}
WaitForResource(mappedBuffer, 0);
// Wait for mapped buffer to become available
if (!WaitForResource(mappedBuffer, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING;
physSlice = mappedBuffer->getSliceHandle();
}

View File

@ -130,6 +130,22 @@ namespace dxvk {
void ClearMappedSubresource() {
m_mappedSubresource = VkImageSubresource { };
}
/**
* \brief Checks whether we can update the mapped buffer early
*
* For images which are mapped through a buffer and that are
* only used for transfer operations, we can update the mapped
* buffer right after performing those transfers to avoid stalls.
* \returns \c true if the mapped buffer can be updated early
*/
bool CanUpdateMappedBufferEarly() const {
return m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER
&& (m_desc.BindFlags & ~D3D11_BIND_SHADER_RESOURCE) == 0
&& m_desc.Usage == D3D11_USAGE_STAGING
&& m_desc.MipLevels == 1
&& m_desc.ArraySize == 1;
}
/**
* \brief Computes subresource from the subresource index