renderer_opengl: Encapsulate sync objects in OGLSync
This commit is contained in:
@@ -52,14 +52,15 @@ void FrameDumperOpenGL::PresentLoop() {
|
||||
LOG_DEBUG(Render_OpenGL, "Reloading present frame");
|
||||
mailbox->ReloadPresentFrame(frame, layout.width, layout.height);
|
||||
}
|
||||
glWaitSync(frame->render_fence, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
frame->render_fence.Wait();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, frame->present.handle);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[current_pbo].handle);
|
||||
glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
|
||||
|
||||
// Insert fence for the main thread to block on
|
||||
frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
frame->present_fence.Create();
|
||||
glFlush();
|
||||
|
||||
// Bind the previous PBO and read the pixels
|
||||
|
@@ -199,6 +199,38 @@ void OGLBuffer::Release() {
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
void OGLSync::Create() {
|
||||
if (handle != 0)
|
||||
return;
|
||||
|
||||
handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
void OGLSync::Release() {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
glDeleteSync(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
void OGLSync::WaitHost() {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
glClientWaitSync(handle, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
void OGLSync::Wait() {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
glWaitSync(handle, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
void OGLVertexArray::Create() {
|
||||
if (handle != 0)
|
||||
return;
|
||||
|
@@ -143,6 +143,36 @@ public:
|
||||
GLuint handle = 0;
|
||||
};
|
||||
|
||||
class OGLSync final : private NonCopyable {
|
||||
public:
|
||||
OGLSync() = default;
|
||||
|
||||
OGLSync(OGLSync&& o) noexcept : handle(std::exchange(o.handle, nullptr)) {}
|
||||
|
||||
~OGLSync() {
|
||||
Release();
|
||||
}
|
||||
OGLSync& operator=(OGLSync&& o) noexcept {
|
||||
Release();
|
||||
handle = std::exchange(o.handle, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Creates a new internal OpenGL resource and stores the handle
|
||||
void Create();
|
||||
|
||||
/// Deletes the internal OpenGL resource
|
||||
void Release();
|
||||
|
||||
/// Causes the host to wait for the OpenGL semaphore
|
||||
void WaitHost();
|
||||
|
||||
/// Causes the GPU to wait for the OpenGL semaphore
|
||||
void Wait();
|
||||
|
||||
GLsync handle = 0;
|
||||
};
|
||||
|
||||
class OGLPipeline : private NonCopyable {
|
||||
public:
|
||||
OGLPipeline() = default;
|
||||
|
@@ -499,22 +499,14 @@ void RendererOpenGL::RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||
|
||||
// INTEL driver workaround. We can't delete the previous render sync object until we are
|
||||
// sure that the presentation is done
|
||||
if (frame->present_fence) {
|
||||
glClientWaitSync(frame->present_fence, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
frame->present_fence.WaitHost();
|
||||
|
||||
// delete the draw fence if the frame wasn't presented
|
||||
if (frame->render_fence) {
|
||||
glDeleteSync(frame->render_fence);
|
||||
frame->render_fence = nullptr;
|
||||
}
|
||||
// Delete the draw fence if the frame wasn't presented
|
||||
frame->render_fence.Release();
|
||||
|
||||
// wait for the presentation to be done
|
||||
if (frame->present_fence) {
|
||||
glWaitSync(frame->present_fence, 0, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(frame->present_fence);
|
||||
frame->present_fence = nullptr;
|
||||
}
|
||||
frame->present_fence.Wait();
|
||||
frame->present_fence.Release();
|
||||
}
|
||||
|
||||
{
|
||||
@@ -529,7 +521,7 @@ void RendererOpenGL::RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||
state.Apply();
|
||||
DrawScreens(layout, flipped);
|
||||
// Create a fence for the frontend to wait on and swap this frame to OffTex
|
||||
frame->render_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
frame->render_fence.Create();
|
||||
glFlush();
|
||||
mailbox->ReleaseRenderFrame(frame);
|
||||
}
|
||||
@@ -1152,7 +1144,9 @@ void RendererOpenGL::TryPresent(int timeout_ms, bool is_secondary) {
|
||||
LOG_DEBUG(Render_OpenGL, "Reloading present frame");
|
||||
window.mailbox->ReloadPresentFrame(frame, layout.width, layout.height);
|
||||
}
|
||||
glWaitSync(frame->render_fence, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
frame->render_fence.Wait();
|
||||
|
||||
// INTEL workaround.
|
||||
// Normally we could just delete the draw fence here, but due to driver bugs, we can just delete
|
||||
// it on the emulation thread without too much penalty
|
||||
@@ -1164,12 +1158,10 @@ void RendererOpenGL::TryPresent(int timeout_ms, bool is_secondary) {
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
// Delete the fence if we're re-presenting to avoid leaking fences
|
||||
if (frame->present_fence) {
|
||||
glDeleteSync(frame->present_fence);
|
||||
}
|
||||
frame->present_fence.Release();
|
||||
|
||||
/* insert fence for the main thread to block on */
|
||||
frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
// Insert fence for the main thread to block on
|
||||
frame->present_fence.Create();
|
||||
glFlush();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
@@ -24,8 +24,8 @@ struct Frame {
|
||||
OpenGL::OGLRenderbuffer color{}; /// Buffer shared between the render/present FBO
|
||||
OpenGL::OGLFramebuffer render{}; /// FBO created on the render thread
|
||||
OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread
|
||||
GLsync render_fence{}; /// Fence created on the render thread
|
||||
GLsync present_fence{}; /// Fence created on the presentation thread
|
||||
OpenGL::OGLSync render_fence{}; /// Fence created on the render thread
|
||||
OpenGL::OGLSync present_fence{}; /// Fence created on the presentation thread
|
||||
};
|
||||
} // namespace Frontend
|
||||
|
||||
|
Reference in New Issue
Block a user