diff --git a/dxvk.conf b/dxvk.conf index e8931913cce..3416dd4dc86 100644 --- a/dxvk.conf +++ b/dxvk.conf @@ -154,9 +154,11 @@ # dxvk.tearFree = Auto -# Assume single-use mode for command lists created on deferred contexts. -# This may need to be disabled for some applications to avoid rendering -# issues, which may come at a significant performance cost. +# Assume that command lists created from deferred contexts are only used +# once. This is extremely common and may improve performance while reducing +# the amount of memory wasted if games keep their command list objects alive +# for too long, but may also lead to rendering issues if command lists are +# submitted multiple times. # # Supported values: True, False diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 2e1a0bfed55..66f78a40aa1 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -265,44 +265,24 @@ namespace dxvk { ID3D11Resource* pResource, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11Buffer* pBuffer = static_cast(pResource); - + if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) { Logger::err("D3D11: Cannot map a device-local buffer"); return E_INVALIDARG; } - + + auto bufferSlice = pBuffer->AllocSlice(&m_allocationCache); + pMappedResource->pData = bufferSlice->mapPtr(); pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth; pMappedResource->DepthPitch = pBuffer->Desc()->ByteWidth; - - if (likely(m_csFlags.test(DxvkCsChunkFlag::SingleUse))) { - // For resources that cannot be written by the GPU, - // we may write to the buffer resource directly and - // just swap in the buffer slice as needed. - auto bufferSlice = pBuffer->AllocSlice(&m_allocationCache); - pMappedResource->pData = bufferSlice->mapPtr(); - - EmitCs([ - cDstBuffer = pBuffer->GetBuffer(), - cDstSlice = std::move(bufferSlice) - ] (DxvkContext* ctx) { - ctx->invalidateBuffer(cDstBuffer, Rc(cDstSlice)); - }); - } else { - // For GPU-writable resources, we need a data slice - // to perform the update operation at execution time. - auto dataSlice = AllocUpdateBufferSlice(pBuffer->Desc()->ByteWidth); - pMappedResource->pData = dataSlice.ptr(); - - EmitCs([ - cDstBuffer = pBuffer->GetBuffer(), - cDataSlice = dataSlice - ] (DxvkContext* ctx) { - Rc slice = cDstBuffer->allocateSlice(); - std::memcpy(slice->mapPtr(), cDataSlice.ptr(), cDataSlice.length()); - ctx->invalidateBuffer(cDstBuffer, std::move(slice)); - }); - } - + + EmitCs([ + cDstBuffer = pBuffer->GetBuffer(), + cDstSlice = std::move(bufferSlice) + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cDstBuffer, Rc(cDstSlice)); + }); + return S_OK; }