OpenGL: Separate submit/present for this backend as well

This commit is contained in:
Henrik Rydgård 2023-08-10 17:34:20 +02:00
parent 7087bd8ae6
commit 0143d67f9b
4 changed files with 56 additions and 40 deletions

View file

@ -377,7 +377,7 @@ void GLRenderManager::Finish() {
frameData_[curFrame].deleter.Take(deleter_); frameData_[curFrame].deleter.Take(deleter_);
VLOG("PUSH: Finish, pushing task. curFrame = %d", curFrame); VLOG("PUSH: Finish, pushing task. curFrame = %d", curFrame);
GLRRenderThreadTask *task = new GLRRenderThreadTask(GLRRunType::PRESENT); GLRRenderThreadTask *task = new GLRRenderThreadTask(GLRRunType::SUBMIT);
task->frame = curFrame; task->frame = curFrame;
{ {
@ -414,10 +414,56 @@ void GLRenderManager::Finish() {
insideFrame_ = false; insideFrame_ = false;
} }
void GLRenderManager::Present() {
int curFrame = GetCurFrame();
GLRRenderThreadTask *task = new GLRRenderThreadTask(GLRRunType::PRESENT);
task->frame = curFrame;
std::unique_lock<std::mutex> lock(pushMutex_);
renderThreadQueue_.push(task);
}
// Render thread. Returns true if the caller should handle a swap. // Render thread. Returns true if the caller should handle a swap.
bool GLRenderManager::Run(GLRRenderThreadTask &task) { bool GLRenderManager::Run(GLRRenderThreadTask &task) {
GLFrameData &frameData = frameData_[task.frame]; GLFrameData &frameData = frameData_[task.frame];
if (task.runType == GLRRunType::PRESENT) {
bool swapRequest = false;
if (!frameData.skipSwap) {
if (swapIntervalChanged_) {
swapIntervalChanged_ = false;
if (swapIntervalFunction_) {
swapIntervalFunction_(swapInterval_);
}
}
// This is the swapchain framebuffer flip.
if (swapFunction_) {
VLOG(" PULL: SwapFunction()");
swapFunction_();
if (!retainControl_) {
// get out of here.
swapRequest = true;
}
} else {
VLOG(" PULL: SwapRequested");
swapRequest = true;
}
} else {
frameData.skipSwap = false;
}
frameData.hasBegun = false;
VLOG(" PULL: Frame %d.readyForFence = true", task.frame);
{
std::lock_guard<std::mutex> lock(frameData.fenceMutex);
frameData.readyForFence = true;
frameData.fenceCondVar.notify_one();
// At this point, we're done with this framedata (for now).
}
return swapRequest;
}
if (!frameData.hasBegun) { if (!frameData.hasBegun) {
frameData.hasBegun = true; frameData.hasBegun = true;
@ -461,43 +507,8 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) {
} }
} }
bool swapRequest = false;
switch (task.runType) { switch (task.runType) {
case GLRRunType::PRESENT: case GLRRunType::SUBMIT:
if (!frameData.skipSwap) {
if (swapIntervalChanged_) {
swapIntervalChanged_ = false;
if (swapIntervalFunction_) {
swapIntervalFunction_(swapInterval_);
}
}
// This is the swapchain framebuffer flip.
if (swapFunction_) {
VLOG(" PULL: SwapFunction()");
swapFunction_();
if (!retainControl_) {
// get out of here.
swapRequest = true;
}
} else {
VLOG(" PULL: SwapRequested");
swapRequest = true;
}
} else {
frameData.skipSwap = false;
}
frameData.hasBegun = false;
VLOG(" PULL: Frame %d.readyForFence = true", task.frame);
{
std::lock_guard<std::mutex> lock(frameData.fenceMutex);
frameData.readyForFence = true;
frameData.fenceCondVar.notify_one();
// At this point, we're done with this framedata (for now).
}
break; break;
case GLRRunType::SYNC: case GLRRunType::SYNC:
@ -516,7 +527,7 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) {
_assert_(false); _assert_(false);
} }
VLOG(" PULL: ::Run(): Done running tasks"); VLOG(" PULL: ::Run(): Done running tasks");
return swapRequest; return false;
} }
void GLRenderManager::FlushSync() { void GLRenderManager::FlushSync() {

View file

@ -198,6 +198,7 @@ public:
}; };
enum class GLRRunType { enum class GLRRunType {
SUBMIT,
PRESENT, PRESENT,
SYNC, SYNC,
EXIT, EXIT,
@ -253,7 +254,8 @@ public:
// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again. // Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
void BeginFrame(bool enableProfiling); void BeginFrame(bool enableProfiling);
// Can run on a different thread! // Can run on a different thread!
void Finish(); void Finish();
void Present();
// Creation commands. These were not needed in Vulkan since there we can do that on the main thread. // Creation commands. These were not needed in Vulkan since there we can do that on the main thread.
// We pass in width/height here even though it's not strictly needed until we support glTextureStorage // We pass in width/height here even though it's not strictly needed until we support glTextureStorage

View file

@ -803,6 +803,7 @@ void OpenGLContext::EndFrame() {
} }
void OpenGLContext::Present() { void OpenGLContext::Present() {
renderManager_.Present();
frameCount_++; frameCount_++;
} }

View file

@ -1172,8 +1172,10 @@ namespace Libretro
gpu->EndHostFrame(); gpu->EndHostFrame();
if (ctx->GetDrawContext()) if (ctx->GetDrawContext()) {
ctx->GetDrawContext()->EndFrame(); ctx->GetDrawContext()->EndFrame();
ctx->GetDrawContext()->Present();
}
} }
static void EmuThreadFunc() static void EmuThreadFunc()