From 2c74ed1a6d15fb1dd12ad4a5841811c841d1413c Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:46:08 +0300 Subject: [PATCH] Rasterizer refactor hotfixes (#6465) * texture_codec: Clamp buffer end to tiled buffer size * Fixes crash on Pokemon Super Mystery Dungeon * rasterizer_cache: Use rect for duplicate surface * Fixes broken bloom in fire emblem * surface_params: Check levels for exact match * It was removed previously to prevent copies when games used the base level of a multi level surface. FE on the other hand will first use the base level and then use it as a face of a cubemap with many levels. So instead check if the surface equal or more levels and consider it an exact match in that case * gl_texture_runtime: Bind old tex to 2D target * Fixes a small error opengl would print when creating texture cubes * gl_blit_helper: Fix nearest filter * Use texture unit 2 which has the nearest sampler bound --- .../host_shaders/texture_filtering/nearest_neighbor.frag | 2 +- src/video_core/rasterizer_cache/rasterizer_cache.cpp | 4 ++-- src/video_core/rasterizer_cache/surface_params.cpp | 2 +- src/video_core/rasterizer_cache/texture_codec.h | 4 +++- src/video_core/renderer_opengl/gl_blit_helper.cpp | 1 + src/video_core/renderer_opengl/gl_texture_runtime.cpp | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/video_core/host_shaders/texture_filtering/nearest_neighbor.frag b/src/video_core/host_shaders/texture_filtering/nearest_neighbor.frag index 5413e7409..e2db96f91 100644 --- a/src/video_core/host_shaders/texture_filtering/nearest_neighbor.frag +++ b/src/video_core/host_shaders/texture_filtering/nearest_neighbor.frag @@ -8,7 +8,7 @@ precision mediump float; layout(location = 0) in vec2 tex_coord; layout(location = 0) out vec4 frag_color; -layout(binding = 0) uniform sampler2D input_texture; +layout(binding = 2) uniform sampler2D input_texture; void main() { frag_color = texture(input_texture, tex_coord); diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.cpp b/src/video_core/rasterizer_cache/rasterizer_cache.cpp index b5577f80e..c9464cc63 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.cpp +++ b/src/video_core/rasterizer_cache/rasterizer_cache.cpp @@ -725,8 +725,8 @@ void RasterizerCache::DuplicateSurface(const SurfaceRef& src_surface, const TextureCopy copy = { .src_level = 0, .dst_level = 0, - .src_offset = {0, 0}, - .dst_offset = {0, 0}, + .src_offset = {src_rect.left, src_rect.bottom}, + .dst_offset = {dst_rect.left, dst_rect.bottom}, .extent = {src_rect.GetWidth(), src_rect.GetHeight()}, }; runtime.CopyTextures(*src_surface, *dest_surface, copy); diff --git a/src/video_core/rasterizer_cache/surface_params.cpp b/src/video_core/rasterizer_cache/surface_params.cpp index cdd5f3a55..bbd3e38ce 100644 --- a/src/video_core/rasterizer_cache/surface_params.cpp +++ b/src/video_core/rasterizer_cache/surface_params.cpp @@ -11,7 +11,7 @@ bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { return std::tie(other_surface.addr, other_surface.width, other_surface.height, other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == std::tie(addr, width, height, stride, pixel_format, is_tiled) && - pixel_format != PixelFormat::Invalid; + pixel_format != PixelFormat::Invalid && levels >= other_surface.levels; } bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { diff --git a/src/video_core/rasterizer_cache/texture_codec.h b/src/video_core/rasterizer_cache/texture_codec.h index 3c136724d..c64ffedcd 100644 --- a/src/video_core/rasterizer_cache/texture_codec.h +++ b/src/video_core/rasterizer_cache/texture_codec.h @@ -305,7 +305,9 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en // If the copy spans multiple tiles, copy the fully aligned tiles in between. if (aligned_start_offset < aligned_end_offset) { - const u32 buffer_end = tiled_offset + aligned_end_offset - aligned_start_offset; + const u32 tile_buffer_size = static_cast(tiled_buffer.size()); + const u32 buffer_end = + std::min(tiled_offset + aligned_end_offset - aligned_start_offset, tile_buffer_size); while (tiled_offset < buffer_end) { auto linear_data = linear_buffer.subspan(linear_offset, linear_tile_stride); auto tiled_data = tiled_buffer.subspan(tiled_offset, tile_size); diff --git a/src/video_core/renderer_opengl/gl_blit_helper.cpp b/src/video_core/renderer_opengl/gl_blit_helper.cpp index 2adc92c32..e41dda81d 100644 --- a/src/video_core/renderer_opengl/gl_blit_helper.cpp +++ b/src/video_core/renderer_opengl/gl_blit_helper.cpp @@ -166,6 +166,7 @@ void BlitHelper::FilterBicubic(Surface& surface, const VideoCore::TextureBlit& b } void BlitHelper::FilterNearest(Surface& surface, const VideoCore::TextureBlit& blit) { + state.texture_units[2].texture_2d = surface.Handle(false); SetParams(nearest_program, surface.width, surface.height, blit.src_rect); Draw(nearest_program, surface.Handle(), filter_fbo.handle, blit.dst_level, blit.dst_rect); } diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index cf64780a0..3ab3b475e 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -199,7 +199,7 @@ Allocation TextureRuntime::Allocate(const VideoCore::SurfaceParams& params) { handles[1] = textures[1].handle; } - glBindTexture(target, old_tex); + glBindTexture(GL_TEXTURE_2D, old_tex); return Allocation{ .textures = std::move(textures),