forked from suyu/suyu
gl_rasterizer_cache: Use accurate framebuffer setting for accurate copies.
This commit is contained in:
parent
123c065086
commit
7f7eb29323
2 changed files with 57 additions and 76 deletions
|
@ -432,16 +432,6 @@ void RasterizerOpenGL::Clear() {
|
||||||
glClearStencil(regs.clear_stencil);
|
glClearStencil(regs.clear_stencil);
|
||||||
|
|
||||||
glClear(clear_mask);
|
glClear(clear_mask);
|
||||||
|
|
||||||
// Mark framebuffer surfaces as dirty
|
|
||||||
if (Settings::values.use_accurate_framebuffers) {
|
|
||||||
if (dirty_color_surface != nullptr) {
|
|
||||||
res_cache.FlushSurface(dirty_color_surface);
|
|
||||||
}
|
|
||||||
if (dirty_depth_surface != nullptr) {
|
|
||||||
res_cache.FlushSurface(dirty_depth_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u8*, GLintptr> RasterizerOpenGL::AlignBuffer(u8* buffer_ptr, GLintptr buffer_offset,
|
std::pair<u8*, GLintptr> RasterizerOpenGL::AlignBuffer(u8* buffer_ptr, GLintptr buffer_offset,
|
||||||
|
@ -557,16 +547,6 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
texture_unit.Unbind();
|
texture_unit.Unbind();
|
||||||
}
|
}
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
// Mark framebuffer surfaces as dirty
|
|
||||||
if (Settings::values.use_accurate_framebuffers) {
|
|
||||||
if (dirty_color_surface != nullptr) {
|
|
||||||
res_cache.FlushSurface(dirty_color_surface);
|
|
||||||
}
|
|
||||||
if (dirty_depth_surface != nullptr) {
|
|
||||||
res_cache.FlushSurface(dirty_depth_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {}
|
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {}
|
||||||
|
|
|
@ -760,11 +760,7 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
|
||||||
// Look up surface in the cache based on address
|
// Look up surface in the cache based on address
|
||||||
Surface surface{TryGet(params.addr)};
|
Surface surface{TryGet(params.addr)};
|
||||||
if (surface) {
|
if (surface) {
|
||||||
if (Settings::values.use_accurate_framebuffers) {
|
if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
|
||||||
// If use_accurate_framebuffers is enabled, always load from memory
|
|
||||||
FlushSurface(surface);
|
|
||||||
Unregister(surface);
|
|
||||||
} else if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
|
|
||||||
// Use the cached surface as-is
|
// Use the cached surface as-is
|
||||||
return surface;
|
return surface;
|
||||||
} else if (preserve_contents) {
|
} else if (preserve_contents) {
|
||||||
|
@ -818,13 +814,15 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
return new_surface;
|
return new_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When using accurate framebuffers, always copy old data to new surface, regardless of format
|
||||||
|
if (Settings::values.use_accurate_framebuffers) {
|
||||||
auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
|
auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
|
||||||
auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
|
auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
|
||||||
|
|
||||||
size_t buffer_size = std::max(params.SizeInBytes(), new_params.SizeInBytes());
|
size_t buffer_size = std::max(params.SizeInBytes(), new_params.SizeInBytes());
|
||||||
|
|
||||||
// Use a Pixel Buffer Object to download the previous texture and then upload it to the new one
|
// Use a Pixel Buffer Object to download the previous texture and then upload it to the new
|
||||||
// using the new format.
|
// one using the new format.
|
||||||
OGLBuffer pbo;
|
OGLBuffer pbo;
|
||||||
pbo.Create();
|
pbo.Create();
|
||||||
|
|
||||||
|
@ -834,25 +832,27 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
glGetCompressedTextureImage(surface->Texture().handle, 0,
|
glGetCompressedTextureImage(surface->Texture().handle, 0,
|
||||||
static_cast<GLsizei>(params.SizeInBytes()), nullptr);
|
static_cast<GLsizei>(params.SizeInBytes()), nullptr);
|
||||||
} else {
|
} else {
|
||||||
glGetTextureImage(surface->Texture().handle, 0, source_format.format, source_format.type,
|
glGetTextureImage(surface->Texture().handle, 0, source_format.format,
|
||||||
static_cast<GLsizei>(params.SizeInBytes()), nullptr);
|
source_format.type, static_cast<GLsizei>(params.SizeInBytes()),
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
// If the new texture is bigger than the previous one, we need to fill in the rest with data
|
// If the new texture is bigger than the previous one, we need to fill in the rest with data
|
||||||
// from the CPU.
|
// from the CPU.
|
||||||
if (params.SizeInBytes() < new_params.SizeInBytes()) {
|
if (params.SizeInBytes() < new_params.SizeInBytes()) {
|
||||||
// Upload the rest of the memory.
|
// Upload the rest of the memory.
|
||||||
if (new_params.is_tiled) {
|
if (new_params.is_tiled) {
|
||||||
// TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest of
|
// TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest
|
||||||
// the data in this case. Games like Super Mario Odyssey seem to hit this case when
|
// of the data in this case. Games like Super Mario Odyssey seem to hit this case
|
||||||
// drawing, it re-uses the memory of a previous texture as a bigger framebuffer but it
|
// when drawing, it re-uses the memory of a previous texture as a bigger framebuffer
|
||||||
// doesn't clear it beforehand, the texture is already full of zeros.
|
// but it doesn't clear it beforehand, the texture is already full of zeros.
|
||||||
LOG_CRITICAL(HW_GPU, "Trying to upload extra texture data from the CPU during "
|
LOG_CRITICAL(HW_GPU, "Trying to upload extra texture data from the CPU during "
|
||||||
"reinterpretation but the texture is tiled.");
|
"reinterpretation but the texture is tiled.");
|
||||||
}
|
}
|
||||||
size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
|
size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
|
||||||
std::vector<u8> data(remaining_size);
|
std::vector<u8> data(remaining_size);
|
||||||
Memory::ReadBlock(new_params.addr + params.SizeInBytes(), data.data(), data.size());
|
Memory::ReadBlock(new_params.addr + params.SizeInBytes(), data.data(), data.size());
|
||||||
glBufferSubData(GL_PIXEL_PACK_BUFFER, params.SizeInBytes(), remaining_size, data.data());
|
glBufferSubData(GL_PIXEL_PACK_BUFFER, params.SizeInBytes(), remaining_size,
|
||||||
|
data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
@ -861,8 +861,8 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle);
|
||||||
if (dest_format.compressed) {
|
if (dest_format.compressed) {
|
||||||
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
|
glCompressedTexSubImage2D(
|
||||||
static_cast<GLsizei>(dest_rect.GetWidth()),
|
GL_TEXTURE_2D, 0, 0, 0, static_cast<GLsizei>(dest_rect.GetWidth()),
|
||||||
static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
|
static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
|
||||||
static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
|
static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -874,6 +874,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
pbo.Release();
|
pbo.Release();
|
||||||
|
}
|
||||||
|
|
||||||
return new_surface;
|
return new_surface;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue