mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 23:10:33 +02:00
GLRFramebuffer's destructor binds the default framebuffer, while the queue runner's cache still had the previous one as bound. A following readback from that framebuffer skipped the bind and read the default framebuffer instead. Cars Race-O-Rama and MX vs ATV Reflex recreate framebuffers every few frames, so their luminance readback came back as zeros on about half the frames and their brightness adaptation went wrong on GL. Now GL reads the same values as Vulkan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
81 lines
2.3 KiB
C++
81 lines
2.3 KiB
C++
#include "Common/GPU/OpenGL/GLCommon.h"
|
|
#include "Common/GPU/OpenGL/GLFrameData.h"
|
|
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
|
#include "Common/Log.h"
|
|
|
|
void GLDeleter::Take(GLDeleter &other) {
|
|
_assert_msg_(IsEmpty(), "Deleter already has stuff");
|
|
shaders = std::move(other.shaders);
|
|
programs = std::move(other.programs);
|
|
buffers = std::move(other.buffers);
|
|
textures = std::move(other.textures);
|
|
inputLayouts = std::move(other.inputLayouts);
|
|
framebuffers = std::move(other.framebuffers);
|
|
pushBuffers = std::move(other.pushBuffers);
|
|
other.shaders.clear();
|
|
other.programs.clear();
|
|
other.buffers.clear();
|
|
other.textures.clear();
|
|
other.inputLayouts.clear();
|
|
other.framebuffers.clear();
|
|
other.pushBuffers.clear();
|
|
}
|
|
|
|
// Runs on the GPU thread.
|
|
void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) {
|
|
for (auto pushBuffer : pushBuffers) {
|
|
renderManager->UnregisterPushBuffer(pushBuffer);
|
|
if (skipGLCalls) {
|
|
pushBuffer->Destroy(false);
|
|
}
|
|
delete pushBuffer;
|
|
}
|
|
pushBuffers.clear();
|
|
for (auto shader : shaders) {
|
|
if (skipGLCalls && shader)
|
|
shader->shader = 0; // prevent the glDeleteShader
|
|
delete shader;
|
|
}
|
|
shaders.clear();
|
|
for (auto program : programs) {
|
|
if (skipGLCalls && program)
|
|
program->program = 0; // prevent the glDeleteProgram
|
|
delete program;
|
|
}
|
|
programs.clear();
|
|
for (auto buffer : buffers) {
|
|
if (skipGLCalls && buffer)
|
|
buffer->buffer_ = 0;
|
|
delete buffer;
|
|
}
|
|
buffers.clear();
|
|
for (auto texture : textures) {
|
|
if (skipGLCalls && texture)
|
|
texture->texture = 0;
|
|
delete texture;
|
|
}
|
|
textures.clear();
|
|
for (auto inputLayout : inputLayouts) {
|
|
// No GL objects in an inputLayout yet
|
|
delete inputLayout;
|
|
}
|
|
inputLayouts.clear();
|
|
for (auto framebuffer : framebuffers) {
|
|
if (skipGLCalls) {
|
|
framebuffer->handle = 0;
|
|
framebuffer->color_texture.texture = 0;
|
|
framebuffer->z_stencil_buffer = 0;
|
|
framebuffer->z_stencil_texture.texture = 0;
|
|
framebuffer->z_buffer = 0;
|
|
framebuffer->stencil_buffer = 0;
|
|
}
|
|
delete framebuffer;
|
|
}
|
|
if (!framebuffers.empty() && !skipGLCalls) {
|
|
// The destructor bound the default framebuffer. Without this, the next readback from the framebuffer
|
|
// that was bound before could read the default one (zeros for Cars Race-O-Rama's luminance, #15914).
|
|
renderManager->ForgetBoundFramebuffers();
|
|
}
|
|
framebuffers.clear();
|
|
}
|