mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-06 20:58:37 +01:00
[d3d11] Always use fast MAP_WRITE_DISCARD path on deferred contexts
... but keep the SingleUse option as-is anyway because games do not release their command lists after submission and end up wasting massive amounts of memory.
This commit is contained in:
parent
39f50999a3
commit
5e5c283149
2 changed files with 15 additions and 33 deletions
|
@ -154,9 +154,11 @@
|
||||||
# dxvk.tearFree = Auto
|
# dxvk.tearFree = Auto
|
||||||
|
|
||||||
|
|
||||||
# Assume single-use mode for command lists created on deferred contexts.
|
# Assume that command lists created from deferred contexts are only used
|
||||||
# This may need to be disabled for some applications to avoid rendering
|
# once. This is extremely common and may improve performance while reducing
|
||||||
# issues, which may come at a significant performance cost.
|
# 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
|
# Supported values: True, False
|
||||||
|
|
||||||
|
|
|
@ -265,44 +265,24 @@ namespace dxvk {
|
||||||
ID3D11Resource* pResource,
|
ID3D11Resource* pResource,
|
||||||
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
|
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
|
||||||
D3D11Buffer* pBuffer = static_cast<D3D11Buffer*>(pResource);
|
D3D11Buffer* pBuffer = static_cast<D3D11Buffer*>(pResource);
|
||||||
|
|
||||||
if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
|
if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
|
||||||
Logger::err("D3D11: Cannot map a device-local buffer");
|
Logger::err("D3D11: Cannot map a device-local buffer");
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto bufferSlice = pBuffer->AllocSlice(&m_allocationCache);
|
||||||
|
pMappedResource->pData = bufferSlice->mapPtr();
|
||||||
pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth;
|
pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth;
|
||||||
pMappedResource->DepthPitch = 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([
|
EmitCs([
|
||||||
cDstBuffer = pBuffer->GetBuffer(),
|
cDstBuffer = pBuffer->GetBuffer(),
|
||||||
cDstSlice = std::move(bufferSlice)
|
cDstSlice = std::move(bufferSlice)
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
ctx->invalidateBuffer(cDstBuffer, Rc<DxvkResourceAllocation>(cDstSlice));
|
ctx->invalidateBuffer(cDstBuffer, Rc<DxvkResourceAllocation>(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<DxvkResourceAllocation> slice = cDstBuffer->allocateSlice();
|
|
||||||
std::memcpy(slice->mapPtr(), cDataSlice.ptr(), cDataSlice.length());
|
|
||||||
ctx->invalidateBuffer(cDstBuffer, std::move(slice));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue