mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d11] Throttle resource uploads via UpdateSubresource
Otherwise, some games (e.g. Frostpunk, New World) end up allocating over a gigabyte of staging memory.
This commit is contained in:
parent
ec18dd7846
commit
df60a061a4
@ -3010,6 +3010,9 @@ namespace dxvk {
|
||||
CopyTiledResourceData(pDestTiledResource,
|
||||
pDestTileRegionStartCoordinate,
|
||||
pDestTileRegionSize, slice, Flags);
|
||||
|
||||
if constexpr (!IsDeferred)
|
||||
static_cast<ContextType*>(this)->ThrottleAllocation();
|
||||
}
|
||||
|
||||
|
||||
@ -5099,6 +5102,9 @@ namespace dxvk {
|
||||
|
||||
if (pDstBuffer->HasSequenceNumber())
|
||||
GetTypedContext()->TrackBufferSequenceNumber(pDstBuffer);
|
||||
|
||||
if constexpr (!IsDeferred)
|
||||
static_cast<ContextType*>(this)->ThrottleAllocation();
|
||||
}
|
||||
|
||||
|
||||
@ -5151,6 +5157,9 @@ namespace dxvk {
|
||||
|
||||
UpdateImage(pDstTexture, &subresource,
|
||||
offset, extent, std::move(stagingSlice));
|
||||
|
||||
if constexpr (!IsDeferred)
|
||||
static_cast<ContextType*>(this)->ThrottleAllocation();
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,6 +20,7 @@ namespace dxvk {
|
||||
m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize),
|
||||
m_submissionFence(new sync::CallbackFence()),
|
||||
m_flushTracker(pParent->GetOptions()->reproducibleCommandStream),
|
||||
m_stagingBufferFence(new sync::Fence(0)),
|
||||
m_multithread(this, false, pParent->GetOptions()->enableContextLock),
|
||||
m_videoContext(this, Device) {
|
||||
EmitCs([
|
||||
@ -956,9 +957,12 @@ namespace dxvk {
|
||||
EmitCs<false>([
|
||||
cSubmissionFence = m_submissionFence,
|
||||
cSubmissionId = submissionId,
|
||||
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr
|
||||
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr,
|
||||
cStagingFence = m_stagingBufferFence,
|
||||
cStagingMemory = m_staging.getStatistics().allocatedTotal
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->signal(cSubmissionFence, cSubmissionId);
|
||||
ctx->signal(cStagingFence, cStagingMemory);
|
||||
ctx->flushCommandList(cSubmissionStatus);
|
||||
});
|
||||
|
||||
@ -977,5 +981,25 @@ namespace dxvk {
|
||||
// end up with a persistent allocation
|
||||
ResetStagingBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void D3D11ImmediateContext::ThrottleAllocation() {
|
||||
DxvkStagingBufferStats stats = m_staging.getStatistics();
|
||||
|
||||
VkDeviceSize stagingMemoryInFlight = stats.allocatedTotal - m_stagingBufferFence->value();
|
||||
|
||||
if (stagingMemoryInFlight > stats.allocatedSinceLastReset + D3D11Initializer::MaxMemoryInFlight) {
|
||||
// Stall calling thread to avoid situation where we keep growing the staging
|
||||
// buffer indefinitely, but ignore the newly allocated amount so that we don't
|
||||
// wait for the GPU to go fully idle in case of a large allocation.
|
||||
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
||||
|
||||
m_stagingBufferFence->wait(stats.allocatedTotal - stats.allocatedSinceLastReset - D3D11Initializer::MaxMemoryInFlight);
|
||||
} else if (stats.allocatedSinceLastReset >= D3D11Initializer::MaxMemoryPerSubmission) {
|
||||
// Flush somewhat aggressively if there's a lot of memory in flight
|
||||
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -126,11 +126,13 @@ namespace dxvk {
|
||||
uint64_t m_flushSeqNum = 0ull;
|
||||
GpuFlushTracker m_flushTracker;
|
||||
|
||||
Rc<sync::Fence> m_stagingBufferFence;
|
||||
|
||||
D3D10Multithread m_multithread;
|
||||
D3D11VideoContext m_videoContext;
|
||||
|
||||
Com<D3D11DeviceContextState, false> m_stateObject;
|
||||
|
||||
|
||||
HRESULT MapBuffer(
|
||||
D3D11Buffer* pResource,
|
||||
D3D11_MAP MapType,
|
||||
@ -195,6 +197,8 @@ namespace dxvk {
|
||||
HANDLE hEvent,
|
||||
BOOL Synchronize);
|
||||
|
||||
void ThrottleAllocation();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user