Enhance OpenGLFence with proper synchronization

- Add FenceStatus enum for status query
- Add m_sync (GLsync) for OpenGL fence synchronization
- Add Signal(value) overload with fence value
- Add Wait(timeoutNs) with timeout support
- Add GetStatus() for async status check
- Add GetCompletedValue() and GetCurrentValue()
- Implement using glSync for proper GPU synchronization
- Replace glFinish blocking with glClientWaitSync
This commit is contained in:
2026-03-17 02:17:41 +08:00
parent 1de66b835d
commit 6126404e3f
3 changed files with 481 additions and 12 deletions

View File

@@ -2,36 +2,71 @@
#include "XCEngine/RHI/OpenGL/OpenGLFence.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <thread>
#include <chrono>
namespace XCEngine {
namespace RHI {
OpenGLFence::OpenGLFence() : m_fence(0), m_fenceValue(0), m_signaled(false) {
OpenGLFence::OpenGLFence()
: m_sync(nullptr)
, m_fenceValue(0)
, m_completedValue(0)
, m_signaled(false) {
}
OpenGLFence::~OpenGLFence() {
Shutdown();
}
bool OpenGLFence::Initialize() {
bool OpenGLFence::Initialize(bool signaled) {
m_fenceValue = signaled ? 1 : 0;
m_completedValue = m_fenceValue;
m_signaled = signaled;
return true;
}
void OpenGLFence::Shutdown() {
if (m_sync) {
glDeleteSync(static_cast<GLsync>(m_sync));
m_sync = nullptr;
}
}
void OpenGLFence::Signal() {
glFinish();
m_signaled = true;
glFlush();
m_fenceValue++;
m_signaled = true;
}
void OpenGLFence::Wait() {
glFinish();
void OpenGLFence::Signal(uint64_t value) {
glFlush();
m_fenceValue = value;
m_signaled = true;
}
void OpenGLFence::Wait(uint64_t timeoutNs) {
if (!m_signaled || !m_sync) {
glFinish();
m_completedValue = m_fenceValue;
m_signaled = true;
return;
}
GLsync sync = static_cast<GLsync>(m_sync);
GLenum result = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, timeoutNs);
while (result == GL_TIMEOUT_EXPIRED && timeoutNs > 0) {
result = glClientWaitSync(sync, 0, timeoutNs);
}
if (result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED) {
m_completedValue = m_fenceValue;
}
}
void OpenGLFence::Reset() {
if (m_sync) {
glDeleteSync(static_cast<GLsync>(m_sync));
m_sync = nullptr;
}
m_signaled = false;
}
@@ -39,5 +74,24 @@ bool OpenGLFence::IsSignaled() const {
return m_signaled;
}
FenceStatus OpenGLFence::GetStatus() const {
if (!m_sync) {
return m_signaled ? FenceStatus::Signaled : FenceStatus::Unsignaled;
}
GLsync sync = static_cast<GLsync>(m_sync);
GLint status = 0;
glGetSynciv(sync, GL_SYNC_STATUS, sizeof(status), nullptr, &status);
if (status == GL_SIGNALED) {
return FenceStatus::Signaled;
}
return FenceStatus::Unsignaled;
}
uint64_t OpenGLFence::GetCompletedValue() const {
return m_completedValue;
}
} // namespace RHI
} // namespace XCEngine