mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	gl_rasterizer_cache: Use accurate framebuffer setting for accurate copies.
This commit is contained in:
		
							parent
							
								
									123c065086
								
							
						
					
					
						commit
						7f7eb29323
					
				@ -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,63 +814,68 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
 | 
				
			|||||||
        return new_surface;
 | 
					        return new_surface;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
 | 
					    // When using accurate framebuffers, always copy old data to new surface, regardless of format
 | 
				
			||||||
    auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
 | 
					    if (Settings::values.use_accurate_framebuffers) {
 | 
				
			||||||
 | 
					        auto source_format = GetFormatTuple(params.pixel_format, 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();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle);
 | 
					        glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle);
 | 
				
			||||||
    glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
 | 
					        glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
 | 
				
			||||||
    if (source_format.compressed) {
 | 
					        if (source_format.compressed) {
 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
    // from the CPU.
 | 
					 | 
				
			||||||
    if (params.SizeInBytes() < new_params.SizeInBytes()) {
 | 
					 | 
				
			||||||
        // Upload the rest of the memory.
 | 
					 | 
				
			||||||
        if (new_params.is_tiled) {
 | 
					 | 
				
			||||||
            // TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest of
 | 
					 | 
				
			||||||
            // the data in this case. Games like Super Mario Odyssey seem to hit this case when
 | 
					 | 
				
			||||||
            // drawing, it re-uses the memory of a previous texture as a bigger framebuffer 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 "
 | 
					 | 
				
			||||||
                                 "reinterpretation but the texture is tiled.");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
 | 
					        // If the new texture is bigger than the previous one, we need to fill in the rest with data
 | 
				
			||||||
        std::vector<u8> data(remaining_size);
 | 
					        // from the CPU.
 | 
				
			||||||
        Memory::ReadBlock(new_params.addr + params.SizeInBytes(), data.data(), data.size());
 | 
					        if (params.SizeInBytes() < new_params.SizeInBytes()) {
 | 
				
			||||||
        glBufferSubData(GL_PIXEL_PACK_BUFFER, params.SizeInBytes(), remaining_size, data.data());
 | 
					            // Upload the rest of the memory.
 | 
				
			||||||
 | 
					            if (new_params.is_tiled) {
 | 
				
			||||||
 | 
					                // TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest
 | 
				
			||||||
 | 
					                // of the data in this case. Games like Super Mario Odyssey seem to hit this case
 | 
				
			||||||
 | 
					                // when drawing, it re-uses the memory of a previous texture as a bigger framebuffer
 | 
				
			||||||
 | 
					                // 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 "
 | 
				
			||||||
 | 
					                                     "reinterpretation but the texture is tiled.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
 | 
				
			||||||
 | 
					            std::vector<u8> data(remaining_size);
 | 
				
			||||||
 | 
					            Memory::ReadBlock(new_params.addr + params.SizeInBytes(), data.data(), data.size());
 | 
				
			||||||
 | 
					            glBufferSubData(GL_PIXEL_PACK_BUFFER, params.SizeInBytes(), remaining_size,
 | 
				
			||||||
 | 
					                            data.data());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& dest_rect{new_params.GetRect()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle);
 | 
				
			||||||
 | 
					        if (dest_format.compressed) {
 | 
				
			||||||
 | 
					            glCompressedTexSubImage2D(
 | 
				
			||||||
 | 
					                GL_TEXTURE_2D, 0, 0, 0, static_cast<GLsizei>(dest_rect.GetWidth()),
 | 
				
			||||||
 | 
					                static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
 | 
				
			||||||
 | 
					                static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0,
 | 
				
			||||||
 | 
					                                static_cast<GLsizei>(dest_rect.GetWidth()),
 | 
				
			||||||
 | 
					                                static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
 | 
				
			||||||
 | 
					                                dest_format.type, nullptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pbo.Release();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto& dest_rect{new_params.GetRect()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle);
 | 
					 | 
				
			||||||
    if (dest_format.compressed) {
 | 
					 | 
				
			||||||
        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
 | 
					 | 
				
			||||||
                                  static_cast<GLsizei>(dest_rect.GetWidth()),
 | 
					 | 
				
			||||||
                                  static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
 | 
					 | 
				
			||||||
                                  static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0,
 | 
					 | 
				
			||||||
                            static_cast<GLsizei>(dest_rect.GetWidth()),
 | 
					 | 
				
			||||||
                            static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
 | 
					 | 
				
			||||||
                            dest_format.type, nullptr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pbo.Release();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return new_surface;
 | 
					    return new_surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user