summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-09-08 21:56:26 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-09-08 21:56:26 +0000
commit52d1b5ab7fee4f2c4e63eaf5774d48111becba12 (patch)
tree9eac4952a2eb4765352270cc7993fbefec83c6ce /Graphics
parentUpdated constructor of RefCountedObject to forward arguments to its base class (diff)
downloadDiligentCore-52d1b5ab7fee4f2c4e63eaf5774d48111becba12.tar.gz
DiligentCore-52d1b5ab7fee4f2c4e63eaf5774d48111becba12.zip
Added IDeviceContext::Wait() method (updated API version to 240026)
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsEngine/interface/APIInfo.h2
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h26
-rwxr-xr-xGraphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h2
-rw-r--r--Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h2
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp10
-rw-r--r--Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp20
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h4
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h4
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h3
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp6
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp10
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp12
-rw-r--r--Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h2
-rw-r--r--Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm10
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h2
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp9
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/FenceGLImpl.cpp17
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp13
24 files changed, 161 insertions, 15 deletions
diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h
index fd6ef747..59bd261a 100644
--- a/Graphics/GraphicsEngine/interface/APIInfo.h
+++ b/Graphics/GraphicsEngine/interface/APIInfo.h
@@ -26,7 +26,7 @@
/// \file
/// Diligent API information
-#define DILIGENT_API_VERSION 240024
+#define DILIGENT_API_VERSION 240026
#include "../../../Primitives/interface/BasicTypes.h"
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index c7dd3d21..62aee8a1 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -799,7 +799,31 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value) = 0;
- /// Flushes the command buffer.
+ /// Waits until the specified fence reaches or exceeds the specified value.
+
+ /// \note The method blocks the execution of the calling thread until the wait is complete.
+ ///
+ /// \param [in] pFence - The fence to wait.
+ /// \param [in] Value - The value that the context is waiting for the fence to reach.
+ ///
+ /// \remarks Wait is only allowed for immediate contexts.\n
+ /// The method flushes the context before initiating the wait (see IDeviceContext::Flush()),
+ /// so an application must explicitly reset the PSO and bind all required shader
+ /// resources after waiting for a fence.\n
+ /// The fence can only be waited for from the same context it has
+ /// previously been signaled.
+ virtual void Wait(IFence* pFence, Uint64 Value) = 0;
+
+
+ /// Submits all pending commands in the context for execution to the command queue.
+
+ /// \remarks Only immediate contexts can be flushed.\n
+ /// Internally the method resets the state of the current command list/buffer.
+ /// When the next draw command is issued, the engine will restore all states
+ /// (rebind render targets and depth-stencil buffer as well as index and vertex buffers,
+ /// restore viewports and scissor rects, etc.) except for the pipeline state and shader resource
+ /// bindings. An application must explicitly reset the PSO and bind all required shader
+ /// resources after flushing the context.
virtual void Flush() = 0;
diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h
index bc5c87a6..ef7124be 100755
--- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h
+++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h
@@ -156,6 +156,8 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value)override final;
+ virtual void Wait(IFence* pFence, Uint64 Value)override final;
+
virtual ID3D11DeviceContext* GetD3D11DeviceContext()override final { return m_pd3d11DeviceContext; }
void CommitRenderTargets();
diff --git a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h
index 9de594cf..bdfc5262 100644
--- a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h
+++ b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h
@@ -58,6 +58,8 @@ public:
m_PendingQueries.emplace_back(std::move(pCtx), std::move(pQuery), Value);
}
+ void Wait(Uint64 Value);
+
private:
struct PendingFenceData
{
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index dc6c3281..1ccdc2e2 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -1764,7 +1764,15 @@ namespace Diligent
m_pd3d11DeviceContext->End(pd3d11Query);
auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
pFenceD3D11Impl->AddPendingQuery(m_pd3d11DeviceContext, std::move(pd3d11Query), Value);
- };
+ }
+
+ void DeviceContextD3D11Impl::Wait(IFence* pFence, Uint64 Value)
+ {
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ Flush();
+ auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
+ pFenceD3D11Impl->Wait(Value);
+ }
void DeviceContextD3D11Impl::ClearStateCache()
{
diff --git a/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp
index 73d32f51..e3bd2f4e 100644
--- a/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp
@@ -64,6 +64,26 @@ Uint64 FenceD3D11Impl :: GetCompletedValue()
return m_LastCompletedFenceValue;
}
+void FenceD3D11Impl :: Wait(Uint64 Value)
+{
+ while (!m_PendingQueries.empty())
+ {
+ auto& QueryData = m_PendingQueries.front();
+ if (QueryData.Value > Value)
+ break;
+
+ BOOL Data;
+ while (QueryData.pd3d11Ctx->GetData(QueryData.pd3d11Query, &Data, sizeof(Data), 0) != S_OK)
+ std::this_thread::yield();
+
+ VERIFY_EXPR(Data == TRUE);
+ if (QueryData.Value > m_LastCompletedFenceValue)
+ m_LastCompletedFenceValue = QueryData.Value;
+
+ m_PendingQueries.pop_front();
+ }
+}
+
void FenceD3D11Impl :: Reset(Uint64 Value)
{
DEV_CHECK_ERR(Value >= m_LastCompletedFenceValue, "Resetting fence '", m_Desc.Name, "' to the value (", Value, ") that is smaller than the last completed value (", m_LastCompletedFenceValue, ")");
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h
index 4089663c..e1d29f2e 100644
--- a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h
@@ -56,7 +56,9 @@ public:
virtual Uint64 GetCompletedFenceValue()override final;
- void SignalFence(ID3D12Fence* pFence, Uint64 Value)override final;
+ virtual void SignalFence(ID3D12Fence* pFence, Uint64 Value)override final;
+
+ virtual void Wait(ID3D12Fence* pFence, Uint64 Value)override final;
private:
// A value that will be signaled by the command queue next
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
index 7674ed54..a0cea3d2 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
@@ -154,6 +154,8 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value)override final;
+ virtual void Wait(IFence* pFence, Uint64 Value)override final;
+
virtual void TransitionTextureState(ITexture *pTexture, D3D12_RESOURCE_STATES State)override final;
virtual void TransitionBufferState(IBuffer *pBuffer, D3D12_RESOURCE_STATES State)override final;
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
index 0551f7d0..9a70e68d 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
@@ -85,6 +85,8 @@ public:
PooledCommandContext AllocateCommandContext(const Char* ID = "");
void CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx);
Uint64 CloseAndExecuteCommandContext(Uint32 QueueIndex, PooledCommandContext&& Ctx, bool DiscardStaleObjects, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence> > >* pSignalFences);
+
+ void WaitForFence(Uint32 QueueIndex, IFence* pFence, Uint64 Value);
// Disposes an unused command context
void DisposeCommandContext(PooledCommandContext&& Ctx);
@@ -101,7 +103,7 @@ public:
}
const GenerateMipsHelper& GetMipsGenerator()const {return m_MipsGenerator;}
-
+
private:
virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
void FreeCommandContext(PooledCommandContext&& Ctx);
diff --git a/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h b/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
index 81ff9b45..5ad649fa 100644
--- a/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
@@ -56,6 +56,9 @@ public:
/// Signals the given fence
virtual void SignalFence(ID3D12Fence* pFence, Uint64 Value) = 0;
+
+ /// Waits until the specified fence reaches or exceeds the specified value.
+ virtual void Wait(ID3D12Fence* pFence, Uint64 Value) = 0;
};
}
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
index ed41e02a..df423816 100644
--- a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
@@ -99,4 +99,10 @@ void CommandQueueD3D12Impl::SignalFence(ID3D12Fence* pFence, Uint64 Value)
m_pd3d12CmdQueue->Signal(pFence, Value);
}
+void CommandQueueD3D12Impl::Wait(ID3D12Fence* pFence, Uint64 Value)
+{
+ std::lock_guard<std::mutex> Lock(m_QueueMtx);
+ m_pd3d12CmdQueue->Wait(pFence, Value);
+}
+
}
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 01aa8307..7daa6437 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -1562,7 +1562,15 @@ namespace Diligent
{
VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
m_PendingFences.emplace_back(Value, pFence);
- };
+ }
+
+ void DeviceContextD3D12Impl::Wait(IFence* pFence, Uint64 Value)
+ {
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ Flush();
+ m_pDevice.RawPtr<RenderDeviceD3D12Impl>()->WaitForFence(m_CommandQueueId, pFence, Value);
+ }
+
void DeviceContextD3D12Impl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
{
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index a7d2f6c6..e7ee520e 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -197,6 +197,18 @@ Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(Uint32 QueueIndex, P
return FenceValue;
}
+void RenderDeviceD3D12Impl::WaitForFence(Uint32 QueueIndex, IFence* pFence, Uint64 Value)
+{
+ VERIFY_EXPR(QueueIndex < m_CmdQueueCount);
+ VERIFY_EXPR(pFence != nullptr);
+
+ auto* pFenceD3D12Impl = ValidatedCast<FenceD3D12Impl>(pFence);
+ auto* pd3d12Fence = pFenceD3D12Impl->GetD3D12Fence();
+ m_CommandQueues[QueueIndex].CmdQueue->Wait(pd3d12Fence, Value);
+
+ PurgeReleaseQueue(QueueIndex);
+}
+
void RenderDeviceD3D12Impl::IdleGPU()
{
diff --git a/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h b/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h
index f3d711a2..77c88c9b 100644
--- a/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h
+++ b/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h
@@ -152,6 +152,8 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value)override final;
+ virtual void Wait(IFence* pFence, Uint64 Value)override final;
+
private:
};
diff --git a/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm b/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm
index 978fccf7..bd975afe 100644
--- a/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm
+++ b/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm
@@ -374,7 +374,15 @@ namespace Diligent
VERIFY(!m_bIsDeferred, "Fence can only be signalled from immediate context");
LOG_ERROR_MESSAGE("DeviceContextMtlImpl::SignalFence() is not implemented");
- };
+ }
+
+ void DeviceContextD3D11Impl::Wait(IFence* pFence, Uint64 Value)
+ {
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ Flush();
+
+ LOG_ERROR_MESSAGE("DeviceContextMtlImpl::Wait() is not implemented");
+ }
void DeviceContextMtlImpl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
{
diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h
index 96653441..3d64ad3f 100644
--- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h
+++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h
@@ -150,6 +150,8 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value)override final;
+ virtual void Wait(IFence* pFence, Uint64 Value)override final;
+
virtual bool UpdateCurrentGLContext()override final;
void BindProgramResources(Uint32& NewMemoryBarriers, IShaderResourceBinding* pResBinding);
diff --git a/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h
index ceab0d57..bade8fd1 100644
--- a/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h
+++ b/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h
@@ -59,6 +59,8 @@ public:
m_PendingFences.emplace_back(Value, std::move(Fence));
}
+ void Wait(Uint64 Value);
+
private:
std::deque<std::pair<Uint64, GLObjectWrappers::GLSyncObj> > m_PendingFences;
volatile Uint64 m_LastCompletedFenceValue = 0;
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
index 2b19d5f1..ec77379d 100644
--- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
@@ -1073,7 +1073,14 @@ namespace Diligent
CHECK_GL_ERROR( "Failed to create gl fence" );
auto* pFenceGLImpl = ValidatedCast<FenceGLImpl>(pFence);
pFenceGLImpl->AddPendingFence(std::move(GLFence), Value);
- };
+ }
+
+ void DeviceContextGLImpl::Wait(IFence* pFence, Uint64 Value)
+ {
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ auto* pFenceGLImpl = ValidatedCast<FenceGLImpl>(pFence);
+ pFenceGLImpl->Wait(Value);
+ }
bool DeviceContextGLImpl::UpdateCurrentGLContext()
{
diff --git a/Graphics/GraphicsEngineOpenGL/src/FenceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/FenceGLImpl.cpp
index 75983e18..7e39aa2f 100644
--- a/Graphics/GraphicsEngineOpenGL/src/FenceGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/FenceGLImpl.cpp
@@ -64,6 +64,23 @@ Uint64 FenceGLImpl :: GetCompletedValue()
return m_LastCompletedFenceValue;
}
+void FenceGLImpl :: Wait(Uint64 Value)
+{
+ while (!m_PendingFences.empty())
+ {
+ auto& val_fence = m_PendingFences.front();
+ if (val_fence.first > Value)
+ break;
+
+ auto res = glClientWaitSync(val_fence.second, GL_SYNC_FLUSH_COMMANDS_BIT, std::numeric_limits<GLuint64>::max());
+ VERIFY_EXPR(res == GL_ALREADY_SIGNALED || res == GL_CONDITION_SATISFIED);
+
+ if (val_fence.first > m_LastCompletedFenceValue)
+ m_LastCompletedFenceValue = val_fence.first;
+ m_PendingFences.pop_front();
+ }
+}
+
void FenceGLImpl :: Reset(Uint64 Value)
{
DEV_CHECK_ERR(Value >= m_LastCompletedFenceValue, "Resetting fence '", m_Desc.Name, "' to the value (", Value, ") that is smaller than the last completed value (", m_LastCompletedFenceValue, ")");
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
index 417f2f5b..bce9f300 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
@@ -159,6 +159,8 @@ public:
virtual void SignalFence(IFence* pFence, Uint64 Value)override final;
+ virtual void Wait(IFence* pFence, Uint64 Value)override final;
+
// Transitions texture subresources from OldState to NewState, and optionally updates
// internal texture state.
// If OldState == RESOURCE_STATE_UNKNOWN, internal texture state is used as old state.
diff --git a/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h
index 9816bfb1..a6c80c83 100644
--- a/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h
@@ -65,7 +65,7 @@ public:
m_PendingFences.emplace_back(FenceValue, std::move(vkFence));
}
- void Wait();
+ void Wait(Uint64 Value);
private:
VulkanUtilities::VulkanFencePool m_FencePool;
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
index 8ee3e7b6..2af4e27f 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
@@ -101,7 +101,7 @@ Uint64 CommandQueueVkImpl::WaitForIdle()
Atomics::AtomicIncrement(m_NextFenceValue);
vkQueueWaitIdle(m_VkQueue);
// For some reason after idling the queue not all fences are signaled
- m_pFence->Wait();
+ m_pFence->Wait(UINT64_MAX);
m_pFence->Reset(LastCompletedFenceValue);
return LastCompletedFenceValue;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 3a3c301a..d2252b4a 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -31,6 +31,7 @@
#include "BufferVkImpl.h"
#include "VulkanTypeConversions.h"
#include "CommandListVkImpl.h"
+#include "FenceVkImpl.h"
#include "GraphicsAccessories.h"
namespace Diligent
@@ -1913,7 +1914,16 @@ namespace Diligent
{
VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
m_PendingFences.emplace_back( std::make_pair(Value, pFence) );
- };
+ }
+
+ void DeviceContextVkImpl::Wait(IFence* pFence, Uint64 Value)
+ {
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ Flush();
+ auto* pFenceVk = ValidatedCast<FenceVkImpl>(pFence);
+ pFenceVk->Wait(Value);
+ }
+
void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayout NewLayout)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
index 3314598a..07f8ba23 100644
--- a/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
@@ -48,7 +48,7 @@ FenceVkImpl :: ~FenceVkImpl()
// Vulkan spec states that all queue submission commands that refer to
// a fence must have completed execution before the fence is destroyed.
// (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyFence-fence-01120)
- Wait();
+ Wait(UINT64_MAX);
}
}
@@ -83,11 +83,15 @@ void FenceVkImpl :: Reset(Uint64 Value)
}
-void FenceVkImpl :: Wait()
+void FenceVkImpl :: Wait(Uint64 Value)
{
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
- for (auto& val_fence : m_PendingFences)
+ while (!m_PendingFences.empty())
{
+ auto& val_fence = m_PendingFences.front();
+ if (val_fence.first > Value)
+ break;
+
auto status = LogicalDevice.GetFenceStatus(val_fence.second);
if (status == VK_NOT_READY)
{
@@ -99,8 +103,9 @@ void FenceVkImpl :: Wait()
if (val_fence.first > m_LastCompletedFenceValue)
m_LastCompletedFenceValue = val_fence.first;
m_FencePool.DisposeFence(std::move(val_fence.second));
+
+ m_PendingFences.pop_front();
}
- m_PendingFences.clear();
}
}