From 94a3b1cfe84f036af720c320fc8c23d365ae91ee Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 17 Nov 2021 23:02:08 +0300 Subject: [PATCH] rsx: Roll back some optimizations - Just use RGB565 for all blit targets. Avoids really dumb transforms done by GPU hw. - When X16 is used, all the channels get written to R channel alone. CmdBlit does perform format conversion! - gl: Force image copy when blit is requested with compatible targets. Avoids format conversion issues. --- rpcs3/Emu/RSX/Common/texture_cache.h | 62 +++++++---- rpcs3/Emu/RSX/Common/texture_cache_helpers.h | 10 +- rpcs3/Emu/RSX/GL/GLHelpers.cpp | 102 ++++++++++--------- rpcs3/Emu/RSX/GL/GLTextureCache.h | 5 - 4 files changed, 100 insertions(+), 79 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 1a0f60edcc..ec08506640 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2240,7 +2240,6 @@ namespace rsx const bool is_copy_op = (fcmp(scale_x, 1.f) && fcmp(scale_y, 1.f)); const bool is_format_convert = (dst_is_argb8 != src_is_argb8); - const bool is_interpolating_op = (!is_copy_op && interpolate); bool skip_if_collision_exists = false; // Offset in x and y for src is 0 (it is already accounted for when getting pixels_src) @@ -2417,14 +2416,14 @@ namespace rsx if (!typeless) [[likely]] { // Use format as-is - typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, src_subres.is_depth, false, is_interpolating_op); + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, src_subres.is_depth, false); } else { // Enable type scaling in src typeless_info.src_is_typeless = true; typeless_info.src_scaling_hint = static_cast(bpp) / src_bpp; - typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false, is_format_convert, is_interpolating_op); + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false, is_format_convert); } if (surf->get_surface_width(rsx::surface_metrics::pixels) != surf->width() || @@ -2492,14 +2491,14 @@ namespace rsx if (!typeless) [[likely]] { - typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, dst_subres.is_depth, false, is_interpolating_op); + typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, dst_subres.is_depth, false); } else { // Enable type scaling in dst typeless_info.dst_is_typeless = true; typeless_info.dst_scaling_hint = static_cast(bpp) / dst_bpp; - typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false, is_format_convert, is_interpolating_op); + typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false, is_format_convert); } } @@ -2624,7 +2623,6 @@ namespace rsx case CELL_GCM_TEXTURE_A8R8G8B8: if (!dst_is_argb8) continue; break; - case CELL_GCM_TEXTURE_X16: case CELL_GCM_TEXTURE_R5G6B5: if (dst_is_argb8) continue; break; @@ -2705,20 +2703,28 @@ namespace rsx // Force format matching; only accept 16-bit data for 16-bit transfers, 32-bit for 32-bit transfers switch (surface->get_gcm_format()) { - case CELL_GCM_TEXTURE_A8R8G8B8: - case CELL_GCM_TEXTURE_D8R8G8B8: - case CELL_GCM_TEXTURE_DEPTH24_D8: - case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_X32_FLOAT: case CELL_GCM_TEXTURE_Y16_X16: case CELL_GCM_TEXTURE_Y16_X16_FLOAT: { - if (!src_is_argb8) continue; - break; + // Should be copy compatible but not scaling compatible + if (src_is_argb8 && (is_copy_op || dst_is_render_target)) break; + continue; + } + case CELL_GCM_TEXTURE_DEPTH24_D8: + case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: + { + // Should be copy compatible but not scaling compatible + if (src_is_argb8 && (is_copy_op || !dst_is_render_target)) break; + continue; + } + case CELL_GCM_TEXTURE_A8R8G8B8: + case CELL_GCM_TEXTURE_D8R8G8B8: + { + // Perfect match + if (src_is_argb8) break; + continue; } - case CELL_GCM_TEXTURE_R5G6B5: - case CELL_GCM_TEXTURE_DEPTH16: - case CELL_GCM_TEXTURE_DEPTH16_FLOAT: case CELL_GCM_TEXTURE_X16: case CELL_GCM_TEXTURE_G8B8: case CELL_GCM_TEXTURE_A1R5G5B5: @@ -2726,8 +2732,22 @@ namespace rsx case CELL_GCM_TEXTURE_D1R5G5B5: case CELL_GCM_TEXTURE_R5G5B5A1: { - if (src_is_argb8) continue; - break; + // Copy compatible + if (!src_is_argb8 && (is_copy_op || dst_is_render_target)) break; + continue; + } + case CELL_GCM_TEXTURE_DEPTH16: + case CELL_GCM_TEXTURE_DEPTH16_FLOAT: + { + // Copy compatible + if (!src_is_argb8 && (is_copy_op || !dst_is_render_target)) break; + continue; + } + case CELL_GCM_TEXTURE_R5G6B5: + { + // Perfect match + if (!src_is_argb8) break; + continue; } default: { @@ -2800,7 +2820,7 @@ namespace rsx subres.data = { vm::_ptr(image_base), static_cast::size_type>(src.pitch * image_height) }; subresource_layout.push_back(subres); - const u32 gcm_format = helpers::get_sized_blit_format(src_is_argb8, dst_is_depth_surface, is_format_convert, is_interpolating_op); + const u32 gcm_format = helpers::get_sized_blit_format(src_is_argb8, dst_is_depth_surface, is_format_convert); const auto rsx_range = address_range::start_length(image_base, src.pitch * image_height); lock.upgrade(); @@ -2829,7 +2849,7 @@ namespace rsx } //const auto src_is_depth_format = helpers::is_gcm_depth_format(typeless_info.src_gcm_format); - const auto preferred_dst_format = helpers::get_sized_blit_format(dst_is_argb8, false, is_format_convert, is_interpolating_op); + const auto preferred_dst_format = helpers::get_sized_blit_format(dst_is_argb8, false, is_format_convert); if (cached_dest && !use_null_region) { @@ -3036,7 +3056,7 @@ namespace rsx if (!typeless_info.src_is_typeless) { typeless_info.src_is_typeless = true; - typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false, false, is_interpolating_op); + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false, false); } } else @@ -3045,7 +3065,7 @@ namespace rsx if (!typeless_info.dst_is_typeless) { typeless_info.dst_is_typeless = true; - typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false, false, is_interpolating_op); + typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false, false); } } } diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index 8feb353ad6..79027ec706 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -133,19 +133,15 @@ namespace rsx return gcm_format; } - static inline u32 get_sized_blit_format(bool is_32_bit, bool depth_format, bool is_format_convert, bool is_interpolating_op) + static inline u32 get_sized_blit_format(bool is_32_bit, bool depth_format, bool is_format_convert) { - if (is_format_convert || is_interpolating_op) - { - return (is_32_bit) ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5; - } - else if (is_32_bit) + if (is_32_bit) { return (!depth_format) ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_DEPTH24_D8; } else { - return (!depth_format) ? CELL_GCM_TEXTURE_X16 : CELL_GCM_TEXTURE_DEPTH16; + return (!depth_format) ? CELL_GCM_TEXTURE_R5G6B5 : CELL_GCM_TEXTURE_DEPTH16; } } diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index 34532b6d26..ebbeb15e1f 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -554,63 +554,73 @@ namespace gl ensure(real_src->aspect() == real_dst->aspect()); - const bool is_depth_copy = (real_src->aspect() != image_aspect::color); - const filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest; - GLenum attachment; - gl::buffers target; - - if (is_depth_copy) + if (src_rect.width() == dst_rect.width() && src_rect.height() == dst_rect.height() && + !src_rect.is_flipped() && !dst_rect.is_flipped()) { - if (real_dst->aspect() & gl::image_aspect::stencil) - { - attachment = GL_DEPTH_STENCIL_ATTACHMENT; - target = gl::buffers::depth_stencil; - } - else - { - attachment = GL_DEPTH_ATTACHMENT; - target = gl::buffers::depth; - } + glCopyImageSubData(real_src->id(), static_cast(real_src->get_target()), 0, src_rect.x1, src_rect.y1, 0, + real_dst->id(), static_cast(real_dst->get_target()), 0, dst_rect.x1, dst_rect.y1, 0, + src_rect.width(), src_rect.height(), 1); } else { - attachment = GL_COLOR_ATTACHMENT0; - target = gl::buffers::color; + const bool is_depth_copy = (real_src->aspect() != image_aspect::color); + const filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest; + GLenum attachment; + gl::buffers target; + + if (is_depth_copy) + { + if (real_dst->aspect() & gl::image_aspect::stencil) + { + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + target = gl::buffers::depth_stencil; + } + else + { + attachment = GL_DEPTH_ATTACHMENT; + target = gl::buffers::depth; + } + } + else + { + attachment = GL_COLOR_ATTACHMENT0; + target = gl::buffers::color; + } + + cmd.drv->enable(GL_FALSE, GL_SCISSOR_TEST); + + save_binding_state saved; + + glBindFramebuffer(GL_READ_FRAMEBUFFER, blit_src.id()); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_src->id(), 0); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blit_dst.id()); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_dst->id(), 0); + + if (xfer_info.flip_horizontal) + { + src_rect.flip_horizontal(); + } + + if (xfer_info.flip_vertical) + { + src_rect.flip_vertical(); + } + + glBlitFramebuffer(src_rect.x1, src_rect.y1, src_rect.x2, src_rect.y2, + dst_rect.x1, dst_rect.y1, dst_rect.x2, dst_rect.y2, + static_cast(target), static_cast(interp)); + + // Release the attachments explicitly (not doing so causes glitches, e.g Journey Menu) + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); } - cmd.drv->enable(GL_FALSE, GL_SCISSOR_TEST); - - save_binding_state saved; - - glBindFramebuffer(GL_READ_FRAMEBUFFER, blit_src.id()); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_src->id(), 0); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blit_dst.id()); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_dst->id(), 0); - - if (xfer_info.flip_horizontal) - { - src_rect.flip_horizontal(); - } - - if (xfer_info.flip_vertical) - { - src_rect.flip_vertical(); - } - - glBlitFramebuffer(src_rect.x1, src_rect.y1, src_rect.x2, src_rect.y2, - dst_rect.x1, dst_rect.y1, dst_rect.x2, dst_rect.y2, - static_cast(target), static_cast(interp)); - if (xfer_info.dst_is_typeless) { // Transfer contents from typeless dst back to original dst copy_typeless(dst, typeless_dst.get()); } - - // Release the attachments explicitly (not doing so causes glitches, e.g Journey Menu) - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); } void blitter::fast_clear_image(gl::command_context& cmd, const texture* dst, const color4f& color) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 1750b2e75d..c098a15d23 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -727,11 +727,6 @@ namespace gl cached.set_format(gl::texture::format::depth, gl::texture::type::ushort, true); break; } - case CELL_GCM_TEXTURE_X16: - { - cached.set_format(gl::texture::format::r, gl::texture::type::ushort, true); - break; - } default: fmt::throw_exception("Unexpected gcm format 0x%X", gcm_format); }