mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[d3d11] Synchronize only to given sequence number in WaitForResources
Avoids costly thread synchronization when mapping staging resources for reading, as well as some other scenarios.
This commit is contained in:
parent
afe1840c74
commit
5a6711ed1d
@ -39,7 +39,7 @@ namespace dxvk {
|
||||
|
||||
D3D11ImmediateContext::~D3D11ImmediateContext() {
|
||||
Flush();
|
||||
SynchronizeCsThread();
|
||||
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||
SynchronizeDevice();
|
||||
}
|
||||
|
||||
@ -368,7 +368,8 @@ namespace dxvk {
|
||||
} else {
|
||||
// Wait until the resource is no longer in use
|
||||
if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
|
||||
if (!WaitForResource(pResource->GetBuffer(), MapType, MapFlags))
|
||||
if (!WaitForResource(pResource->GetBuffer(),
|
||||
pResource->GetSequenceNumber(), MapType, MapFlags))
|
||||
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||
}
|
||||
|
||||
@ -422,7 +423,8 @@ namespace dxvk {
|
||||
|
||||
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
|
||||
// Wait for the resource to become available
|
||||
if (!WaitForResource(mappedImage, MapType, MapFlags))
|
||||
if (!WaitForResource(mappedImage,
|
||||
pResource->GetSequenceNumber(Subresource), MapType, MapFlags))
|
||||
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||
|
||||
// Query the subresource's memory layout and hope that
|
||||
@ -447,7 +449,8 @@ namespace dxvk {
|
||||
|| mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
||||
|
||||
// Wait for mapped buffer to become available
|
||||
if (wait && !WaitForResource(mappedBuffer, MapType, MapFlags))
|
||||
if (wait && !WaitForResource(mappedBuffer,
|
||||
pResource->GetSequenceNumber(Subresource), MapType, MapFlags))
|
||||
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||
|
||||
mapPtr = pResource->GetMappedSlice(Subresource).mapPtr;
|
||||
@ -542,14 +545,15 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11ImmediateContext::SynchronizeCsThread() {
|
||||
void D3D11ImmediateContext::SynchronizeCsThread(uint64_t SequenceNumber) {
|
||||
D3D10DeviceLock lock = LockContext();
|
||||
|
||||
// Dispatch current chunk so that all commands
|
||||
// recorded prior to this function will be run
|
||||
if (SequenceNumber > m_csSeqNum)
|
||||
FlushCsChunk();
|
||||
|
||||
m_csThread.synchronize(DxvkCsThread::SynchronizeAll);
|
||||
m_csThread.synchronize(SequenceNumber);
|
||||
}
|
||||
|
||||
|
||||
@ -560,6 +564,7 @@ namespace dxvk {
|
||||
|
||||
bool D3D11ImmediateContext::WaitForResource(
|
||||
const Rc<DxvkResource>& Resource,
|
||||
uint64_t SequenceNumber,
|
||||
D3D11_MAP MapType,
|
||||
UINT MapFlags) {
|
||||
// Determine access type to wait for based on map mode
|
||||
@ -567,24 +572,30 @@ namespace dxvk {
|
||||
? DxvkAccess::Write
|
||||
: DxvkAccess::Read;
|
||||
|
||||
// Wait for the any pending D3D11 command to be executed
|
||||
// on the CS thread so that we can determine whether the
|
||||
// resource is currently in use or not.
|
||||
if (!Resource->isInUse(access))
|
||||
SynchronizeCsThread();
|
||||
// Wait for any CS chunk using the resource to execute, since
|
||||
// otherwise we cannot accurately determine if the resource is
|
||||
// actually being used by the GPU right now.
|
||||
bool isInUse = Resource->isInUse(access);
|
||||
|
||||
if (!isInUse) {
|
||||
SynchronizeCsThread(SequenceNumber);
|
||||
isInUse = Resource->isInUse(access);
|
||||
}
|
||||
|
||||
if (Resource->isInUse(access)) {
|
||||
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) {
|
||||
if (isInUse) {
|
||||
// We don't have to wait, but misbehaving games may
|
||||
// still try to spin on `Map` until the resource is
|
||||
// idle, so we should flush pending commands
|
||||
FlushImplicit(FALSE);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (isInUse) {
|
||||
// Make sure pending commands using the resource get
|
||||
// executed on the the GPU if we have to wait for it
|
||||
Flush();
|
||||
SynchronizeCsThread();
|
||||
SynchronizeCsThread(SequenceNumber);
|
||||
|
||||
Resource->waitIdle(access);
|
||||
}
|
||||
|
@ -112,7 +112,8 @@ namespace dxvk {
|
||||
ID3DDeviceContextState* pState,
|
||||
ID3DDeviceContextState** ppPreviousState);
|
||||
|
||||
void SynchronizeCsThread();
|
||||
void SynchronizeCsThread(
|
||||
uint64_t SequenceNumber);
|
||||
|
||||
private:
|
||||
|
||||
@ -158,6 +159,7 @@ namespace dxvk {
|
||||
|
||||
bool WaitForResource(
|
||||
const Rc<DxvkResource>& Resource,
|
||||
uint64_t SequenceNumber,
|
||||
D3D11_MAP MapType,
|
||||
UINT MapFlags);
|
||||
|
||||
|
@ -91,7 +91,7 @@ namespace dxvk {
|
||||
|
||||
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
|
||||
immediateContext->Flush();
|
||||
immediateContext->SynchronizeCsThread();
|
||||
immediateContext->SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user