2026-03-16 18:48:12 +08:00
|
|
|
#include "XCEngine/RHI/OpenGL/OpenGLFence.h"
|
|
|
|
|
#include <glad/glad.h>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace RHI {
|
|
|
|
|
|
2026-03-17 02:17:41 +08:00
|
|
|
OpenGLFence::OpenGLFence()
|
|
|
|
|
: m_sync(nullptr)
|
|
|
|
|
, m_fenceValue(0)
|
|
|
|
|
, m_completedValue(0)
|
|
|
|
|
, m_signaled(false) {
|
2026-03-16 18:48:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OpenGLFence::~OpenGLFence() {
|
2026-03-17 02:17:41 +08:00
|
|
|
Shutdown();
|
2026-03-16 18:48:12 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-17 02:17:41 +08:00
|
|
|
bool OpenGLFence::Initialize(bool signaled) {
|
|
|
|
|
m_fenceValue = signaled ? 1 : 0;
|
|
|
|
|
m_completedValue = m_fenceValue;
|
|
|
|
|
m_signaled = signaled;
|
2026-03-16 18:48:12 +08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OpenGLFence::Shutdown() {
|
2026-03-17 02:17:41 +08:00
|
|
|
if (m_sync) {
|
|
|
|
|
glDeleteSync(static_cast<GLsync>(m_sync));
|
|
|
|
|
m_sync = nullptr;
|
|
|
|
|
}
|
2026-03-16 18:48:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OpenGLFence::Signal() {
|
2026-03-17 02:17:41 +08:00
|
|
|
glFlush();
|
2026-03-16 18:48:12 +08:00
|
|
|
m_fenceValue++;
|
2026-03-17 02:17:41 +08:00
|
|
|
m_signaled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OpenGLFence::Signal(uint64_t value) {
|
|
|
|
|
glFlush();
|
|
|
|
|
m_fenceValue = value;
|
2026-03-23 21:09:15 +08:00
|
|
|
m_completedValue = value;
|
2026-03-17 02:17:41 +08:00
|
|
|
m_signaled = true;
|
2026-03-23 21:09:15 +08:00
|
|
|
if (m_sync) {
|
|
|
|
|
glDeleteSync(static_cast<GLsync>(m_sync));
|
|
|
|
|
}
|
|
|
|
|
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
2026-03-16 18:48:12 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-17 02:17:41 +08:00
|
|
|
void OpenGLFence::Wait(uint64_t timeoutNs) {
|
2026-03-23 21:09:15 +08:00
|
|
|
if (m_signaled && m_sync) {
|
|
|
|
|
GLsync sync = static_cast<GLsync>(m_sync);
|
|
|
|
|
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
2026-03-17 02:17:41 +08:00
|
|
|
}
|
2026-03-23 21:09:15 +08:00
|
|
|
glFinish();
|
|
|
|
|
m_completedValue = m_fenceValue;
|
|
|
|
|
m_signaled = true;
|
2026-03-16 18:48:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OpenGLFence::Reset() {
|
2026-03-17 02:17:41 +08:00
|
|
|
if (m_sync) {
|
|
|
|
|
glDeleteSync(static_cast<GLsync>(m_sync));
|
|
|
|
|
m_sync = nullptr;
|
|
|
|
|
}
|
2026-03-16 18:48:12 +08:00
|
|
|
m_signaled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool OpenGLFence::IsSignaled() const {
|
|
|
|
|
return m_signaled;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 02:17:41 +08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 21:09:15 +08:00
|
|
|
void* OpenGLFence::GetNativeHandle() {
|
|
|
|
|
if (!m_sync) {
|
|
|
|
|
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
|
|
|
}
|
|
|
|
|
return m_sync;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 18:48:12 +08:00
|
|
|
} // namespace RHI
|
|
|
|
|
} // namespace XCEngine
|