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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user