diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index fbad66f7ed..8ab5b28b5e 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -262,11 +262,13 @@ namespace rsx u16 h; }; + using texture_channel_remap_t = std::pair, std::array>; struct deferred_subresource { image_resource_type external_handle = 0; std::array external_cubemap_sources; std::vector sections_to_copy; + texture_channel_remap_t remap; u32 base_address = 0; u32 gcm_format = 0; u16 x = 0; @@ -280,8 +282,8 @@ namespace rsx deferred_subresource() {} - deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h) : - external_handle(_res), base_address(_addr), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h) + deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h, const texture_channel_remap_t& _remap) : + external_handle(_res), base_address(_addr), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h), remap(_remap) {} }; @@ -316,9 +318,9 @@ namespace rsx } sampled_image_descriptor(image_resource_type external_handle, u32 base_address, u32 gcm_format, u16 x_offset, u16 y_offset, u16 width, u16 height, - texture_upload_context ctx, bool is_depth, f32 x_scale, f32 y_scale, rsx::texture_dimension_extended type) + texture_upload_context ctx, bool is_depth, f32 x_scale, f32 y_scale, rsx::texture_dimension_extended type, const texture_channel_remap_t& remap) { - external_subresource_desc = { external_handle, base_address, gcm_format, x_offset, y_offset, width, height }; + external_subresource_desc = { external_handle, base_address, gcm_format, x_offset, y_offset, width, height, remap }; image_handle = 0; upload_context = ctx; @@ -336,7 +338,7 @@ namespace rsx }; protected: - std::pair, std::array> default_remap_vector = + texture_channel_remap_t default_remap_vector = { { CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B }, { CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP } @@ -375,17 +377,17 @@ namespace rsx /* Helpers */ virtual void free_texture_section(section_storage_type&) = 0; - virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0; - virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0; + virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0; + virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0; virtual section_storage_type* create_new_texture(commandbuffer_type&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format, - rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags, rsx::texture_colorspace colorspace, const std::pair, std::array>& remap_vector) = 0; + rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags, rsx::texture_colorspace colorspace, const texture_channel_remap_t& remap_vector) = 0; virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, texture_upload_context context, - const std::vector& subresource_layout, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace, bool swizzled, const std::pair, std::array>& remap_vector) = 0; + const std::vector& subresource_layout, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& remap_vector) = 0; virtual void enforce_surface_creation_type(section_storage_type& section, u32 gcm_format, texture_create_flags expected) = 0; - virtual void set_up_remap_vector(section_storage_type& section, const std::pair, std::array>& remap_vector) = 0; + virtual void set_up_remap_vector(section_storage_type& section, const texture_channel_remap_t& remap_vector) = 0; virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0; - virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array& sources) = 0; - virtual image_view_type generate_atlas_from_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy) = 0; + virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array& sources, const texture_channel_remap_t& remap_vector) = 0; + virtual image_view_type generate_atlas_from_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy, const texture_channel_remap_t& remap_vector) = 0; virtual void update_image_contents(commandbuffer_type&, image_view_type dst, image_resource_type src, u16 width, u16 height) = 0; virtual bool render_target_format_is_compatible(image_storage_type* tex, u32 gcm_format) = 0; @@ -1267,11 +1269,11 @@ namespace rsx image_view_type result = 0; if (desc.is_copy_cmd) - result = generate_atlas_from_images(cmd, desc.gcm_format, desc.width, desc.height, desc.sections_to_copy); + result = generate_atlas_from_images(cmd, desc.gcm_format, desc.width, desc.height, desc.sections_to_copy, desc.remap); else if (desc.is_cubemap) - result = generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources); + result = generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources, desc.remap); else - result = create_temporary_subresource_view(cmd, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height); + result = create_temporary_subresource_view(cmd, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height, desc.remap); if (result) { @@ -1288,7 +1290,7 @@ namespace rsx template sampled_image_descriptor process_framebuffer_resource(commandbuffer_type& cmd, render_target_type texptr, u32 texaddr, u32 gcm_format, surface_store_type& m_rtts, - u16 tex_width, u16 tex_height, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth) + u16 tex_width, u16 tex_height, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth, const texture_channel_remap_t& remap) { const u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); const auto surface_width = texptr->get_surface_width(); @@ -1348,7 +1350,7 @@ namespace rsx sampled_image_descriptor desc = { texptr->get_surface(), texaddr, format, 0, 0, rsx::apply_resolution_scale(surface_width, true), rsx::apply_resolution_scale(surface_height, true), texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f, - rsx::texture_dimension_extended::texture_dimension_cubemap }; + rsx::texture_dimension_extended::texture_dimension_cubemap, remap }; desc.set_external_cubemap_resources(image_array); return desc; @@ -1383,7 +1385,7 @@ namespace rsx sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h, texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, - rsx::texture_dimension_extended::texture_dimension_2d }; + rsx::texture_dimension_extended::texture_dimension_2d, remap }; result.external_subresource_desc.is_copy_cmd = true; result.external_subresource_desc.sections_to_copy.reserve(overlapping.size()); @@ -1472,13 +1474,13 @@ namespace rsx const auto h = rsx::apply_resolution_scale(internal_height, true); sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h, texture_upload_context::framebuffer_storage, - is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d }; + is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d, remap }; result.external_subresource_desc.update_cached = update_subresource_cache; return result; } - return{ texptr->get_view(), texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d }; + return{ texptr->get_view(remap), texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d }; } template @@ -1527,7 +1529,8 @@ namespace rsx { if (test_framebuffer(texaddr)) { - return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, tex_pitch, extended_dimension, false); + return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, + tex_width, tex_height, tex_pitch, extended_dimension, false, tex.decoded_remap()); } else { @@ -1540,7 +1543,8 @@ namespace rsx { if (test_framebuffer(texaddr)) { - return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, tex_pitch, extended_dimension, true); + return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, + tex_width, tex_height, tex_pitch, extended_dimension, true, tex.decoded_remap()); } else { @@ -1559,17 +1563,11 @@ namespace rsx if (!is_compressed_format) { - /* Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise - * This check is much stricter than the one above - * (Turbo: Super Stunt Squad does this; bypassing the need for a sync object) - * The engine does not read back the texture resource through cell, but specifies a texture location that is - * a bound render target. We can bypass the expensive download in this case - */ + // Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch); if (rsc.surface) { - //TODO: Check that this region is not cpu-dirty before doing a copy if (!test_framebuffer(rsc.base_address)) { m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface); @@ -1587,23 +1585,10 @@ namespace rsx u16 internal_height = tex_height; get_native_dimensions(internal_width, internal_height, rsc.surface); - if (!rsc.is_bound || !g_cfg.video.strict_rendering_mode) + if (!rsc.x && !rsc.y && rsc.w == internal_width && rsc.h == internal_height) { - if (!rsc.x && !rsc.y && rsc.w == internal_width && rsc.h == internal_height) - { - if (rsc.is_bound) - { - LOG_WARNING(RSX, "Sampling from a currently bound render target @ 0x%x", texaddr); - insert_texture_barrier(cmd, rsc.surface); - } - - return{ rsc.surface->get_view(), texture_upload_context::framebuffer_storage, rsc.is_depth_surface, - scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d }; - } - } - else - { - LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); + //Full sized hit from the surface cache. This should have been already found before getting here + fmt::throw_exception("Unreachable" HERE); } internal_width = rsx::apply_resolution_scale(internal_width, true); @@ -1611,7 +1596,7 @@ namespace rsx return{ rsc.surface->get_surface(), rsc.base_address, format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false), internal_width, internal_height, texture_upload_context::framebuffer_storage, rsc.is_depth_surface, scale_x, scale_y, - rsx::texture_dimension_extended::texture_dimension_2d }; + rsx::texture_dimension_extended::texture_dimension_2d, tex.decoded_remap() }; } } } @@ -1680,7 +1665,7 @@ namespace rsx auto src_image = surface->get_raw_texture(); return{ src_image, surface->get_section_base(), format, offset_x, offset_y, tex_width, tex_height, texture_upload_context::blit_engine_dst, - surface->is_depth_texture(), scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d }; + surface->is_depth_texture(), scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d, default_remap_vector }; } } } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index c58022bd28..1fe1a52dab 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -63,7 +63,7 @@ namespace gl u16 surface_pixel_size = 0; texture::internal_format compatible_internal_format = texture::internal_format::rgba8; - + std::array native_component_mapping; public: render_target *old_contents = nullptr; @@ -116,8 +116,10 @@ namespace gl return id(); } - u32 get_view() const + u32 get_view(const std::pair, std::array>& remap) const { + bind(); + apply_swizzle_remap(GL_TEXTURE_2D, native_component_mapping, remap); return id(); } @@ -137,6 +139,12 @@ namespace gl internal_height = height(); surface_width = rsx::apply_inverse_resolution_scale(internal_width, true); surface_height = rsx::apply_inverse_resolution_scale(internal_height, true); + + bind(); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&native_component_mapping[0]); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&native_component_mapping[1]); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&native_component_mapping[2]); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&native_component_mapping[3]); } bool matches_dimensions(u16 _width, u16 _height) const diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 01e8b25e61..b1ef0abdf5 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -654,7 +654,8 @@ namespace gl m_temporary_surfaces.resize(0); } - u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format, u16 x, u16 y, u16 width, u16 height, bool copy = true) + u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format, + u16 x, u16 y, u16 width, u16 height, const texture_channel_remap_t& remap, bool copy) { u32 dst_id = 0; @@ -712,6 +713,10 @@ namespace gl apply_component_mapping_flags(dst_type, gcm_format, rsx::texture_create_flags::default_component_order); } + if (memcmp(remap.first.data(), default_remap_vector.first.data(), 4) || + memcmp(remap.second.data(), default_remap_vector.second.data(), 4)) + set_up_remap_vector(dst_id, dst_type, remap); + return dst_id; } @@ -765,6 +770,18 @@ namespace gl } } + void set_up_remap_vector(u32 texture_id, GLenum texture_type, const texture_channel_remap_t& remap_vector) + { + std::array swizzle_remap; + glBindTexture(texture_type, texture_id); + glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_A, (GLint*)&swizzle_remap[0]); + glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_R, (GLint*)&swizzle_remap[1]); + glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_G, (GLint*)&swizzle_remap[2]); + glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_B, (GLint*)&swizzle_remap[3]); + + apply_swizzle_remap(texture_type, swizzle_remap, remap_vector); + } + protected: void free_texture_section(cached_texture_section& tex) override @@ -772,24 +789,28 @@ namespace gl tex.destroy(); } - u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override + u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, + const texture_channel_remap_t& remap_vector) override { - return create_temporary_subresource_impl(*src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h); + return create_temporary_subresource_impl(*src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true); } - u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override + u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, + const texture_channel_remap_t& remap_vector) override { if (auto as_rtt = dynamic_cast(src)) { - return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), GL_TEXTURE_2D, gcm_format, x, y, w, h); + return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), + GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true); } else { - return create_temporary_subresource_impl(src->id(), GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h); + return create_temporary_subresource_impl(src->id(), GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, + remap_vector, true); } } - u32 generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::array& sources) override + u32 generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::array& sources, const texture_channel_remap_t& remap_vector) override { const GLenum ifmt = gl::get_sized_internal_format(gcm_format); GLuint dst_id = 0; @@ -826,9 +847,10 @@ namespace gl return dst_id; } - u32 generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy) override + u32 generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy, + const texture_channel_remap_t& remap_vector) override { - auto result = create_temporary_subresource_impl(sections_to_copy.front().src, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, false); + auto result = create_temporary_subresource_impl(sections_to_copy.front().src, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false); for (const auto ®ion : sections_to_copy) { @@ -847,7 +869,7 @@ namespace gl cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags, - rsx::texture_colorspace colorspace, const std::pair, std::array>& /*remap_vector*/) override + rsx::texture_colorspace colorspace, const texture_channel_remap_t& /*remap_vector*/) override { u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace); bool depth_flag = false; @@ -919,7 +941,7 @@ namespace gl cached_texture_section* upload_image_from_cpu(void*&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, - rsx::texture_colorspace colorspace, bool swizzled, const std::pair, std::array>& remap_vector) override + rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& remap_vector) override { void* unused = nullptr; auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type, @@ -955,16 +977,9 @@ namespace gl section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); } - void set_up_remap_vector(cached_texture_section& section, const std::pair, std::array>& remap_vector) override + void set_up_remap_vector(cached_texture_section& section, const texture_channel_remap_t& remap_vector) override { - std::array swizzle_remap; - glBindTexture(GL_TEXTURE_2D, section.get_raw_texture()); - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&swizzle_remap[0]); - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&swizzle_remap[1]); - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&swizzle_remap[2]); - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&swizzle_remap[3]); - - apply_swizzle_remap(GL_TEXTURE_2D, swizzle_remap, remap_vector); + set_up_remap_vector(section.get_raw_texture(), GL_TEXTURE_2D, remap_vector); section.set_sampler_status(rsx::texture_sampler_status::status_ready); } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 53702c5612..4c6025c6b7 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -75,6 +75,7 @@ namespace vk bool sanitize_fp_values(); VkComponentMapping default_component_map(); + VkComponentMapping apply_swizzle_remap(const std::array& base_remap, const std::pair, std::array>& remap_vector); VkImageSubresource default_image_subresource(); VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect); diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 45f1c49fed..89fdfb88cf 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -20,7 +20,7 @@ namespace vk u16 surface_height = 0; VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT; - std::unique_ptr view; + std::vector> views; render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid @@ -42,13 +42,43 @@ namespace vk mipmaps, layers, samples, initial_layout, tiling, usage, image_flags) {} + vk::image_view* get_view(const std::pair, std::array>& remap) + { + VkComponentMapping real_mapping = vk::apply_swizzle_remap + ( + {native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b }, + remap + ); + + for (const auto& view : views) + { + if (view->info.components.a == real_mapping.a && + view->info.components.r == real_mapping.r && + view->info.components.g == real_mapping.g && + view->info.components.b == real_mapping.b) + { + return view.get(); + } + } + + auto view = std::make_unique(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format, + real_mapping, vk::get_image_subresource_range(0, 0, 1, 1, attachment_aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT))); + + views.push_back(std::move(view)); + return views.back().get(); + } + vk::image_view* get_view() { - if (!view) - view = std::make_unique(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format, + if (views.empty()) + { + auto view = std::make_unique(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format, native_component_map, vk::get_image_subresource_range(0, 0, 1, 1, attachment_aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT))); - return view.get(); + views.push_back(std::move(view)); + } + + return views.back().get(); } vk::image* get_surface() const override diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 8000f84370..a83f0c9203 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -180,4 +180,29 @@ namespace vk mipmap_level++; } } + + VkComponentMapping apply_swizzle_remap(const std::array& base_remap, const std::pair, std::array>& remap_vector) + { + VkComponentSwizzle final_mapping[4] = {}; + + for (u8 channel = 0; channel < 4; ++channel) + { + switch (remap_vector.second[channel]) + { + case CELL_GCM_TEXTURE_REMAP_ONE: + final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE; + break; + case CELL_GCM_TEXTURE_REMAP_ZERO: + final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO; + break; + case CELL_GCM_TEXTURE_REMAP_REMAP: + final_mapping[channel] = base_remap[remap_vector.first[channel]]; + break; + default: + LOG_ERROR(RSX, "Unknown remap lookup value %d", remap_vector.second[channel]); + } + } + + return{ final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; + } } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 6ed540fee4..548fbb9c18 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -489,32 +489,7 @@ namespace vk m_discarded_memory_size = 0; } - VkComponentMapping apply_swizzle_remap(const std::array& base_remap, const std::pair, std::array>& remap_vector) - { - VkComponentSwizzle final_mapping[4] = {}; - - for (u8 channel = 0; channel < 4; ++channel) - { - switch (remap_vector.second[channel]) - { - case CELL_GCM_TEXTURE_REMAP_ONE: - final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE; - break; - case CELL_GCM_TEXTURE_REMAP_ZERO: - final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO; - break; - case CELL_GCM_TEXTURE_REMAP_REMAP: - final_mapping[channel] = base_remap[remap_vector.first[channel]]; - break; - default: - LOG_ERROR(RSX, "Unknown remap lookup value %d", remap_vector.second[channel]); - } - } - - return { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; - } - - VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const std::pair, std::array>& remap_vector) + VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const texture_channel_remap_t& remap_vector) { //NOTE: Depth textures should always read RRRR switch (gcm_format) @@ -535,7 +510,7 @@ namespace vk { case rsx::texture_create_flags::default_component_order: { - mapping = apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector); + mapping = vk::apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector); break; } case rsx::texture_create_flags::native_component_order: @@ -564,7 +539,8 @@ namespace vk tex.destroy(); } - vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, bool copy = true) + vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, + u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector, bool copy) { VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; @@ -597,16 +573,22 @@ namespace vk w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, source->info.flags)); + //This method is almost exclusively used to work on framebuffer resources + //Keep the original swizzle layout unless there is data format conversion VkComponentMapping view_swizzle = source->native_component_map; if (dst_format != source->info.format) { //This is a data cast operation //Use native mapping for the new type - //TODO: Also reapply the view swizzle + //TODO: Also simlulate the readback+reupload step (very tricky) const auto remap = get_component_mapping(gcm_format); view_swizzle = { remap[1], remap[2], remap[3], remap[0] }; } + if (memcmp(remap_vector.first.data(), default_remap_vector.first.data(), 4) || + memcmp(remap_vector.second.data(), default_remap_vector.second.data(), 4)) + view_swizzle = vk::apply_swizzle_remap({view_swizzle.a, view_swizzle.r, view_swizzle.g, view_swizzle.b}, remap_vector); + VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 }; view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, view_type, dst_format, view_swizzle, view_range)); @@ -637,17 +619,21 @@ namespace vk return m_discardable_storage.back().view.get(); } - vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override + vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format, + u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) override { - return create_temporary_subresource_view_impl(cmd, source, source->info.imageType, VK_IMAGE_VIEW_TYPE_2D, gcm_format, x, y, w, h); + return create_temporary_subresource_view_impl(cmd, source, source->info.imageType, VK_IMAGE_VIEW_TYPE_2D, + gcm_format, x, y, w, h, remap_vector, true); } - vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override + vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, + u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) override { - return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h); + return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h, remap_vector); } - vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size, const std::array& sources) override + vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size, + const std::array& sources, const texture_channel_remap_t& remap_vector) override { std::unique_ptr image; std::unique_ptr view; @@ -719,10 +705,11 @@ namespace vk return m_discardable_storage.back().view.get(); } - vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy) override + vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, + const std::vector& sections_to_copy, const texture_channel_remap_t& remap_vector) override { auto result = create_temporary_subresource_view_impl(cmd, sections_to_copy.front().src, VK_IMAGE_TYPE_2D, - VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, false); + VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, default_remap_vector, false); VkImage dst = result->info.image; VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; @@ -800,7 +787,7 @@ namespace vk cached_texture_section* create_new_texture(vk::command_buffer& cmd, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags, - rsx::texture_colorspace colorspace, const std::pair, std::array>& remap_vector) override + rsx::texture_colorspace colorspace, const texture_channel_remap_t& remap_vector) override { const u16 section_depth = depth; const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap; @@ -902,7 +889,7 @@ namespace vk cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, - rsx::texture_colorspace colorspace, bool swizzled, const std::pair, std::array>& remap_vector) override + rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& remap_vector) override { auto section = create_new_texture(cmd, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type, rsx::texture_create_flags::default_component_order, colorspace, remap_vector); @@ -971,13 +958,13 @@ namespace vk section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); } - void set_up_remap_vector(cached_texture_section& section, const std::pair, std::array>& remap_vector) override + void set_up_remap_vector(cached_texture_section& section, const texture_channel_remap_t& remap_vector) override { auto& view = section.get_view(); auto& original_remap = view->info.components; std::array base_remap = {original_remap.a, original_remap.r, original_remap.g, original_remap.b}; - auto final_remap = apply_swizzle_remap(base_remap, remap_vector); + auto final_remap = vk::apply_swizzle_remap(base_remap, remap_vector); if (final_remap.a != original_remap.a || final_remap.r != original_remap.r || final_remap.g != original_remap.g ||