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
This commit is contained in:
@@ -38,7 +38,6 @@ void D3D12Fence::Signal() {
|
||||
}
|
||||
|
||||
void D3D12Fence::Signal(uint64_t value) {
|
||||
m_signalValue = value;
|
||||
m_fence->Signal(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,21 +4,19 @@
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
OpenGLFence::OpenGLFence()
|
||||
OpenGLFence::OpenGLFence()
|
||||
: m_sync(nullptr)
|
||||
, m_fenceValue(0)
|
||||
, m_completedValue(0)
|
||||
, m_signaled(false) {
|
||||
, m_signaledValue(0)
|
||||
, m_completedValue(0) {
|
||||
}
|
||||
|
||||
OpenGLFence::~OpenGLFence() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool OpenGLFence::Initialize(bool signaled) {
|
||||
m_fenceValue = signaled ? 1 : 0;
|
||||
m_completedValue = m_fenceValue;
|
||||
m_signaled = signaled;
|
||||
bool OpenGLFence::Initialize(uint64_t initialValue) {
|
||||
m_signaledValue.store(initialValue, std::memory_order_release);
|
||||
m_completedValue.store(initialValue, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,64 +25,56 @@ void OpenGLFence::Shutdown() {
|
||||
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() {
|
||||
glFlush();
|
||||
m_fenceValue++;
|
||||
m_signaled = true;
|
||||
Signal(1);
|
||||
}
|
||||
|
||||
void OpenGLFence::Signal(uint64_t value) {
|
||||
glFlush();
|
||||
m_fenceValue = value;
|
||||
m_completedValue = value;
|
||||
m_signaled = true;
|
||||
if (m_sync) {
|
||||
glDeleteSync(static_cast<GLsync>(m_sync));
|
||||
}
|
||||
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
void OpenGLFence::Wait(uint64_t timeoutNs) {
|
||||
if (m_signaled && m_sync) {
|
||||
GLsync sync = static_cast<GLsync>(m_sync);
|
||||
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
glFinish();
|
||||
m_completedValue = m_fenceValue;
|
||||
m_signaled = true;
|
||||
}
|
||||
|
||||
void OpenGLFence::Reset() {
|
||||
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;
|
||||
}
|
||||
m_signaled = false;
|
||||
|
||||
glFlush();
|
||||
|
||||
m_signaledValue.store(value, std::memory_order_release);
|
||||
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
bool OpenGLFence::IsSignaled() const {
|
||||
return m_signaled;
|
||||
}
|
||||
|
||||
FenceStatus OpenGLFence::GetStatus() const {
|
||||
if (!m_sync) {
|
||||
return m_signaled ? FenceStatus::Signaled : FenceStatus::Unsignaled;
|
||||
void OpenGLFence::Wait(uint64_t value) {
|
||||
uint64_t currentCompleted = m_completedValue.load(std::memory_order_acquire);
|
||||
if (currentCompleted >= value) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
return FenceStatus::Unsignaled;
|
||||
|
||||
uint64_t signaled = m_signaledValue.load(std::memory_order_acquire);
|
||||
m_completedValue.store(signaled, std::memory_order_release);
|
||||
}
|
||||
|
||||
uint64_t OpenGLFence::GetCompletedValue() const {
|
||||
return m_completedValue;
|
||||
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() {
|
||||
@@ -95,4 +85,4 @@ void* OpenGLFence::GetNativeHandle() {
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user