#include "XCEngine/RHI/OpenGL/OpenGLFence.h" #include 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(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(m_sync), GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); glDeleteSync(static_cast(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(m_sync), GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); glDeleteSync(static_cast(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(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