From 4a0e1c79ed64113d263800a69bdf84e772c1c2a6 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 17 Nov 2019 23:03:18 +0300 Subject: [PATCH] rsx: Improve format validation for blit engine - Check all possible cases where format mismatch is possible. - Warn if a slow path is going to be taken. Should help with future optimizations. --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 1 - rpcs3/Emu/RSX/Common/TextureUtils.h | 2 - rpcs3/Emu/RSX/Common/texture_cache.h | 226 ++++++++++--------- rpcs3/Emu/RSX/Common/texture_cache_helpers.h | 13 +- rpcs3/Emu/RSX/GL/GLHelpers.cpp | 40 ++-- rpcs3/Emu/RSX/GL/GLHelpers.h | 2 +- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 3 +- rpcs3/Emu/RSX/GL/GLTextureCache.h | 7 +- rpcs3/Emu/RSX/VK/VKHelpers.h | 2 +- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 3 +- rpcs3/Emu/RSX/VK/VKTexture.cpp | 46 ++-- 11 files changed, 188 insertions(+), 157 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 45de801efd..daeed5b856 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -15,7 +15,6 @@ namespace rsx { if (fcmp(src_scaling_hint, dst_scaling_hint) && !fcmp(src_scaling_hint, 1.f)) { - verify(HERE), src_is_depth == dst_is_depth; src_is_typeless = dst_is_typeless = false; src_scaling_hint = dst_scaling_hint = 1.f; } diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index 20bf3d77f9..07f3df6d44 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -68,8 +68,6 @@ namespace rsx { bool src_is_typeless = false; bool dst_is_typeless = false; - bool src_is_depth = false; - bool dst_is_depth = false; bool flip_vertical = false; bool flip_horizontal = false; diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 744287b3d4..c4785bc69c 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -12,6 +12,8 @@ extern u64 get_system_time(); namespace rsx { + namespace helpers = rsx::texture_cache_helpers; + template class texture_cache { @@ -1487,11 +1489,11 @@ namespace rsx if (UNLIKELY(m_rtts.address_is_bound(attr.address))) { if (auto texptr = m_rtts.get_surface_at(attr.address); - texture_cache_helpers::check_framebuffer_resource(texptr, attr, extended_dimension)) + helpers::check_framebuffer_resource(texptr, attr, extended_dimension)) { const bool force_convert = !render_target_format_is_compatible(texptr, attr.gcm_format); - auto result = texture_cache_helpers::process_framebuffer_resource_fast( + auto result = helpers::process_framebuffer_resource_fast( cmd, texptr, attr, scale, extended_dimension, encoded_remap, remap, true, force_convert); if (!options.skip_texture_barriers && result.is_cyclic_reference) @@ -1515,7 +1517,7 @@ namespace rsx { const bool force_convert = !render_target_format_is_compatible(last.surface, attr.gcm_format); - return texture_cache_helpers::process_framebuffer_resource_fast( + return helpers::process_framebuffer_resource_fast( cmd, last.surface, attr, scale, extended_dimension, encoded_remap, remap, false, force_convert); } @@ -1611,23 +1613,23 @@ namespace rsx normalized_width >= attr.width && last->get_height() >= attr.height) { u32 gcm_format = attr.gcm_format; - const bool gcm_format_is_depth = texture_cache_helpers::is_gcm_depth_format(attr.gcm_format); + const bool gcm_format_is_depth = helpers::is_gcm_depth_format(attr.gcm_format); if (!gcm_format_is_depth && last->is_depth_texture()) { // While the copy routines can perform a typeless cast, prefer to not cross the aspect barrier if possible - gcm_format = texture_cache_helpers::get_compatible_depth_format(attr.gcm_format); + gcm_format = helpers::get_compatible_depth_format(attr.gcm_format); } auto new_attr = attr; new_attr.gcm_format = gcm_format; return { last->get_raw_texture(), deferred_request_command::copy_image_static, new_attr, {}, - last->get_context(), texture_cache_helpers::get_format_class(gcm_format), scale, extended_dimension, remap }; + last->get_context(), helpers::get_format_class(gcm_format), scale, extended_dimension, remap }; } } - auto result = texture_cache_helpers::merge_cache_resources( + auto result = helpers::merge_cache_resources( overlapping_fbos, overlapping_locals, attr, scale, extended_dimension, encoded_remap, remap, _pool); if (options.skip_texture_merge) @@ -1692,7 +1694,7 @@ namespace rsx const bool is_swizzled = !(tex.format() & CELL_GCM_TEXTURE_LN); auto extended_dimension = tex.get_extended_texture_dimension(); - options.is_compressed_format = texture_cache_helpers::is_compressed_gcm_format(attributes.gcm_format); + options.is_compressed_format = helpers::is_compressed_gcm_format(attributes.gcm_format); u32 tex_size = 0, required_surface_height; u8 subsurface_count; @@ -1801,7 +1803,7 @@ namespace rsx std::vector sections; const bool use_upscaling = (result.upload_context == rsx::texture_upload_context::framebuffer_storage && g_cfg.video.resolution_scale_percent != 100); - if (UNLIKELY(!texture_cache_helpers::append_mipmap_level(sections, result, attributes, 0, use_upscaling, attributes))) + if (UNLIKELY(!helpers::append_mipmap_level(sections, result, attributes, 0, use_upscaling, attributes))) { // Abort if mip0 is not compatible return result; @@ -1831,7 +1833,7 @@ namespace rsx options, range, extended_dimension, m_rtts, std::forward(extras)...); if (!ret.validate() || - !texture_cache_helpers::append_mipmap_level(sections, ret, attr2, subsurface, use_upscaling, attributes)) + !helpers::append_mipmap_level(sections, ret, attr2, subsurface, use_upscaling, attributes)) { // Abort break; @@ -1866,7 +1868,7 @@ namespace rsx // Do direct upload from CPU as the last resort const auto subresources_layout = get_subresources_layout(tex); - const auto format_class = texture_cache_helpers::get_format_class(attributes.gcm_format); + const auto format_class = helpers::get_format_class(attributes.gcm_format); if (!tex_size) { @@ -2083,28 +2085,23 @@ namespace rsx } } - // Sanity and format compatibility checks - if (dst_is_render_target) - { - if (src_subres.is_depth != dst_subres.is_depth) - { - // Create a cache-local resource to resolve later - // TODO: Support depth->RGBA typeless transfer for vulkan - dst_is_render_target = false; - } - } - if (src_is_render_target) { const auto surf = src_subres.surface; const auto bpp = surf->get_bpp(); - if (bpp != src_bpp) + const bool typeless = (bpp != src_bpp || is_format_convert); + + if (LIKELY(!typeless)) { - //Enable type scaling in src + // Use format as-is + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, src_subres.is_depth); + } + else + { + // Enable type scaling in src typeless_info.src_is_typeless = true; - typeless_info.src_is_depth = src_subres.is_depth; typeless_info.src_scaling_hint = (f32)bpp / src_bpp; - typeless_info.src_gcm_format = src_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5; + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false); } if (surf->get_surface_width(rsx::surface_metrics::pixels) != surf->width() || @@ -2118,18 +2115,24 @@ namespace rsx if (dst_is_render_target) { - auto bpp = dst_subres.surface->get_bpp(); - if (bpp != dst_bpp) + const auto bpp = dst_subres.surface->get_bpp(); + const bool typeless = (bpp != dst_bpp || is_format_convert); + + if (LIKELY(!typeless)) { - //Enable type scaling in dst + typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, dst_subres.is_depth); + } + else + { + // Enable type scaling in dst typeless_info.dst_is_typeless = true; - typeless_info.dst_is_depth = dst_subres.is_depth; typeless_info.dst_scaling_hint = (f32)bpp / dst_bpp; - typeless_info.dst_gcm_format = dst_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5; + typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false); } } section_storage_type* cached_dest = nullptr; + bool dst_is_depth_surface = false; u16 max_dst_width = dst.width; u16 max_dst_height = dst.height; areai src_area = { 0, 0, src_w, src_h }; @@ -2202,6 +2205,20 @@ namespace rsx continue; } + switch (surface->get_gcm_format()) + { + case CELL_GCM_TEXTURE_A8R8G8B8: + case CELL_GCM_TEXTURE_DEPTH24_D8: + if (!dst_is_argb8) continue; + break; + case CELL_GCM_TEXTURE_R5G6B5: + case CELL_GCM_TEXTURE_DEPTH16: + if (dst_is_argb8) continue; + break; + default: + continue; + } + if (const u32 address_offset = dst_address - this_address) { const u16 offset_y = address_offset / dst.pitch; @@ -2229,6 +2246,38 @@ namespace rsx dst_area = old_dst_area; } + + const bool format_check = (src_is_render_target || is_format_convert); + if (!use_null_region && cached_dest && format_check) + { + bool src_is_depth; + if (is_format_convert) + { + src_is_depth = false; + } + else + { + verify(HERE), src_is_render_target; + src_is_depth = (typeless_info.src_is_typeless)? false : src_subres.is_depth; + } + + if (cached_dest->is_depth_texture() != src_is_depth) + { + // Opt to cancel the destination. Can also use typeless convert + LOG_WARNING(RSX, "Format mismatch on blit destination block. Performance warning."); + + // The invalidate call before creating a new target will remove this section + cached_dest = nullptr; + dest_texture = 0; + dst_area = old_dst_area; + } + } + + if (LIKELY(cached_dest)) + { + typeless_info.dst_gcm_format = cached_dest->get_gcm_format(); + dst_is_depth_surface = cached_dest->is_depth_texture(); + } } else { @@ -2237,59 +2286,26 @@ namespace rsx dest_texture = dst_subres.surface->get_surface(rsx::surface_access::transfer); typeless_info.dst_context = texture_upload_context::framebuffer_storage; + dst_is_depth_surface = typeless_info.dst_is_typeless ? false : dst_subres.is_depth; max_dst_width = (u16)(dst_subres.surface->get_surface_width(rsx::surface_metrics::samples) * typeless_info.dst_scaling_hint); max_dst_height = dst_subres.surface->get_surface_height(rsx::surface_metrics::samples); } - // Check if available target is acceptable - // TODO: Check for other types of format mismatch - if (cached_dest && !use_null_region) - { - bool format_mismatch = false; - if (cached_dest->is_depth_texture() != src_subres.is_depth) - { - // Dest surface has the wrong 'aspect' - format_mismatch = true; - } - else - { - // Check if it matches the transfer declaration - switch (cached_dest->get_gcm_format()) - { - case CELL_GCM_TEXTURE_A8R8G8B8: - case CELL_GCM_TEXTURE_DEPTH24_D8: - format_mismatch = !dst_is_argb8; - break; - case CELL_GCM_TEXTURE_R5G6B5: - case CELL_GCM_TEXTURE_DEPTH16: - format_mismatch = dst_is_argb8; - break; - default: - format_mismatch = true; - break; - } - } - - if (format_mismatch) - { - // The invalidate call before creating a new target will remove this section - cached_dest = nullptr; - dest_texture = 0; - dst_area = old_dst_area; - } - } - // Create source texture if does not exist // TODO: This can be greatly improved with DMA optimizations. Most transfer operations here are actually non-graphical (no transforms applied) if (!src_is_render_target) { // NOTE: Src address already takes into account the flipped nature of the overlap! - const u32 gcm_format = src_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5; const u32 lookup_mask = rsx::texture_upload_context::blit_engine_src | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::shader_read; auto overlapping_surfaces = find_texture_from_range(address_range::start_length(src_address, src_payload_length), src.pitch, lookup_mask); auto old_src_area = src_area; + section_storage_type *cached_src = nullptr; + + // If no source exists, a dest texture must exist since format matching should always pass + verify(HERE), dest_texture; + for (const auto &surface : overlapping_surfaces) { if (!surface->is_locked()) @@ -2352,27 +2368,14 @@ namespace rsx if (src_area.x2 <= surface->get_width() && src_area.y2 <= surface->get_height()) { - vram_texture = surface->get_raw_texture(); - typeless_info.src_context = surface->get_context(); - typeless_info.src_is_depth = surface->is_depth_texture(); - - const bool dst_is_depth = cached_dest ? cached_dest->is_depth_texture() : dst_subres.is_depth; - if (dst_is_depth != typeless_info.src_is_depth && !typeless_info.dst_is_typeless) - { - // Transfer crosses the dreaded DEPTH_STENCIL<->COLOR barrier - // Transfer in a typeless context using this surface as the reference - typeless_info.dst_is_depth = dst_is_depth; - typeless_info.dst_is_typeless = true; - typeless_info.dst_gcm_format = surface->get_gcm_format(); - } - + cached_src = surface; break; } src_area = old_src_area; } - if (!vram_texture) + if (!cached_src) { const u16 full_width = src.pitch / src_bpp; u32 image_base = src.rsx_address; @@ -2394,11 +2397,6 @@ namespace rsx image_height = src_h; } - lock.upgrade(); - - const auto rsx_range = address_range::start_length(image_base, src.pitch * image_height); - invalidate_range_impl_base(cmd, rsx_range, invalidation_cause::read, std::forward(extras)...); - std::vector subresource_layout; rsx_subresource_layout subres = {}; subres.width_in_block = subres.width_in_texel = image_width; @@ -2408,11 +2406,30 @@ namespace rsx subres.data = { vm::_ptr(image_base), static_cast::index_type>(src.pitch * image_height) }; subresource_layout.push_back(subres); - vram_texture = upload_image_from_cpu(cmd, rsx_range, image_width, image_height, 1, 1, src.pitch, gcm_format, texture_upload_context::blit_engine_src, - subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, dst.swizzled)->get_raw_texture(); + const u32 gcm_format = helpers::get_sized_blit_format(src_is_argb8, dst_is_depth_surface); + const auto rsx_range = address_range::start_length(image_base, src.pitch * image_height); - typeless_info.src_context = texture_upload_context::blit_engine_src; + lock.upgrade(); + + invalidate_range_impl_base(cmd, rsx_range, invalidation_cause::read, std::forward(extras)...); + + cached_src = upload_image_from_cpu(cmd, rsx_range, image_width, image_height, 1, 1, src.pitch, gcm_format, texture_upload_context::blit_engine_src, + subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, dst.swizzled); + + typeless_info.src_gcm_format = gcm_format; } + else if (cached_src->is_depth_texture() != dst_is_depth_surface) + { + typeless_info.src_is_typeless = true; + typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, dst_is_depth_surface); + } + else + { + typeless_info.src_gcm_format = cached_src->get_gcm_format(); + } + + vram_texture = cached_src->get_raw_texture(); + typeless_info.src_context = cached_src->get_context(); } else { @@ -2421,15 +2438,7 @@ namespace rsx typeless_info.src_context = texture_upload_context::framebuffer_storage; } - // Type of blit decided by the source, destination use should adapt on the fly - const bool is_depth_blit = src_subres.is_depth; - u32 gcm_format; - - if (is_depth_blit) - gcm_format = (dst_is_argb8) ? CELL_GCM_TEXTURE_DEPTH24_D8 : CELL_GCM_TEXTURE_DEPTH16; - else - gcm_format = (dst_is_argb8) ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5; - + const auto preferred_dst_format = helpers::get_sized_blit_format(dst_is_argb8, dst_is_depth_surface); if (cached_dest && !use_null_region) { // Prep surface @@ -2437,7 +2446,7 @@ namespace rsx dst_is_argb8 ? rsx::texture_create_flags::default_component_order : rsx::texture_create_flags::swapped_native_component_order; - enforce_surface_creation_type(*cached_dest, gcm_format, channel_order); + enforce_surface_creation_type(*cached_dest, preferred_dst_format, channel_order); } // Validate clipping region @@ -2520,7 +2529,7 @@ namespace rsx if (!dst_area.x1 && !dst_area.y1 && dst_area.x2 == dst_dimensions.width && dst_area.y2 == dst_dimensions.height) { cached_dest = create_new_texture(cmd, rsx_range, dst_dimensions.width, dst_dimensions.height, 1, 1, dst.pitch, - gcm_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d, + preferred_dst_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d, channel_order); } else @@ -2541,10 +2550,12 @@ namespace rsx subresource_layout.push_back(subres); cached_dest = upload_image_from_cpu(cmd, rsx_range, dst_dimensions.width, dst_dimensions.height, 1, 1, dst.pitch, - gcm_format, rsx::texture_upload_context::blit_engine_dst, subresource_layout, + preferred_dst_format, rsx::texture_upload_context::blit_engine_dst, subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, false); - enforce_surface_creation_type(*cached_dest, gcm_format, channel_order); + enforce_surface_creation_type(*cached_dest, preferred_dst_format, channel_order); + + typeless_info.dst_gcm_format = preferred_dst_format; } dest_texture = cached_dest->get_raw_texture(); @@ -2626,7 +2637,7 @@ namespace rsx if (!use_null_region) { typeless_info.analyse(); - blitter.scale_image(cmd, vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit, typeless_info); + blitter.scale_image(cmd, vram_texture, dest_texture, src_area, dst_area, interpolate, typeless_info); } else { @@ -2634,7 +2645,6 @@ namespace rsx } blit_op_result result = true; - result.is_depth = is_depth_blit; if (cached_dest) { diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index a273eed65e..f1bf23ace9 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -61,7 +61,6 @@ namespace rsx struct blit_op_result { bool succeeded = false; - bool is_depth = false; u32 real_dst_address = 0; u32 real_dst_size = 0; @@ -123,6 +122,18 @@ namespace rsx return gcm_format; } + static inline u32 get_sized_blit_format(bool _32_bit, bool depth_format) + { + if (LIKELY(_32_bit)) + { + return (!depth_format) ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_DEPTH24_D8; + } + else + { + return (!depth_format) ? CELL_GCM_TEXTURE_R5G6B5 : CELL_GCM_TEXTURE_DEPTH16; + } + } + static inline bool is_compressed_gcm_format(u32 format) { switch (format) diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index d98c6bed83..52742bd984 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -374,8 +374,8 @@ namespace gl return attrib_t(index); } - void blitter::scale_image(gl::command_context& cmd, const texture* src, texture* dst, areai src_rect, areai dst_rect, bool linear_interpolation, - bool is_depth_copy, const rsx::typeless_xfer& xfer_info) + void blitter::scale_image(gl::command_context& cmd, const texture* src, texture* dst, areai src_rect, areai dst_rect, + bool linear_interpolation, const rsx::typeless_xfer& xfer_info) { std::unique_ptr typeless_src; std::unique_ptr typeless_dst; @@ -384,41 +384,49 @@ namespace gl if (xfer_info.src_is_typeless) { - const auto internal_width = (u16)(src->width() * xfer_info.src_scaling_hint); const auto internal_fmt = xfer_info.src_native_format_override ? GLenum(xfer_info.src_native_format_override) : get_sized_internal_format(xfer_info.src_gcm_format); - typeless_src = std::make_unique(GL_TEXTURE_2D, internal_width, src->height(), 1, 1, internal_fmt); - copy_typeless(typeless_src.get(), src); + if (static_cast(internal_fmt) != src->get_internal_format()) + { + const auto internal_width = (u16)(src->width() * xfer_info.src_scaling_hint); + typeless_src = std::make_unique(GL_TEXTURE_2D, internal_width, src->height(), 1, 1, internal_fmt); + copy_typeless(typeless_src.get(), src); - real_src = typeless_src.get(); - src_rect.x1 = (u16)(src_rect.x1 * xfer_info.src_scaling_hint); - src_rect.x2 = (u16)(src_rect.x2 * xfer_info.src_scaling_hint); + real_src = typeless_src.get(); + src_rect.x1 = (u16)(src_rect.x1 * xfer_info.src_scaling_hint); + src_rect.x2 = (u16)(src_rect.x2 * xfer_info.src_scaling_hint); + } } if (xfer_info.dst_is_typeless) { - const auto internal_width = (u16)(dst->width() * xfer_info.dst_scaling_hint); const auto internal_fmt = xfer_info.dst_native_format_override ? GLenum(xfer_info.dst_native_format_override) : get_sized_internal_format(xfer_info.dst_gcm_format); - typeless_dst = std::make_unique(GL_TEXTURE_2D, internal_width, dst->height(), 1, 1, internal_fmt); - copy_typeless(typeless_dst.get(), dst); + if (static_cast(internal_fmt) != dst->get_internal_format()) + { + const auto internal_width = (u16)(dst->width() * xfer_info.dst_scaling_hint); + typeless_dst = std::make_unique(GL_TEXTURE_2D, internal_width, dst->height(), 1, 1, internal_fmt); + copy_typeless(typeless_dst.get(), dst); - real_dst = typeless_dst.get(); - dst_rect.x1 = (u16)(dst_rect.x1 * xfer_info.dst_scaling_hint); - dst_rect.x2 = (u16)(dst_rect.x2 * xfer_info.dst_scaling_hint); + real_dst = typeless_dst.get(); + dst_rect.x1 = (u16)(dst_rect.x1 * xfer_info.dst_scaling_hint); + dst_rect.x2 = (u16)(dst_rect.x2 * xfer_info.dst_scaling_hint); + } } - filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest; + verify(HERE), 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) { - verify(HERE), real_src->aspect() == real_dst->aspect(); if (real_dst->aspect() & gl::image_aspect::stencil) { attachment = GL_DEPTH_STENCIL_ATTACHMENT; diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index d35fce0c7a..5ec956a59d 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -2926,7 +2926,7 @@ public: } void scale_image(gl::command_context& cmd, const texture* src, texture* dst, areai src_rect, areai dst_rect, bool linear_interpolation, - bool is_depth_copy, const rsx::typeless_xfer& xfer_info); + const rsx::typeless_xfer& xfer_info); void fast_clear_image(gl::command_context& cmd, const texture* dst, const color4f& color); void fast_clear_image(gl::command_context& cmd, const texture* dst, float depth, u8 stencil); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index d9b8a0a18d..2dadf4d382 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -485,7 +485,6 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, bool force_init typeless_info.src_is_typeless = true; typeless_info.src_context = rsx::texture_upload_context::framebuffer_storage; typeless_info.src_native_format_override = (u32)get_internal_format(); - typeless_info.src_is_depth = !!(src_texture->aspect() & gl::image_aspect::depth); typeless_info.src_scaling_hint = f32(src_bpp) / dst_bpp; } } @@ -508,7 +507,7 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, bool force_init gl::g_hw_blitter->scale_image(cmd, section.source, this, section.src_rect(), section.dst_rect(), - !dst_is_depth, dst_is_depth, typeless_info); + !dst_is_depth, typeless_info); newest_tag = src_texture->last_use_tag; } diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index a822c20d54..67899b6949 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -258,9 +258,8 @@ namespace gl scaled_texture = std::make_unique(GL_TEXTURE_2D, real_width, real_height, 1, 1, (GLenum)ifmt); } - const bool is_depth = is_depth_texture(); - const bool linear_interp = is_depth? false : true; - g_hw_blitter->scale_image(cmd, vram_texture, scaled_texture.get(), src_area, dst_area, linear_interp, is_depth, {}); + const bool linear_interp = is_depth_texture() ? false : true; + g_hw_blitter->scale_image(cmd, vram_texture, scaled_texture.get(), src_area, dst_area, linear_interp, {}); target_texture = scaled_texture.get(); } } @@ -643,7 +642,7 @@ namespace gl } _blitter->scale_image(cmd, src_image, _dst, - src_rect, dst_rect, false, false, {}); + src_rect, dst_rect, false, {}); if (_dst != dst_image) { diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index f8449fc7e7..c671e2fff9 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -3534,6 +3534,6 @@ public: struct blitter { - void scale_image(vk::command_buffer& cmd, vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool interpolate, bool /*is_depth*/, const rsx::typeless_xfer& xfer_info); + void scale_image(vk::command_buffer& cmd, vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool interpolate, const rsx::typeless_xfer& xfer_info); }; } diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 1f5aee67f1..80365f4ea3 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -457,7 +457,6 @@ namespace vk typeless_info.src_is_typeless = true; typeless_info.src_context = rsx::texture_upload_context::framebuffer_storage; typeless_info.src_native_format_override = (u32)info.format; - typeless_info.src_is_depth = is_depth; typeless_info.src_scaling_hint = f32(src_bpp) / dst_bpp; } } @@ -502,7 +501,7 @@ namespace vk this->get_surface(rsx::surface_access::transfer), src_area, dst_area, - /*linear?*/false, /*depth?(unused)*/false, typeless_info); + /*linear?*/false, typeless_info); optimize_copy = optimize_copy && !memory_load; newest_tag = src_texture->last_use_tag; diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 61a9f7e94b..0d67caa647 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -847,7 +847,7 @@ namespace vk return{ final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; } - void blitter::scale_image(vk::command_buffer& cmd, vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool interpolate, bool /*is_depth*/, const rsx::typeless_xfer& xfer_info) + void blitter::scale_image(vk::command_buffer& cmd, vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool interpolate, const rsx::typeless_xfer& xfer_info) { const auto src_aspect = vk::get_aspect_flags(src->info.format); const auto dst_aspect = vk::get_aspect_flags(dst->info.format); @@ -857,40 +857,48 @@ namespace vk if (xfer_info.src_is_typeless) { - const auto internal_width = src->width() * xfer_info.src_scaling_hint; const auto format = xfer_info.src_native_format_override ? VkFormat(xfer_info.src_native_format_override) : vk::get_compatible_sampler_format(vk::get_current_renderer()->get_formats_support(), xfer_info.src_gcm_format); - const auto aspect = vk::get_aspect_flags(format); - // Transfer bits from src to typeless src - real_src = vk::get_typeless_helper(format, (u32)internal_width, src->height()); - vk::change_image_layout(cmd, real_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); + if (format != src->format()) + { + const auto internal_width = src->width() * xfer_info.src_scaling_hint; + const auto aspect = vk::get_aspect_flags(format); - vk::copy_image_typeless(cmd, src, real_src, { 0, 0, (s32)src->width(), (s32)src->height() }, { 0, 0, (s32)internal_width, (s32)src->height() }, 1, - vk::get_aspect_flags(src->info.format), aspect); + // Transfer bits from src to typeless src + real_src = vk::get_typeless_helper(format, (u32)internal_width, src->height()); + vk::change_image_layout(cmd, real_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); - src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint); - src_area.x2 = (u16)(src_area.x2 * xfer_info.src_scaling_hint); + vk::copy_image_typeless(cmd, src, real_src, { 0, 0, (s32)src->width(), (s32)src->height() }, { 0, 0, (s32)internal_width, (s32)src->height() }, 1, + vk::get_aspect_flags(src->info.format), aspect); + + src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint); + src_area.x2 = (u16)(src_area.x2 * xfer_info.src_scaling_hint); + } } if (xfer_info.dst_is_typeless) { - const auto internal_width = dst->width() * xfer_info.dst_scaling_hint; const auto format = xfer_info.dst_native_format_override ? VkFormat(xfer_info.dst_native_format_override) : vk::get_compatible_sampler_format(vk::get_current_renderer()->get_formats_support(), xfer_info.dst_gcm_format); - const auto aspect = vk::get_aspect_flags(format); - // Transfer bits from dst to typeless dst - real_dst = vk::get_typeless_helper(format, (u32)internal_width, dst->height()); - vk::change_image_layout(cmd, real_dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); + if (format != dst->format()) + { + const auto internal_width = dst->width() * xfer_info.dst_scaling_hint; + const auto aspect = vk::get_aspect_flags(format); - vk::copy_image_typeless(cmd, dst, real_dst, { 0, 0, (s32)dst->width(), (s32)dst->height() }, { 0, 0, (s32)internal_width, (s32)dst->height() }, 1, - vk::get_aspect_flags(dst->info.format), aspect); + // Transfer bits from dst to typeless dst + real_dst = vk::get_typeless_helper(format, (u32)internal_width, dst->height()); + vk::change_image_layout(cmd, real_dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); - dst_area.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint); - dst_area.x2 = (u16)(dst_area.x2 * xfer_info.dst_scaling_hint); + vk::copy_image_typeless(cmd, dst, real_dst, { 0, 0, (s32)dst->width(), (s32)dst->height() }, { 0, 0, (s32)internal_width, (s32)dst->height() }, 1, + vk::get_aspect_flags(dst->info.format), aspect); + + dst_area.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint); + dst_area.x2 = (u16)(dst_area.x2 * xfer_info.dst_scaling_hint); + } } // Checks