renderer_opengl: Encapsulate sync objects in OGLSync

This commit is contained in:
emufan4568
2022-09-08 23:38:57 +03:00
committed by GPUCode
parent f13738d252
commit e30e977140
5 changed files with 79 additions and 24 deletions

View File

@@ -52,14 +52,15 @@ void FrameDumperOpenGL::PresentLoop() {
LOG_DEBUG(Render_OpenGL, "Reloading present frame"); LOG_DEBUG(Render_OpenGL, "Reloading present frame");
mailbox->ReloadPresentFrame(frame, layout.width, layout.height); 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); glBindFramebuffer(GL_READ_FRAMEBUFFER, frame->present.handle);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[current_pbo].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); 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 // Insert fence for the main thread to block on
frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); frame->present_fence.Create();
glFlush(); glFlush();
// Bind the previous PBO and read the pixels // Bind the previous PBO and read the pixels

View File

@@ -199,6 +199,38 @@ void OGLBuffer::Release() {
handle = 0; 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() { void OGLVertexArray::Create() {
if (handle != 0) if (handle != 0)
return; return;

View File

@@ -143,6 +143,36 @@ public:
GLuint handle = 0; 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 { class OGLPipeline : private NonCopyable {
public: public:
OGLPipeline() = default; OGLPipeline() = default;

View File

@@ -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 // INTEL driver workaround. We can't delete the previous render sync object until we are
// sure that the presentation is done // sure that the presentation is done
if (frame->present_fence) { frame->present_fence.WaitHost();
glClientWaitSync(frame->present_fence, 0, GL_TIMEOUT_IGNORED);
}
// delete the draw fence if the frame wasn't presented // Delete the draw fence if the frame wasn't presented
if (frame->render_fence) { frame->render_fence.Release();
glDeleteSync(frame->render_fence);
frame->render_fence = nullptr;
}
// wait for the presentation to be done // wait for the presentation to be done
if (frame->present_fence) { frame->present_fence.Wait();
glWaitSync(frame->present_fence, 0, GL_TIMEOUT_IGNORED); frame->present_fence.Release();
glDeleteSync(frame->present_fence);
frame->present_fence = nullptr;
}
} }
{ {
@@ -529,7 +521,7 @@ void RendererOpenGL::RenderToMailbox(const Layout::FramebufferLayout& layout,
state.Apply(); state.Apply();
DrawScreens(layout, flipped); DrawScreens(layout, flipped);
// Create a fence for the frontend to wait on and swap this frame to OffTex // 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(); glFlush();
mailbox->ReleaseRenderFrame(frame); mailbox->ReleaseRenderFrame(frame);
} }
@@ -1152,7 +1144,9 @@ void RendererOpenGL::TryPresent(int timeout_ms, bool is_secondary) {
LOG_DEBUG(Render_OpenGL, "Reloading present frame"); LOG_DEBUG(Render_OpenGL, "Reloading present frame");
window.mailbox->ReloadPresentFrame(frame, layout.width, layout.height); window.mailbox->ReloadPresentFrame(frame, layout.width, layout.height);
} }
glWaitSync(frame->render_fence, 0, GL_TIMEOUT_IGNORED);
frame->render_fence.Wait();
// INTEL workaround. // INTEL workaround.
// Normally we could just delete the draw fence here, but due to driver bugs, we can just delete // 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 // 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); GL_COLOR_BUFFER_BIT, GL_LINEAR);
// Delete the fence if we're re-presenting to avoid leaking fences // Delete the fence if we're re-presenting to avoid leaking fences
if (frame->present_fence) { frame->present_fence.Release();
glDeleteSync(frame->present_fence);
}
/* insert fence for the main thread to block on */ // Insert fence for the main thread to block on
frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); frame->present_fence.Create();
glFlush(); glFlush();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

View File

@@ -24,8 +24,8 @@ struct Frame {
OpenGL::OGLRenderbuffer color{}; /// Buffer shared between the render/present FBO OpenGL::OGLRenderbuffer color{}; /// Buffer shared between the render/present FBO
OpenGL::OGLFramebuffer render{}; /// FBO created on the render thread OpenGL::OGLFramebuffer render{}; /// FBO created on the render thread
OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread
GLsync render_fence{}; /// Fence created on the render thread OpenGL::OGLSync render_fence{}; /// Fence created on the render thread
GLsync present_fence{}; /// Fence created on the presentation thread OpenGL::OGLSync present_fence{}; /// Fence created on the presentation thread
}; };
} // namespace Frontend } // namespace Frontend