Merge remote-tracking branch 'origin/master' into 1.12

# Conflicts:
#	Source/Editor/Options/InterfaceOptions.cs
#	Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
#	Source/Engine/Graphics/Graphics.cpp
#	Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
#	Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.h
#	Source/Engine/GraphicsDevice/Vulkan/Config.h
#	Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
#	Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
#	Source/Engine/GraphicsDevice/Vulkan/QueueVulkan.cpp
This commit is contained in:
Wojtek Figat
2026-03-10 15:08:43 +01:00
28 changed files with 381 additions and 201 deletions

View File

@@ -20,15 +20,6 @@ void CmdBufferVulkan::AddWaitSemaphore(VkPipelineStageFlags waitFlags, Semaphore
_waitSemaphores.Add(waitSemaphore);
}
void CmdBufferVulkan::Wait(float timeInSecondsToWait)
{
if (!IsSubmitted())
return;
const bool failed = _device->FenceManager.WaitForFence(_fence, (uint64)(timeInSecondsToWait * 1e9));
ASSERT(!failed);
RefreshFenceStatus();
}
void CmdBufferVulkan::Begin()
{
PROFILE_CPU();
@@ -145,6 +136,16 @@ void CmdBufferVulkan::EndEvent()
#endif
void CmdBufferVulkan::Wait(float timeoutSeconds)
{
if (!IsSubmitted())
return;
PROFILE_CPU();
const bool failed = _device->FenceManager.WaitForFence(GetFence(), timeoutSeconds);
ASSERT(!failed);
RefreshFenceStatus();
}
void CmdBufferVulkan::RefreshFenceStatus()
{
if (_state == State::Submitted)
@@ -306,14 +307,6 @@ void CmdBufferManagerVulkan::SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaph
_activeCmdBuffer = nullptr;
}
void CmdBufferManagerVulkan::WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait)
{
ASSERT(cmdBuffer->IsSubmitted());
const bool failed = _device->FenceManager.WaitForFence(cmdBuffer->GetFence(), (uint64)(timeInSecondsToWait * 1e9));
ASSERT(!failed);
cmdBuffer->RefreshFenceStatus();
}
void CmdBufferManagerVulkan::GetNewActiveCommandBuffer()
{
PROFILE_CPU();

View File

@@ -119,7 +119,6 @@ public:
public:
void AddWaitSemaphore(VkPipelineStageFlags waitFlags, SemaphoreVulkan* waitSemaphore);
void Wait(float timeInSecondsToWait = 1.0f);
void Begin();
void End();
@@ -137,6 +136,7 @@ public:
void EndEvent();
#endif
void Wait(float timeoutSeconds = VULKAN_WAIT_TIMEOUT);
void RefreshFenceStatus();
};
@@ -210,8 +210,7 @@ public:
public:
void SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaphore = nullptr);
void WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait = 1.0f);
void RefreshFenceStatus(const CmdBufferVulkan* skipCmdBuffer = nullptr)
void RefreshFenceStatus(CmdBufferVulkan* skipCmdBuffer = nullptr)
{
_pool.RefreshFenceStatus(skipCmdBuffer);
}

View File

@@ -49,6 +49,11 @@
#define VULKAN_USE_TIMER_QUERIES 1
#endif
// Fence wait operation timeout in seconds
#ifndef VULKAN_WAIT_TIMEOUT
#define VULKAN_WAIT_TIMEOUT 5.0f
#endif
// Toggles GPUTimerQueryVulkan to use BeginQuery/EndQuery via GPuContext rather than old custom implementation
#define GPU_VULKAN_QUERY_NEW 1

View File

@@ -2253,16 +2253,15 @@ FenceVulkan* FenceManagerVulkan::AllocateFence(bool createSignaled)
return fence;
}
bool FenceManagerVulkan::WaitForFence(FenceVulkan* fence, uint64 timeInNanoseconds) const
bool FenceManagerVulkan::WaitForFence(FenceVulkan* fence, float timeoutSeconds) const
{
if (fence->IsSignaled)
return false;
PROFILE_CPU();
ZoneColor(TracyWaitZoneColor);
ASSERT(_usedFences.Contains(fence));
if (timeInNanoseconds)
timeInNanoseconds = 1000ll * 1000ll * 1000LL; // 1s
const VkResult result = vkWaitForFences(_device->Device, 1, &fence->Handle, true, timeInNanoseconds);
uint64 timeNanoseconds = (uint64)((double)timeoutSeconds * 1000000000.0);
const VkResult result = vkWaitForFences(_device->Device, 1, &fence->Handle, true, timeNanoseconds);
LOG_VULKAN_RESULT(result);
if (result == VK_SUCCESS)
{
@@ -2290,11 +2289,11 @@ void FenceManagerVulkan::ReleaseFence(FenceVulkan*& fence)
fence = nullptr;
}
void FenceManagerVulkan::WaitAndReleaseFence(FenceVulkan*& fence, uint64 timeInNanoseconds)
void FenceManagerVulkan::WaitAndReleaseFence(FenceVulkan*& fence, float timeoutSeconds)
{
ScopeLock lock(_device->_fenceLock);
if (!fence->IsSignaled)
WaitForFence(fence, timeInNanoseconds);
WaitForFence(fence, timeoutSeconds);
ResetFence(fence);
_usedFences.Remove(fence);
_freeFences.Add(fence);

View File

@@ -106,7 +106,7 @@ public:
}
// Returns true if waiting timed out or failed, false otherwise.
bool WaitForFence(FenceVulkan* fence, uint64 timeInNanoseconds = 0) const;
bool WaitForFence(FenceVulkan* fence, float timeoutSeconds = VULKAN_WAIT_TIMEOUT) const;
void ResetFence(FenceVulkan* fence) const;
@@ -114,7 +114,7 @@ public:
void ReleaseFence(FenceVulkan*& fence);
// Sets the fence handle to null
void WaitAndReleaseFence(FenceVulkan*& fence, uint64 timeInNanoseconds = 0);
void WaitAndReleaseFence(FenceVulkan*& fence, float timeoutSeconds = VULKAN_WAIT_TIMEOUT);
private:
// Returns true if fence was signaled, otherwise false.

View File

@@ -62,10 +62,7 @@ void QueueVulkan::Submit(CmdBufferVulkan* cmdBuffer, uint32 signalSemaphoresCoun
const bool WaitForIdleOnSubmit = false;
if (WaitForIdleOnSubmit)
{
bool success = _device->FenceManager.WaitForFence(fence);
ASSERT(success);
ASSERT(_device->FenceManager.IsFenceSignaled(fence));
cmdBuffer->GetOwner()->RefreshFenceStatus();
cmdBuffer->Wait();
}
#endif