From 41b87cf577d00411986e1e9eac1f046108738e65 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 22 Mar 2019 14:10:29 +0300 Subject: [PATCH] rsx: Blit engine fixes - If a transfer writes to a RTT and depth mismatch happens, create a local target and the upload function will likely resolve between the two - If a surface is rejected, reset the target region! --- rpcs3/Emu/RSX/Common/texture_cache.h | 74 +++++++++++++++------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index e297f4eede..fe8770004a 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2290,6 +2290,7 @@ namespace rsx if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target)) return false; + // Check if trivial memcpy can perform the same task // Used to copy programs and arbitrary data to the GPU in some cases if (!src_is_render_target && !dst_is_render_target && dst_is_argb8 == src_is_argb8 && !dst.swizzled) @@ -2315,6 +2316,17 @@ 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) { src_subres.surface->read_barrier(cmd); @@ -2377,12 +2389,11 @@ namespace rsx reader_lock lock(m_cache_mutex); + const auto old_dst_area = dst_area; if (!dst_is_render_target) { // Check for any available region that will fit this one auto overlapping_surfaces = find_texture_from_range(address_range::start_length(dst_address, dst.pitch * dst.clip_height), dst.pitch, rsx::texture_upload_context::blit_engine_dst); - const auto old_dst_area = dst_area; - for (const auto &surface : overlapping_surfaces) { if (!surface->is_locked()) @@ -2444,48 +2455,42 @@ namespace rsx max_dst_height = dst_subres.surface->get_surface_height(); } - const bool src_is_depth = src_subres.is_depth; - const bool dst_is_depth = dst_is_render_target? dst_subres.is_depth : - dest_texture ? cached_dest->is_depth_texture() : src_is_depth; - - // Type of blit decided by the source, destination use should adapt on the fly - const bool is_depth_blit = src_is_depth; - - bool format_mismatch = (src_is_depth != dst_is_depth); - if (format_mismatch) + // Check if available target is acceptable + // TODO: Check for other types of format mismatch + bool format_mismatch = false; + if (cached_dest) { - if (dst_is_render_target) + if (cached_dest->is_depth_texture() != src_subres.is_depth) { - LOG_ERROR(RSX, "Depth<->RGBA blit on a framebuffer requested but not supported"); - return false; - } - } - else if (src_is_render_target && cached_dest) - { - 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: + // Dest surface has the wrong 'aspect' format_mismatch = true; - break; + } + 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; + } } } - //TODO: Check for other types of format mismatch - const address_range dst_range = address_range::start_length(dst_address, dst.pitch * dst.height); - AUDIT(cached_dest == nullptr || cached_dest->overlaps(dst_range, section_bounds::full_range)); 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 @@ -2564,7 +2569,10 @@ 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