mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-27 13:54:16 +01:00
[d3d11] Don't synchronize with CS thread on present
Instead, submit from the CS thread in order to prevent out-of-order submissions. Improves minimum FPS in Final Fantasy XIV by 5-10%.
This commit is contained in:
parent
e6c3f0479d
commit
77a0cb2b19
@ -11,6 +11,7 @@ namespace dxvk {
|
|||||||
class D3D11CommonTexture;
|
class D3D11CommonTexture;
|
||||||
|
|
||||||
class D3D11ImmediateContext : public D3D11DeviceContext {
|
class D3D11ImmediateContext : public D3D11DeviceContext {
|
||||||
|
friend class D3D11SwapChain;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
D3D11ImmediateContext(
|
D3D11ImmediateContext(
|
||||||
|
@ -181,8 +181,6 @@ namespace dxvk {
|
|||||||
if (std::exchange(m_dirty, false))
|
if (std::exchange(m_dirty, false))
|
||||||
RecreateSwapChain(vsync);
|
RecreateSwapChain(vsync);
|
||||||
|
|
||||||
FlushImmediateContext();
|
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -200,6 +198,16 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::PresentImage(UINT SyncInterval) {
|
void D3D11SwapChain::PresentImage(UINT SyncInterval) {
|
||||||
|
Com<ID3D11DeviceContext> deviceContext = nullptr;
|
||||||
|
m_parent->GetImmediateContext(&deviceContext);
|
||||||
|
|
||||||
|
// Flush pending rendering commands before
|
||||||
|
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
|
||||||
|
immediateContext->Flush();
|
||||||
|
|
||||||
|
if (!m_device->hasAsyncPresent())
|
||||||
|
immediateContext->SynchronizeCsThread();
|
||||||
|
|
||||||
// Wait for the sync event so that we respect the maximum frame latency
|
// Wait for the sync event so that we respect the maximum frame latency
|
||||||
auto syncEvent = m_dxgiDevice->GetFrameSyncEvent(m_desc.BufferCount);
|
auto syncEvent = m_dxgiDevice->GetFrameSyncEvent(m_desc.BufferCount);
|
||||||
syncEvent->wait();
|
syncEvent->wait();
|
||||||
@ -305,16 +313,41 @@ namespace dxvk {
|
|||||||
if (i + 1 >= SyncInterval)
|
if (i + 1 >= SyncInterval)
|
||||||
m_context->queueSignal(syncEvent);
|
m_context->queueSignal(syncEvent);
|
||||||
|
|
||||||
|
SubmitPresent(immediateContext, sync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11SwapChain::SubmitPresent(
|
||||||
|
D3D11ImmediateContext* pContext,
|
||||||
|
const vk::PresenterSync& Sync) {
|
||||||
|
if (m_device->hasAsyncPresent()) {
|
||||||
|
// Present from CS thread so that we don't
|
||||||
|
// have to synchronize with it first.
|
||||||
|
m_presentStatus.result = VK_NOT_READY;
|
||||||
|
|
||||||
|
pContext->EmitCs([this,
|
||||||
|
cSync = Sync,
|
||||||
|
cCommandList = m_context->endRecording()
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
m_device->submitCommandList(cCommandList,
|
||||||
|
cSync.acquire, cSync.present);
|
||||||
|
|
||||||
|
m_device->presentImage(m_presenter,
|
||||||
|
cSync.present, &m_presentStatus);
|
||||||
|
});
|
||||||
|
|
||||||
|
pContext->FlushCsChunk();
|
||||||
|
} else {
|
||||||
|
// Safe path, present from calling thread
|
||||||
m_device->submitCommandList(
|
m_device->submitCommandList(
|
||||||
m_context->endRecording(),
|
m_context->endRecording(),
|
||||||
sync.acquire, sync.present);
|
Sync.acquire, Sync.present);
|
||||||
|
|
||||||
m_device->presentImage(m_presenter,
|
m_device->presentImage(m_presenter,
|
||||||
sync.present, &m_presentStatus);
|
Sync.present, &m_presentStatus);
|
||||||
|
|
||||||
if (m_presentStatus.result != VK_NOT_READY
|
SynchronizePresent();
|
||||||
&& m_presentStatus.result != VK_SUCCESS)
|
|
||||||
RecreateSwapChain(m_vsync);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,18 +445,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::FlushImmediateContext() {
|
|
||||||
Com<ID3D11DeviceContext> deviceContext = nullptr;
|
|
||||||
m_parent->GetImmediateContext(&deviceContext);
|
|
||||||
|
|
||||||
// The presentation code is run from the main rendering thread
|
|
||||||
// rather than the command stream thread, so we synchronize.
|
|
||||||
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
|
|
||||||
immediateContext->Flush();
|
|
||||||
immediateContext->SynchronizeCsThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::CreateBackBuffer() {
|
void D3D11SwapChain::CreateBackBuffer() {
|
||||||
// Explicitly destroy current swap image before
|
// Explicitly destroy current swap image before
|
||||||
// creating a new one to free up resources
|
// creating a new one to free up resources
|
||||||
|
@ -122,10 +122,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
void PresentImage(UINT SyncInterval);
|
void PresentImage(UINT SyncInterval);
|
||||||
|
|
||||||
|
void SubmitPresent(
|
||||||
|
D3D11ImmediateContext* pContext,
|
||||||
|
const vk::PresenterSync& Sync);
|
||||||
|
|
||||||
void SynchronizePresent();
|
void SynchronizePresent();
|
||||||
|
|
||||||
void FlushImmediateContext();
|
|
||||||
|
|
||||||
void RecreateSwapChain(
|
void RecreateSwapChain(
|
||||||
BOOL Vsync);
|
BOOL Vsync);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user