diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 54a7a89bb4..ef0e1419f1 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -155,11 +155,6 @@ namespace rsx class texture_cache { private: - std::pair, std::array> 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 } - }; struct ranged_storage { @@ -277,6 +272,12 @@ namespace rsx }; protected: + std::pair, std::array> 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 } + }; + shared_mutex m_cache_mutex; std::unordered_map m_cache; std::unordered_multimap> m_temporary_subresource_cache; @@ -304,7 +305,7 @@ namespace rsx const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const texture_create_flags flags, std::pair, std::array>& 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, const u32 gcm_format, const texture_upload_context context, std::vector& subresource_layout, const rsx::texture_dimension_extended type, const bool swizzled, std::pair, std::array>& remap_vector) = 0; - virtual void enforce_surface_creation_type(section_storage_type& section, const texture_create_flags expected) = 0; + virtual void enforce_surface_creation_type(section_storage_type& section, const u32 gcm_format, const texture_create_flags expected) = 0; virtual void set_up_remap_vector(section_storage_type& section, std::pair, std::array>& remap_vector) = 0; virtual void insert_texture_barrier() = 0; virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, const u32 gcm_format, u16 size, std::array& sources) = 0; @@ -1689,9 +1690,6 @@ namespace rsx max_dst_width = cached_dest->get_width(); max_dst_height = cached_dest->get_height(); - - //Prep surface - enforce_surface_creation_type(*cached_dest, dst.swizzled ? rsx::texture_create_flags::swapped_native_component_order : rsx::texture_create_flags::native_component_order); } else if (overlapping_surfaces.size() > 0) { @@ -1837,6 +1835,19 @@ namespace rsx invalidate_range_impl_base(dst_address, dst.pitch * dst.height, true, false, false, true, std::forward(extras)...); } + 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; + + if (cached_dest) + { + //Prep surface + auto channel_order = src_is_render_target ? rsx::texture_create_flags::native_component_order : rsx::texture_create_flags::default_component_order; + enforce_surface_creation_type(*cached_dest, gcm_format, channel_order); + } + //Validate clipping region if ((dst.offset_x + dst.clip_x + dst.clip_width) > max_dst_width) dst.clip_x = 0; if ((dst.offset_y + dst.clip_y + dst.clip_height) > max_dst_height) dst.clip_y = 0; @@ -1855,18 +1866,12 @@ namespace rsx if (dest_texture == 0) { - 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; - lock.upgrade(); dest_texture = create_new_texture(cmd, dst.rsx_address, dst.pitch * dst_dimensions.height, dst_dimensions.width, dst_dimensions.height, 1, 1, gcm_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d, - dst.swizzled? rsx::texture_create_flags::swapped_native_component_order : rsx::texture_create_flags::native_component_order, + rsx::texture_create_flags::default_component_order, default_remap_vector)->get_raw_texture(); m_texture_memory_in_use += dst.pitch * dst_dimensions.height; diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index a0a06e28f0..e3cd12981b 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -14,6 +14,7 @@ namespace gl std::tuple get_format_type(u32 texture_format); GLenum wrap_mode(rsx::texture_wrap_mode wrap); float max_aniso(rsx::texture_max_anisotropy aniso); + std::array get_swizzle_remap(u32 texture_format); GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type); diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 830bab9c01..4a5d38df92 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -665,6 +665,38 @@ namespace gl return dst_id; } + + void apply_component_mapping_flags(const GLenum target, const u32 gcm_format, const rsx::texture_create_flags flags) + { + switch (flags) + { + case rsx::texture_create_flags::default_component_order: + { + auto remap = gl::get_swizzle_remap(gcm_format); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap[1]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap[2]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap[3]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap[0]); + break; + } + case rsx::texture_create_flags::native_component_order: + { + glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); + break; + } + case rsx::texture_create_flags::swapped_native_component_order: + { + glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_ALPHA); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_GREEN); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_BLUE); + break; + } + } + } protected: @@ -744,14 +776,8 @@ namespace gl break; } - if (flags == rsx::texture_create_flags::swapped_native_component_order) - { - glBindTexture(GL_TEXTURE_2D, vram_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE); - } + glBindTexture(GL_TEXTURE_2D, vram_texture); + apply_component_mapping_flags(GL_TEXTURE_2D, gcm_format, flags); auto& cached = create_texture(vram_texture, rsx_address, rsx_size, width, height, depth, mipmaps); cached.set_dirty(false); @@ -796,21 +822,16 @@ namespace gl return section; } - void enforce_surface_creation_type(cached_texture_section& section, const rsx::texture_create_flags flags) override + void enforce_surface_creation_type(cached_texture_section& section, const u32 gcm_format, const rsx::texture_create_flags flags) override { if (flags == section.get_view_flags()) return; - if (flags == rsx::texture_create_flags::swapped_native_component_order) - { - glBindTexture(GL_TEXTURE_2D, section.get_raw_texture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE); - } + glBindTexture(GL_TEXTURE_2D, section.get_raw_texture()); + apply_component_mapping_flags(GL_TEXTURE_2D, gcm_format, flags); section.set_view_flags(flags); + section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); } void set_up_remap_vector(cached_texture_section& section, std::pair, std::array>& remap_vector) override diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 21c99e414e..8e42222ae9 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -482,6 +482,33 @@ namespace vk return { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; } + + VkComponentMapping apply_component_mapping_flags(const u32 gcm_format, const rsx::texture_create_flags flags, const std::pair, std::array>& remap_vector) + { + VkComponentMapping mapping = {}; + switch (flags) + { + case rsx::texture_create_flags::default_component_order: + { + mapping = apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector); + break; + } + case rsx::texture_create_flags::native_component_order: + { + mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + break; + } + case rsx::texture_create_flags::swapped_native_component_order: + { + mapping = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; + break; + } + default: + break; + } + + return mapping; + } protected: @@ -698,22 +725,7 @@ namespace vk VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0); - switch (flags) - { - case rsx::texture_create_flags::default_component_order: - { - mapping = apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector); - break; - } - case rsx::texture_create_flags::native_component_order: - mapping = image->native_component_map; - break; - case rsx::texture_create_flags::swapped_native_component_order: - mapping = {VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A}; - break; - default: - fmt::throw_exception("Unknown create flags 0x%X", (u32)flags); - } + mapping = apply_component_mapping_flags(gcm_format, flags, remap_vector); vk::image_view *view = new vk::image_view(*m_device, image->value, image_view_type, vk_format, mapping, { (aspect_flags & ~VK_IMAGE_ASPECT_STENCIL_BIT), 0, mipmaps, 0, layer}); @@ -784,23 +796,15 @@ namespace vk return section; } - void enforce_surface_creation_type(cached_texture_section& section, const rsx::texture_create_flags expected_flags) override + void enforce_surface_creation_type(cached_texture_section& section, const u32 gcm_format, const rsx::texture_create_flags expected_flags) override { - VkComponentMapping mapping; + if (expected_flags == section.get_view_flags()) + return; + vk::image* image = section.get_raw_texture(); auto& view = section.get_view(); - switch (expected_flags) - { - case rsx::texture_create_flags::native_component_order: - mapping = image->native_component_map; - break; - case rsx::texture_create_flags::swapped_native_component_order: - mapping = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; - break; - default: - return; - } + VkComponentMapping mapping = apply_component_mapping_flags(gcm_format, expected_flags, default_remap_vector); if (mapping.a != view->info.components.a || mapping.b != view->info.components.b || @@ -815,19 +819,26 @@ namespace vk } section.set_view_flags(expected_flags); + section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); } void set_up_remap_vector(cached_texture_section& section, std::pair, std::array>& remap_vector) override { auto& view = section.get_view(); - auto& original_remap = section.get_view()->info.components; + 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); - vk::image_view *new_view = new vk::image_view(*m_device, view->info.image, view->info.viewType, view->info.format, - final_remap, view->info.subresourceRange); + if (final_remap.a != original_remap.a || + final_remap.r != original_remap.r || + final_remap.g != original_remap.g || + final_remap.b != original_remap.b) + { + vk::image_view *new_view = new vk::image_view(*m_device, view->info.image, view->info.viewType, view->info.format, + final_remap, view->info.subresourceRange); - view.reset(new_view); + view.reset(new_view); + } section.set_sampler_status(rsx::texture_sampler_status::status_ready); }