Files
XCEngine/engine/src/RHI/OpenGL/OpenGLFence.cpp
ssdfasd 08c01dd143 RHI: Refactor Fence module to pure timeline semantics
- Remove IsSignaled() from RHIFence interface (semantic inconsistency)
- Remove Reset() from OpenGL implementation (no D3D12 counterpart)
- OpenGL Fence now uses single GLsync + CPU counters for timeline simulation
- OpenGL Fence Initialize() now accepts uint64_t initialValue (was bool)
- Add comprehensive timeline semantics tests for all backends:
  - Signal increment/decrement scenarios
  - Multiple signals
  - Wait smaller than completed value
  - GetCompletedValue stages verification
- Update documentation to reflect actual implementation
2026-03-24 01:53:00 +08:00

88 lines
2.3 KiB
C++

#include "XCEngine/RHI/OpenGL/OpenGLFence.h"
#include <glad/glad.h>
namespace XCEngine {
namespace RHI {
OpenGLFence::OpenGLFence()
: m_sync(nullptr)
, m_signaledValue(0)
, m_completedValue(0) {
}
OpenGLFence::~OpenGLFence() {
Shutdown();
}
bool OpenGLFence::Initialize(uint64_t initialValue) {
m_signaledValue.store(initialValue, std::memory_order_release);
m_completedValue.store(initialValue, std::memory_order_release);
return true;
}
void OpenGLFence::Shutdown() {
if (m_sync) {
glDeleteSync(static_cast<GLsync>(m_sync));
m_sync = nullptr;
}
m_signaledValue.store(0, std::memory_order_release);
m_completedValue.store(0, std::memory_order_release);
}
void OpenGLFence::Signal() {
Signal(1);
}
void OpenGLFence::Signal(uint64_t value) {
if (m_sync) {
glClientWaitSync(static_cast<GLsync>(m_sync), GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
glDeleteSync(static_cast<GLsync>(m_sync));
m_sync = nullptr;
}
glFlush();
m_signaledValue.store(value, std::memory_order_release);
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
void OpenGLFence::Wait(uint64_t value) {
uint64_t currentCompleted = m_completedValue.load(std::memory_order_acquire);
if (currentCompleted >= value) {
return;
}
if (m_sync) {
glClientWaitSync(static_cast<GLsync>(m_sync), GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
glDeleteSync(static_cast<GLsync>(m_sync));
m_sync = nullptr;
}
uint64_t signaled = m_signaledValue.load(std::memory_order_acquire);
m_completedValue.store(signaled, std::memory_order_release);
}
uint64_t OpenGLFence::GetCompletedValue() const {
if (!m_sync) {
return m_completedValue.load(std::memory_order_acquire);
}
GLint status = 0;
glGetSynciv(static_cast<GLsync>(m_sync), GL_SYNC_STATUS, sizeof(status), nullptr, &status);
if (status == GL_SIGNALED) {
return m_signaledValue.load(std::memory_order_acquire);
}
return m_completedValue.load(std::memory_order_acquire);
}
void* OpenGLFence::GetNativeHandle() {
if (!m_sync) {
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
return m_sync;
}
} // namespace RHI
} // namespace XCEngine