[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:
Philip Rebohle 2019-11-02 16:32:55 +01:00
parent e6c3f0479d
commit 77a0cb2b19
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 45 additions and 21 deletions

View File

@ -11,6 +11,7 @@ namespace dxvk {
class D3D11CommonTexture;
class D3D11ImmediateContext : public D3D11DeviceContext {
friend class D3D11SwapChain;
public:
D3D11ImmediateContext(

View File

@ -181,8 +181,6 @@ namespace dxvk {
if (std::exchange(m_dirty, false))
RecreateSwapChain(vsync);
FlushImmediateContext();
HRESULT hr = S_OK;
try {
@ -200,6 +198,16 @@ namespace dxvk {
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
auto syncEvent = m_dxgiDevice->GetFrameSyncEvent(m_desc.BufferCount);
syncEvent->wait();
@ -305,16 +313,41 @@ namespace dxvk {
if (i + 1 >= SyncInterval)
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_context->endRecording(),
sync.acquire, sync.present);
Sync.acquire, Sync.present);
m_device->presentImage(m_presenter,
sync.present, &m_presentStatus);
Sync.present, &m_presentStatus);
if (m_presentStatus.result != VK_NOT_READY
&& m_presentStatus.result != VK_SUCCESS)
RecreateSwapChain(m_vsync);
SynchronizePresent();
}
}
@ -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() {
// Explicitly destroy current swap image before
// creating a new one to free up resources

View File

@ -122,10 +122,12 @@ namespace dxvk {
void PresentImage(UINT SyncInterval);
void SubmitPresent(
D3D11ImmediateContext* pContext,
const vk::PresenterSync& Sync);
void SynchronizePresent();
void FlushImmediateContext();
void RecreateSwapChain(
BOOL Vsync);