mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-20 08:52:22 +01:00
[d3d11] Consider discards when throttling immediate context
This commit is contained in:
parent
65aa74aa7f
commit
f9bb8f0ad5
@ -341,6 +341,11 @@ namespace dxvk {
|
|||||||
ctx->invalidateBuffer(cBuffer, std::move(cBufferSlice));
|
ctx->invalidateBuffer(cBuffer, std::move(cBufferSlice));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ignore small buffers here. These are often updated per
|
||||||
|
// draw and won't contribute much to memory waste anyway.
|
||||||
|
if (unlikely(bufferSize > DxvkPageAllocator::PageSize))
|
||||||
|
ThrottleDiscard(bufferSize);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
} else if (likely(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)) {
|
} else if (likely(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)) {
|
||||||
// Put this on a fast path without any extra checks since it's
|
// Put this on a fast path without any extra checks since it's
|
||||||
@ -360,7 +365,7 @@ namespace dxvk {
|
|||||||
auto buffer = pResource->GetBuffer();
|
auto buffer = pResource->GetBuffer();
|
||||||
auto sequenceNumber = pResource->GetSequenceNumber();
|
auto sequenceNumber = pResource->GetSequenceNumber();
|
||||||
|
|
||||||
if (MapType != D3D11_MAP_READ && !MapFlags && bufferSize <= m_maxImplicitDiscardSize) {
|
if (MapType != D3D11_MAP_READ && !MapFlags && bufferSize <= D3D11Initializer::MaxMemoryPerSubmission) {
|
||||||
SynchronizeCsThread(sequenceNumber);
|
SynchronizeCsThread(sequenceNumber);
|
||||||
|
|
||||||
bool hasWoAccess = buffer->isInUse(DxvkAccess::Write);
|
bool hasWoAccess = buffer->isInUse(DxvkAccess::Write);
|
||||||
@ -389,6 +394,8 @@ namespace dxvk {
|
|||||||
pMappedResource->pData = dstPtr;
|
pMappedResource->pData = dstPtr;
|
||||||
pMappedResource->RowPitch = bufferSize;
|
pMappedResource->RowPitch = bufferSize;
|
||||||
pMappedResource->DepthPitch = bufferSize;
|
pMappedResource->DepthPitch = bufferSize;
|
||||||
|
|
||||||
|
ThrottleDiscard(bufferSize);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
} else {
|
} else {
|
||||||
if (!WaitForResource(*buffer, sequenceNumber, MapType, MapFlags)) {
|
if (!WaitForResource(*buffer, sequenceNumber, MapType, MapFlags)) {
|
||||||
@ -497,11 +504,11 @@ namespace dxvk {
|
|||||||
// Need to synchronize thread to determine pending GPU accesses
|
// Need to synchronize thread to determine pending GPU accesses
|
||||||
SynchronizeCsThread(sequenceNumber);
|
SynchronizeCsThread(sequenceNumber);
|
||||||
|
|
||||||
// Don't implicitly discard large buffers or buffers of images with
|
// Don't implicitly discard large very large resources
|
||||||
// multiple subresources, as that is likely to cause memory issues.
|
// since that might lead to memory issues.
|
||||||
VkDeviceSize bufferSize = mappedBuffer->info().size;
|
VkDeviceSize bufferSize = mappedBuffer->info().size;
|
||||||
|
|
||||||
if (bufferSize >= m_maxImplicitDiscardSize || pResource->CountSubresources() > 1) {
|
if (bufferSize > D3D11Initializer::MaxMemoryPerSubmission) {
|
||||||
// Don't check access flags, WaitForResource will return
|
// Don't check access flags, WaitForResource will return
|
||||||
// early anyway if the resource is currently in use
|
// early anyway if the resource is currently in use
|
||||||
doFlags = DoWait;
|
doFlags = DoWait;
|
||||||
@ -541,6 +548,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (doFlags & DoPreserve)
|
if (doFlags & DoPreserve)
|
||||||
std::memcpy(mapPtr, srcPtr, bufferSize);
|
std::memcpy(mapPtr, srcPtr, bufferSize);
|
||||||
|
|
||||||
|
ThrottleDiscard(bufferSize);
|
||||||
} else {
|
} else {
|
||||||
if (doFlags & DoWait) {
|
if (doFlags & DoWait) {
|
||||||
// We cannot respect DO_NOT_WAIT for buffer-mapped resources since
|
// We cannot respect DO_NOT_WAIT for buffer-mapped resources since
|
||||||
@ -955,7 +964,7 @@ namespace dxvk {
|
|||||||
cSubmissionId = submissionId,
|
cSubmissionId = submissionId,
|
||||||
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr,
|
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr,
|
||||||
cStagingFence = m_stagingBufferFence,
|
cStagingFence = m_stagingBufferFence,
|
||||||
cStagingMemory = m_staging.getStatistics().allocatedTotal
|
cStagingMemory = GetStagingMemoryStatistics().allocatedTotal
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
ctx->signal(cSubmissionFence, cSubmissionId);
|
ctx->signal(cSubmissionFence, cSubmissionId);
|
||||||
ctx->signal(cStagingFence, cStagingMemory);
|
ctx->signal(cStagingFence, cStagingMemory);
|
||||||
@ -977,6 +986,9 @@ namespace dxvk {
|
|||||||
// end up with a persistent allocation
|
// end up with a persistent allocation
|
||||||
ResetStagingBuffer();
|
ResetStagingBuffer();
|
||||||
|
|
||||||
|
// Reset counter for discarded memory in flight
|
||||||
|
m_discardMemoryOnFlush = m_discardMemoryCounter;
|
||||||
|
|
||||||
// Notify the device that the context has been flushed,
|
// Notify the device that the context has been flushed,
|
||||||
// this resets some resource initialization heuristics.
|
// this resets some resource initialization heuristics.
|
||||||
m_parent->NotifyContextFlush();
|
m_parent->NotifyContextFlush();
|
||||||
@ -984,7 +996,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void D3D11ImmediateContext::ThrottleAllocation() {
|
void D3D11ImmediateContext::ThrottleAllocation() {
|
||||||
DxvkStagingBufferStats stats = m_staging.getStatistics();
|
DxvkStagingBufferStats stats = GetStagingMemoryStatistics();
|
||||||
|
|
||||||
VkDeviceSize stagingMemoryInFlight = stats.allocatedTotal - m_stagingBufferFence->value();
|
VkDeviceSize stagingMemoryInFlight = stats.allocatedTotal - m_stagingBufferFence->value();
|
||||||
|
|
||||||
@ -994,7 +1006,8 @@ namespace dxvk {
|
|||||||
// wait for the GPU to go fully idle in case of a large allocation.
|
// wait for the GPU to go fully idle in case of a large allocation.
|
||||||
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
||||||
|
|
||||||
m_device->waitForFence(*m_stagingBufferFence, stats.allocatedTotal - stats.allocatedSinceLastReset - D3D11Initializer::MaxMemoryInFlight);
|
m_device->waitForFence(*m_stagingBufferFence, stats.allocatedTotal -
|
||||||
|
stats.allocatedSinceLastReset - D3D11Initializer::MaxMemoryInFlight);
|
||||||
} else if (stats.allocatedSinceLastReset >= D3D11Initializer::MaxMemoryPerSubmission) {
|
} else if (stats.allocatedSinceLastReset >= D3D11Initializer::MaxMemoryPerSubmission) {
|
||||||
// Flush somewhat aggressively if there's a lot of memory in flight
|
// Flush somewhat aggressively if there's a lot of memory in flight
|
||||||
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
|
||||||
@ -1002,4 +1015,20 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11ImmediateContext::ThrottleDiscard(
|
||||||
|
VkDeviceSize Size) {
|
||||||
|
m_discardMemoryCounter += Size;
|
||||||
|
|
||||||
|
if (m_discardMemoryCounter - m_discardMemoryOnFlush >= D3D11Initializer::MaxMemoryPerSubmission)
|
||||||
|
ThrottleAllocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkStagingBufferStats D3D11ImmediateContext::GetStagingMemoryStatistics() {
|
||||||
|
DxvkStagingBufferStats stats = m_staging.getStatistics();
|
||||||
|
stats.allocatedTotal += m_discardMemoryCounter;
|
||||||
|
stats.allocatedSinceLastReset += m_discardMemoryCounter - m_discardMemoryOnFlush;
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
Rc<sync::Fence> m_stagingBufferFence;
|
Rc<sync::Fence> m_stagingBufferFence;
|
||||||
|
|
||||||
|
VkDeviceSize m_discardMemoryCounter = 0u;
|
||||||
|
VkDeviceSize m_discardMemoryOnFlush = 0u;
|
||||||
|
|
||||||
D3D10Multithread m_multithread;
|
D3D10Multithread m_multithread;
|
||||||
D3D11VideoContext m_videoContext;
|
D3D11VideoContext m_videoContext;
|
||||||
|
|
||||||
@ -199,6 +202,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
void ThrottleAllocation();
|
void ThrottleAllocation();
|
||||||
|
|
||||||
|
void ThrottleDiscard(
|
||||||
|
VkDeviceSize Size);
|
||||||
|
|
||||||
|
DxvkStagingBufferStats GetStagingMemoryStatistics();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user