diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 1a65bbd089..54a7a89bb4 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -25,6 +25,12 @@ namespace rsx framebuffer_storage = 3 }; + enum texture_sampler_status + { + status_uninitialized = 0, + status_ready = 1 + }; + //Sampled image descriptor struct sampled_image_descriptor_base { @@ -52,6 +58,7 @@ namespace rsx rsx::texture_create_flags view_flags = rsx::texture_create_flags::default_component_order; rsx::texture_upload_context context = rsx::texture_upload_context::shader_read; rsx::texture_dimension_extended image_type = rsx::texture_dimension_extended::texture_dimension_2d; + rsx::texture_sampler_status sampler_status = rsx::texture_sampler_status::status_uninitialized; bool matches(const u32 rsx_address, const u32 rsx_size) { @@ -98,6 +105,11 @@ namespace rsx image_type = type; } + void set_sampler_status(const rsx::texture_sampler_status status) + { + sampler_status = status; + } + void set_gcm_format(u32 format) { gcm_format = format; @@ -132,6 +144,11 @@ namespace rsx { return gcm_format; } + + rsx::texture_sampler_status get_sampler_status() const + { + return sampler_status; + } }; template @@ -288,6 +305,7 @@ namespace rsx 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 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; @@ -795,6 +813,7 @@ namespace rsx region.protect(utils::protection::no); region.create(width, height, 1, 1, nullptr, image, pitch, false, std::forward(extras)...); region.set_context(texture_upload_context::framebuffer_storage); + region.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); region.set_image_type(rsx::texture_dimension_extended::texture_dimension_2d); update_cache_tag(); } @@ -1432,6 +1451,9 @@ namespace rsx if (cached_texture->get_image_type() == rsx::texture_dimension_extended::texture_dimension_1d) scale_y = 0.f; + if (cached_texture->get_sampler_status() != rsx::texture_sampler_status::status_ready) + set_up_remap_vector(*cached_texture, tex.decoded_remap()); + return{ cached_texture->get_raw_view(), cached_texture->get_context(), cached_texture->is_depth_texture(), scale_x, scale_y, cached_texture->get_image_type() }; } } @@ -1475,6 +1497,9 @@ namespace rsx break; } + if (surface->get_sampler_status() != rsx::texture_sampler_status::status_ready) + set_up_remap_vector(*surface, tex.decoded_remap()); + 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 }; diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 388e199178..0b53b01fd2 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -442,6 +442,41 @@ namespace gl } } + void apply_swizzle_remap(const GLenum target, const std::array& swizzle_remap, const std::pair, std::array>& decoded_remap) + { + //Remapping tables; format is A-R-G-B + //Remap input table. Contains channel index to read color from + const auto remap_inputs = decoded_remap.first; + + //Remap control table. Controls whether the remap value is used, or force either 0 or 1 + const auto remap_lookup = decoded_remap.second; + + GLenum remap_values[4]; + + for (u8 channel = 0; channel < 4; ++channel) + { + switch (remap_lookup[channel]) + { + default: + LOG_ERROR(RSX, "Unknown remap function 0x%X", remap_lookup[channel]); + case CELL_GCM_TEXTURE_REMAP_REMAP: + remap_values[channel] = swizzle_remap[remap_inputs[channel]]; + break; + case CELL_GCM_TEXTURE_REMAP_ZERO: + remap_values[channel] = GL_ZERO; + break; + case CELL_GCM_TEXTURE_REMAP_ONE: + remap_values[channel] = GL_ONE; + break; + } + } + + glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap_values[0]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap_values[1]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap_values[2]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap_values[3]); + } + void upload_texture(const GLuint id, const u32 texaddr, const u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type, std::vector& subresources_layout, std::pair, std::array>& decoded_remap, bool static_state) { @@ -453,7 +488,6 @@ namespace gl const std::array& glRemap = get_swizzle_remap(gcm_format); GLenum target; - GLenum remap_values[4]; switch (type) { @@ -496,35 +530,7 @@ namespace gl } else { - //Remapping tables; format is A-R-G-B - //Remap input table. Contains channel index to read color from - const auto remap_inputs = decoded_remap.first; - - //Remap control table. Controls whether the remap value is used, or force either 0 or 1 - const auto remap_lookup = decoded_remap.second; - - for (u8 channel = 0; channel < 4; ++channel) - { - switch (remap_lookup[channel]) - { - default: - LOG_ERROR(RSX, "Unknown remap function 0x%X", remap_lookup[channel]); - case CELL_GCM_TEXTURE_REMAP_REMAP: - remap_values[channel] = glRemap[remap_inputs[channel]]; - break; - case CELL_GCM_TEXTURE_REMAP_ZERO: - remap_values[channel] = GL_ZERO; - break; - case CELL_GCM_TEXTURE_REMAP_ONE: - remap_values[channel] = GL_ONE; - break; - } - } - - glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap_values[0]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap_values[1]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap_values[2]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap_values[3]); + apply_swizzle_remap(target, glRemap, decoded_remap); } //The rest of sampler state is now handled by sampler state objects diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index 335003298d..a0a06e28f0 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -28,6 +28,8 @@ namespace gl void upload_texture(const GLuint id, const u32 texaddr, const u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type, std::vector& subresources_layout, std::pair, std::array>& decoded_remap, bool static_state); + void apply_swizzle_remap(const GLenum target, const std::array& swizzle_remap, const std::pair, std::array>& decoded_remap); + class sampler_state { GLuint samplerHandle = 0; diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 66aeca7d30..830bab9c01 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -758,6 +758,7 @@ namespace gl cached.set_depth_flag(depth_flag); cached.set_view_flags(flags); cached.set_context(context); + cached.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); cached.set_image_type(type); //Its not necessary to lock blit dst textures as they are just reused as necessary @@ -778,8 +779,18 @@ namespace gl auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type, rsx::texture_create_flags::default_component_order, remap_vector); - //Swizzling is ignored for blit engine copy and emulated using remapping - bool input_swizzled = (context == rsx::texture_upload_context::blit_engine_src)? false : swizzled; + bool input_swizzled = swizzled; + if (context == rsx::texture_upload_context::blit_engine_src) + { + //Swizzling is ignored for blit engine copy and emulated using remapping + input_swizzled = false; + section->set_sampler_status(rsx::texture_sampler_status::status_uninitialized); + } + else + { + //Generic upload - sampler status will be set on upload + section->set_sampler_status(rsx::texture_sampler_status::status_ready); + } gl::upload_texture(section->get_raw_texture(), rsx_address, gcm_format, width, height, depth, mipmaps, input_swizzled, type, subresource_layout, remap_vector, false); return section; @@ -802,6 +813,19 @@ namespace gl section.set_view_flags(flags); } + void set_up_remap_vector(cached_texture_section& section, std::pair, std::array>& 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); + section.set_sampler_status(rsx::texture_sampler_status::status_ready); + } + void insert_texture_barrier() override { auto &caps = gl::get_driver_caps(); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index d6fa3d481f..21c99e414e 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -457,6 +457,31 @@ namespace vk m_texture_memory_in_use = 0; 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] }; + } protected: @@ -677,28 +702,7 @@ namespace vk { case rsx::texture_create_flags::default_component_order: { - auto native_mapping = vk::get_component_mapping(gcm_format); - 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] = native_mapping[remap_vector.first[channel]]; - break; - default: - LOG_ERROR(RSX, "Unknown remap lookup value %d", remap_vector.second[channel]); - } - } - - mapping = { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; + mapping = apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector); break; } case rsx::texture_create_flags::native_component_order: @@ -721,6 +725,7 @@ namespace vk region.create(width, height, section_depth, mipmaps, view, image, 0, true, gcm_format); region.set_dirty(false); region.set_context(context); + region.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); region.set_image_type(type); //Its not necessary to lock blit dst textures as they are just reused as necessary @@ -756,8 +761,18 @@ namespace vk vk::enter_uninterruptible(); - //Swizzling is ignored for blit engine copy and emulated using a swapped order image view - bool input_swizzled = (context == rsx::texture_upload_context::blit_engine_src) ? false : swizzled; + bool input_swizzled = swizzled; + if (context == rsx::texture_upload_context::blit_engine_src) + { + //Swizzling is ignored for blit engine copy and emulated using remapping + input_swizzled = false; + section->set_sampler_status(rsx::texture_sampler_status::status_uninitialized); + } + else + { + //Generic upload - sampler status will be set on upload + section->set_sampler_status(rsx::texture_sampler_status::status_ready); + } vk::copy_mipmaped_image_using_buffer(cmd, image->value, subresource_layout, gcm_format, input_swizzled, mipmaps, subres_range.aspectMask, *m_texture_upload_heap, m_texture_upload_buffer); @@ -802,6 +817,20 @@ namespace vk section.set_view_flags(expected_flags); } + 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; + 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); + + view.reset(new_view); + section.set_sampler_status(rsx::texture_sampler_status::status_ready); + } + void insert_texture_barrier() override {}