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() {
|
D3D11ImmediateContext::~D3D11ImmediateContext() {
|
||||||
Flush();
|
Flush();
|
||||||
SynchronizeCsThread();
|
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||||
SynchronizeDevice();
|
SynchronizeDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +368,8 @@ namespace dxvk {
|
|||||||
} else {
|
} else {
|
||||||
// Wait until the resource is no longer in use
|
// Wait until the resource is no longer in use
|
||||||
if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
|
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;
|
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +423,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
|
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
|
||||||
// Wait for the resource to become available
|
// 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;
|
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||||
|
|
||||||
// Query the subresource's memory layout and hope that
|
// Query the subresource's memory layout and hope that
|
||||||
@ -447,7 +449,8 @@ namespace dxvk {
|
|||||||
|| mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
|| mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
// Wait for mapped buffer to become available
|
// 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;
|
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||||
|
|
||||||
mapPtr = pResource->GetMappedSlice(Subresource).mapPtr;
|
mapPtr = pResource->GetMappedSlice(Subresource).mapPtr;
|
||||||
@ -542,14 +545,15 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11ImmediateContext::SynchronizeCsThread() {
|
void D3D11ImmediateContext::SynchronizeCsThread(uint64_t SequenceNumber) {
|
||||||
D3D10DeviceLock lock = LockContext();
|
D3D10DeviceLock lock = LockContext();
|
||||||
|
|
||||||
// Dispatch current chunk so that all commands
|
// Dispatch current chunk so that all commands
|
||||||
// recorded prior to this function will be run
|
// recorded prior to this function will be run
|
||||||
FlushCsChunk();
|
if (SequenceNumber > m_csSeqNum)
|
||||||
|
FlushCsChunk();
|
||||||
|
|
||||||
m_csThread.synchronize(DxvkCsThread::SynchronizeAll);
|
m_csThread.synchronize(SequenceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -560,6 +564,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
bool D3D11ImmediateContext::WaitForResource(
|
bool D3D11ImmediateContext::WaitForResource(
|
||||||
const Rc<DxvkResource>& Resource,
|
const Rc<DxvkResource>& Resource,
|
||||||
|
uint64_t SequenceNumber,
|
||||||
D3D11_MAP MapType,
|
D3D11_MAP MapType,
|
||||||
UINT MapFlags) {
|
UINT MapFlags) {
|
||||||
// Determine access type to wait for based on map mode
|
// Determine access type to wait for based on map mode
|
||||||
@ -567,29 +572,35 @@ namespace dxvk {
|
|||||||
? DxvkAccess::Write
|
? DxvkAccess::Write
|
||||||
: DxvkAccess::Read;
|
: DxvkAccess::Read;
|
||||||
|
|
||||||
// Wait for the any pending D3D11 command to be executed
|
// Wait for any CS chunk using the resource to execute, since
|
||||||
// on the CS thread so that we can determine whether the
|
// otherwise we cannot accurately determine if the resource is
|
||||||
// resource is currently in use or not.
|
// actually being used by the GPU right now.
|
||||||
if (!Resource->isInUse(access))
|
bool isInUse = Resource->isInUse(access);
|
||||||
SynchronizeCsThread();
|
|
||||||
|
if (!isInUse) {
|
||||||
if (Resource->isInUse(access)) {
|
SynchronizeCsThread(SequenceNumber);
|
||||||
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) {
|
isInUse = Resource->isInUse(access);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) {
|
||||||
|
if (isInUse) {
|
||||||
// We don't have to wait, but misbehaving games may
|
// We don't have to wait, but misbehaving games may
|
||||||
// still try to spin on `Map` until the resource is
|
// still try to spin on `Map` until the resource is
|
||||||
// idle, so we should flush pending commands
|
// idle, so we should flush pending commands
|
||||||
FlushImplicit(FALSE);
|
FlushImplicit(FALSE);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
} else {
|
||||||
|
if (isInUse) {
|
||||||
// Make sure pending commands using the resource get
|
// Make sure pending commands using the resource get
|
||||||
// executed on the the GPU if we have to wait for it
|
// executed on the the GPU if we have to wait for it
|
||||||
Flush();
|
Flush();
|
||||||
SynchronizeCsThread();
|
SynchronizeCsThread(SequenceNumber);
|
||||||
|
|
||||||
Resource->waitIdle(access);
|
Resource->waitIdle(access);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,10 +109,11 @@ namespace dxvk {
|
|||||||
const UINT* pUAVInitialCounts);
|
const UINT* pUAVInitialCounts);
|
||||||
|
|
||||||
void STDMETHODCALLTYPE SwapDeviceContextState(
|
void STDMETHODCALLTYPE SwapDeviceContextState(
|
||||||
ID3DDeviceContextState* pState,
|
ID3DDeviceContextState* pState,
|
||||||
ID3DDeviceContextState** ppPreviousState);
|
ID3DDeviceContextState** ppPreviousState);
|
||||||
|
|
||||||
void SynchronizeCsThread();
|
void SynchronizeCsThread(
|
||||||
|
uint64_t SequenceNumber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -158,6 +159,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
bool WaitForResource(
|
bool WaitForResource(
|
||||||
const Rc<DxvkResource>& Resource,
|
const Rc<DxvkResource>& Resource,
|
||||||
|
uint64_t SequenceNumber,
|
||||||
D3D11_MAP MapType,
|
D3D11_MAP MapType,
|
||||||
UINT MapFlags);
|
UINT MapFlags);
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
|
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
|
||||||
immediateContext->Flush();
|
immediateContext->Flush();
|
||||||
immediateContext->SynchronizeCsThread();
|
immediateContext->SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user