diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index 1a1a3a6f76..c5179a01e0 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -21,6 +21,13 @@ namespace rsx srgb_nonlinear = 1 }; + enum surface_usage_flags : u32 + { + unknown = 0, + attachment = 1, + storage = 2 + }; + //Sampled image descriptor struct sampled_image_descriptor_base { diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 71148355f2..329f5d0aaf 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -134,6 +134,8 @@ namespace rsx GcmTileInfo *tile = nullptr; rsx::surface_antialiasing write_aa_mode = rsx::surface_antialiasing::center_1_sample; + flags32_t usage = surface_usage_flags::unknown; + union { rsx::surface_color_format gcm_color_format; diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 815b56cb2d..b560590af0 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2459,40 +2459,50 @@ namespace rsx return {}; } - if (list.back().is_clipped && !allow_clipped) + for (auto It = list.rbegin(); It != list.rend(); ++It) { - for (auto It = list.rbegin(); It != list.rend(); ++It) + if (!(It->surface->usage & rsx::surface_usage_flags::attachment)) { - if (!It->is_clipped) - { - return *It; - } - - auto _w = u32(It->width * It->surface->get_bpp()) / bpp; - auto _h = u32(It->height); - get_rsx_dimensions(_w, _h, It->surface); - - if (_w < width) - { - if ((_w * scale_x) <= 1.f) - continue; - } - - if (_h < height) - { - if ((_h * scale_y) <= 1.f) - continue; - } - - // Some surface exists, but its size is questionable - // Opt to re-upload (needs WCB/WDB to work properly) - break; + // HACK + // TODO: Properly analyse the input here to determine if it can properly fit what we need + // This is a problem due to chunked transfer + // First 2 512x720 blocks go into a cpu-side buffer but suddenly when its time to render the final 256x720 + // it falls onto some storage buffer in surface cache that has bad dimensions + // Proper solution is to always merge when a cpu resource is created (it should absorb the render targets in range) + // We then should not have any 'dst-is-rendertarget' surfaces in use + // Option 2: Make surfaces here part of surface cache and do not pad them for optimization + // Surface cache is good at merging for resolve operations. This keeps integrity even when drawing to the rendertgargets + // This option needs a lot more work + continue; } - return {}; + if (!It->is_clipped || allow_clipped) + { + return *It; + } + + auto _w = u32(It->width * It->surface->get_bpp()) / bpp; + auto _h = u32(It->height); + get_rsx_dimensions(_w, _h, It->surface); + + if (_w < width) + { + if ((_w * scale_x) <= 1.f) + continue; + } + + if (_h < height) + { + if ((_h * scale_y) <= 1.f) + continue; + } + + // Some surface exists, but its size is questionable + // Opt to re-upload (needs WCB/WDB to work properly) + break; } - return list.back(); + return {}; }; // Check if src/dst are parts of render targets diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index 9827df7d58..856d146eeb 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -188,6 +188,7 @@ struct gl_render_target_traits std::array native_layout = { (GLenum)format.swizzle.a, (GLenum)format.swizzle.r, (GLenum)format.swizzle.g, (GLenum)format.swizzle.b }; result->set_native_component_layout(native_layout); + result->usage = rsx::surface_usage_flags::attachment; result->set_cleared(false); result->queue_tag(address); result->add_ref(); @@ -215,6 +216,7 @@ struct gl_render_target_traits result->set_native_component_layout(native_layout); result->set_format(surface_depth_format); + result->usage = rsx::surface_usage_flags::attachment; result->set_cleared(false); result->queue_tag(address); result->add_ref(); @@ -234,6 +236,7 @@ struct gl_render_target_traits const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height()); sink.reset(new gl::render_target(new_w, new_h, internal_format)); + sink->usage = rsx::surface_usage_flags::storage; sink->add_ref(); sink->format_info = ref->format_info; sink->set_native_pitch(prev.width * ref->get_bpp()); @@ -272,10 +275,17 @@ struct gl_render_target_traits info->bpp = surface->get_bpp(); } - static void prepare_rtt_for_drawing(gl::command_context&, gl::render_target*) {} + static void prepare_rtt_for_drawing(gl::command_context&, gl::render_target* rtt) + { + rtt->usage |= rsx::surface_usage_flags::attachment; + } + + static void prepare_ds_for_drawing(gl::command_context&, gl::render_target* ds) + { + ds->usage |= rsx::surface_usage_flags::attachment; + } + static void prepare_rtt_for_sampling(gl::command_context&, gl::render_target*) {} - - static void prepare_ds_for_drawing(gl::command_context&, gl::render_target*) {} static void prepare_ds_for_sampling(gl::command_context&, gl::render_target*) {} static @@ -292,6 +302,7 @@ struct gl_render_target_traits surface->queue_tag(address); surface->set_cleared(false); surface->last_use_tag = 0; + surface->usage = rsx::surface_usage_flags::unknown; } static diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index e5c9a2902e..ccd122c00a 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -197,6 +197,7 @@ namespace rsx change_image_layout(cmd, rtt.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT)); rtt->set_format(format); + rtt->usage = rsx::surface_usage_flags::attachment; rtt->native_component_map = fmt.second; rtt->rsx_pitch = (u16)pitch; rtt->native_pitch = (u16)width * get_format_block_size_in_bytes(format); @@ -235,7 +236,9 @@ namespace rsx VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT| VK_IMAGE_USAGE_TRANSFER_SRC_BIT| VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, 0)); + ds->set_format(format); + ds->usage = rsx::surface_usage_flags::attachment; ds->native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; change_image_layout(cmd, ds.get(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, range); @@ -277,6 +280,7 @@ namespace rsx sink->add_ref(); sink->format_info = ref->format_info; + sink->usage = rsx::surface_usage_flags::storage; sink->native_component_map = ref->native_component_map; sink->native_pitch = u16(prev.width * ref->get_bpp()); sink->surface_width = prev.width; @@ -315,6 +319,7 @@ namespace rsx { surface->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); surface->frame_tag = 0; + surface->usage |= rsx::surface_usage_flags::attachment; } static void prepare_rtt_for_sampling(vk::command_buffer& cmd, vk::render_target *surface) @@ -326,6 +331,7 @@ namespace rsx { surface->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); surface->frame_tag = 0; + surface->usage |= rsx::surface_usage_flags::attachment; } static void prepare_ds_for_sampling(vk::command_buffer& cmd, vk::render_target *surface) @@ -345,6 +351,7 @@ namespace rsx surface->queue_tag(address); surface->dirty = true; surface->last_use_tag = 0; + surface->usage = rsx::surface_usage_flags::unknown; } static void notify_surface_invalidated(const std::unique_ptr &surface) diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index a34f7bb774..7508e14538 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -27,6 +27,11 @@ namespace rsx using utils::page_end; using utils::next_page; + using flags64_t = uint64_t; + using flags32_t = uint32_t; + using flags16_t = uint16_t; + using flags8_t = uint8_t; + // Definitions class thread; extern thread* g_current_renderer;