Partial revert of Choreographer implementation; it doesn't seem *that* much worse...
This commit is contained in:
parent
0184e1af53
commit
5f79f9ed6d
@ -246,7 +246,8 @@ void EmuWindow_Android::TryPresenting() {
|
||||
}
|
||||
}
|
||||
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
|
||||
if (VideoCore::g_renderer && VideoCore::g_renderer->TryPresent()) {
|
||||
if (VideoCore::g_renderer) {
|
||||
VideoCore::g_renderer->TryPresent(0);
|
||||
eglSwapBuffers(egl_display, egl_surface);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
* frame available after timeout, returns the previous frame. If there is no previous frame it
|
||||
* returns nullptr
|
||||
*/
|
||||
virtual Frontend::Frame* TryGetPresentFrame() = 0;
|
||||
virtual Frontend::Frame* TryGetPresentFrame(int timeout_ms) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
|
||||
/// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer
|
||||
/// specific implementation)
|
||||
virtual bool TryPresent() = 0;
|
||||
virtual void TryPresent(int timeout_ms) = 0;
|
||||
|
||||
/// Prepares for video dumping (e.g. create necessary buffers, etc)
|
||||
virtual void PrepareVideoDumping() = 0;
|
||||
|
@ -44,7 +44,7 @@ void FrameDumperOpenGL::PresentLoop() {
|
||||
|
||||
const auto& layout = GetLayout();
|
||||
while (!stop_requested.exchange(false)) {
|
||||
auto frame = mailbox->TryGetPresentFrame();
|
||||
auto frame = mailbox->TryGetPresentFrame(200);
|
||||
if (!frame) {
|
||||
continue;
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ class OGLTextureMailbox : public Frontend::TextureMailbox {
|
||||
public:
|
||||
std::mutex swap_chain_lock;
|
||||
std::condition_variable free_cv;
|
||||
std::condition_variable present_cv;
|
||||
std::array<Frontend::Frame, SWAP_CHAIN_SIZE> swap_chain{};
|
||||
std::queue<Frontend::Frame*> free_queue{};
|
||||
std::deque<Frontend::Frame*> present_queue{};
|
||||
Frontend::Frame* previous_frame = nullptr;
|
||||
const std::chrono::milliseconds elapsed{100};
|
||||
|
||||
OGLTextureMailbox() {
|
||||
for (auto& frame : swap_chain) {
|
||||
@ -73,6 +73,7 @@ public:
|
||||
std::scoped_lock lock(swap_chain_lock);
|
||||
std::queue<Frontend::Frame*>().swap(free_queue);
|
||||
present_queue.clear();
|
||||
present_cv.notify_all();
|
||||
free_cv.notify_all();
|
||||
}
|
||||
|
||||
@ -124,8 +125,6 @@ public:
|
||||
|
||||
// If theres no free frames, we will reuse the oldest render frame
|
||||
if (free_queue.empty()) {
|
||||
// wait for new entries in the present_queue
|
||||
free_cv.wait_for(lock, elapsed, [this] { return !present_queue.empty(); });
|
||||
auto frame = present_queue.back();
|
||||
present_queue.pop_back();
|
||||
return frame;
|
||||
@ -138,25 +137,41 @@ public:
|
||||
|
||||
void ReleaseRenderFrame(Frontend::Frame* frame) override {
|
||||
std::unique_lock<std::mutex> lock(swap_chain_lock);
|
||||
present_queue.push_back(frame);
|
||||
present_queue.push_front(frame);
|
||||
present_cv.notify_one();
|
||||
}
|
||||
|
||||
Frontend::Frame* TryGetPresentFrame() override {
|
||||
// This is virtual as it is to be overriden in OGLVideoDumpingMailbox below.
|
||||
virtual void LoadPresentFrame() {
|
||||
// free the previous frame and add it back to the free queue
|
||||
if (previous_frame) {
|
||||
free_queue.push(previous_frame);
|
||||
free_cv.notify_one();
|
||||
}
|
||||
|
||||
// the newest entries are pushed to the front of the queue
|
||||
Frontend::Frame* frame = present_queue.front();
|
||||
present_queue.pop_front();
|
||||
// remove all old entries from the present queue and move them back to the free_queue
|
||||
for (auto f : present_queue) {
|
||||
free_queue.push(f);
|
||||
}
|
||||
present_queue.clear();
|
||||
previous_frame = frame;
|
||||
}
|
||||
|
||||
Frontend::Frame* TryGetPresentFrame(int timeout_ms) override {
|
||||
std::unique_lock<std::mutex> lock(swap_chain_lock);
|
||||
// wait for new entries in the present_queue
|
||||
present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms),
|
||||
[&] { return !present_queue.empty(); });
|
||||
if (present_queue.empty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
std::unique_lock<std::mutex> lock(swap_chain_lock);
|
||||
|
||||
// free the previous frame and add it back to the free queue
|
||||
if (previous_frame) {
|
||||
free_queue.push(previous_frame);
|
||||
free_cv.notify_one();
|
||||
}
|
||||
|
||||
previous_frame = present_queue.front();
|
||||
present_queue.pop_front();
|
||||
// timed out waiting for a frame to draw so return the previous frame
|
||||
return previous_frame;
|
||||
}
|
||||
|
||||
LoadPresentFrame();
|
||||
return previous_frame;
|
||||
}
|
||||
};
|
||||
|
||||
@ -185,6 +200,35 @@ public:
|
||||
free_queue.pop();
|
||||
return frame;
|
||||
}
|
||||
|
||||
void LoadPresentFrame() override {
|
||||
// free the previous frame and add it back to the free queue
|
||||
if (previous_frame) {
|
||||
free_queue.push(previous_frame);
|
||||
free_cv.notify_one();
|
||||
}
|
||||
|
||||
Frontend::Frame* frame = present_queue.back();
|
||||
present_queue.pop_back();
|
||||
previous_frame = frame;
|
||||
|
||||
// Do not remove entries from the present_queue, as video dumping would require
|
||||
// that we preserve all frames
|
||||
}
|
||||
|
||||
Frontend::Frame* TryGetPresentFrame(int timeout_ms) override {
|
||||
std::unique_lock<std::mutex> lock(swap_chain_lock);
|
||||
// wait for new entries in the present_queue
|
||||
present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms),
|
||||
[&] { return !present_queue.empty(); });
|
||||
if (present_queue.empty()) {
|
||||
// timed out waiting for a frame
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LoadPresentFrame();
|
||||
return previous_frame;
|
||||
}
|
||||
};
|
||||
|
||||
static const char vertex_shader[] = R"(
|
||||
@ -1078,12 +1122,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
||||
}
|
||||
}
|
||||
|
||||
bool RendererOpenGL::TryPresent() {
|
||||
void RendererOpenGL::TryPresent(int timeout_ms) {
|
||||
const auto& layout = render_window.GetFramebufferLayout();
|
||||
auto frame = render_window.mailbox->TryGetPresentFrame();
|
||||
auto frame = render_window.mailbox->TryGetPresentFrame(timeout_ms);
|
||||
if (!frame) {
|
||||
LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a
|
||||
@ -1116,8 +1160,6 @@ bool RendererOpenGL::TryPresent() {
|
||||
glFlush();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Updates the framerate
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
/// Draws the latest frame from texture mailbox to the currently bound draw framebuffer in this
|
||||
/// context
|
||||
bool TryPresent() override;
|
||||
void TryPresent(int timeout_ms) override;
|
||||
|
||||
/// Prepares for video dumping (e.g. create necessary buffers, etc)
|
||||
void PrepareVideoDumping() override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user