From a95a44cf660ca804c8688aa8cb663038efaddfb3 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 18 Dec 2018 20:04:03 +0300 Subject: [PATCH] rsx: Strictness cleanups - Also account for variable pitch textures (swizzled scan) --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 42 ++++++++++++++++++++------- rpcs3/Emu/RSX/Common/texture_cache.h | 2 +- rpcs3/Emu/RSX/GL/GLTextureCache.h | 20 ++++++------- rpcs3/Emu/RSX/VK/VKTextureCache.h | 17 +++++------ 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index dfee0dee72..784afd25e2 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -587,22 +587,44 @@ size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_ static size_t get_texture_size(u32 format, u16 width, u16 height, u16 depth, u32 pitch, u16 mipmaps, u16 layers) { const auto gcm_format = format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + const bool packed = !(format & CELL_GCM_TEXTURE_LN); const auto texel_rows_per_line = get_format_texel_rows_per_line(gcm_format); - if (pitch == 0) - { - pitch = get_format_packed_pitch(gcm_format, width); - } + verify(HERE), packed || pitch; u32 size = 0; - for (u32 layer = 0; layer < layers; ++layer) + if (!packed) { - u32 mip_height = (height + texel_rows_per_line - 1) / texel_rows_per_line; // Convert texels to blocks - - for (u32 mipmap = 0; mipmap < mipmaps; ++mipmap) + // Constant pitch layout, simple scanning + const u32 internal_height = (height + texel_rows_per_line - 1) / texel_rows_per_line; // Convert texels to blocks + for (u32 layer = 0; layer < layers; ++layer) { - size += pitch * mip_height; - mip_height = std::max(mip_height / 2u, 1u); + u32 mip_height = internal_height; + for (u32 mipmap = 0; mipmap < mipmaps && mip_height > 0; ++mipmap) + { + size += pitch * mip_height * depth; + mip_height = std::max(mip_height / 2u, 1u); + } + } + } + else + { + // Variable pitch per mipmap level + const auto texels_per_block = get_format_block_size_in_texel(gcm_format); + const auto bytes_per_block = get_format_block_size_in_bytes(gcm_format); + + const u32 internal_height = (height + texel_rows_per_line - 1) / texel_rows_per_line; // Convert texels to blocks + const u32 internal_width = (width + texels_per_block - 1) / texels_per_block; // Convert texels to blocks + for (u32 layer = 0; layer < layers; ++layer) + { + u32 mip_height = internal_height; + u32 mip_width = internal_width; + for (u32 mipmap = 0; mipmap < mipmaps && mip_height > 0; ++mipmap) + { + size += (mip_width * bytes_per_block * mip_height * depth); + mip_height = std::max(mip_height / 2u, 1u); + mip_width = std::max(mip_width / 2u, 1u); + } } } diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 52d229a06b..7f12932f0a 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -286,7 +286,7 @@ namespace rsx */ 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&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format, + virtual section_storage_type* create_new_texture(commandbuffer_type&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags) = 0; virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, const address_range &rsx_range, 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, bool swizzled) = 0; diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 11398610df..9d5bfa0962 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -182,11 +182,9 @@ namespace gl synchronized = false; sync_timestamp = 0ull; - if (rsx_pitch > 0) - this->rsx_pitch = rsx_pitch; - else - this->rsx_pitch = get_section_size() / height; + verify(HERE), rsx_pitch; + this->rsx_pitch = rsx_pitch; this->width = w; this->height = h; this->real_pitch = 0; @@ -199,10 +197,12 @@ namespace gl baseclass::on_section_resources_created(); } - void create_read_only(gl::viewable_image* image, u32 width, u32 height, u32 depth, u32 mipmaps) + void create_read_only(gl::viewable_image* image, u32 width, u32 height, u32 depth, u32 mipmaps, u16 pitch) { ASSERT(!exists() || !is_managed() || vram_texture == image); + verify(HERE), pitch; + //Only to be used for ro memory, we dont care about most members, just dimensions and the vram texture handle this->width = width; this->height = height; @@ -212,7 +212,7 @@ namespace gl managed_texture.reset(image); vram_texture = image; - rsx_pitch = 0; + rsx_pitch = pitch; real_pitch = 0; // Notify baseclass @@ -818,8 +818,8 @@ namespace gl dst->image()->id(), GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1); } - cached_texture_section* create_new_texture(void*&, const utils::address_range &rsx_range, 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) override + cached_texture_section* create_new_texture(void*&, const utils::address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, + u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags) override { auto image = gl::create_texture(gcm_format, width, height, depth, mipmaps, type); @@ -836,7 +836,7 @@ namespace gl cached.set_image_type(type); cached.set_gcm_format(gcm_format); - cached.create_read_only(image, width, height, depth, mipmaps); + cached.create_read_only(image, width, height, depth, mipmaps, pitch); cached.set_dirty(false); if (context != rsx::texture_upload_context::blit_engine_dst) @@ -890,7 +890,7 @@ namespace gl rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool input_swizzled) override { void* unused = nullptr; - auto section = create_new_texture(unused, rsx_range, width, height, depth, mipmaps, gcm_format, context, type, + auto section = create_new_texture(unused, rsx_range, width, height, depth, mipmaps, pitch, gcm_format, context, type, rsx::texture_create_flags::default_component_order); gl::upload_texture(section->get_raw_texture()->id(), gcm_format, width, height, depth, mipmaps, diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 903d0a238f..4638152315 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -50,10 +50,13 @@ namespace vk ASSERT(!exists() || !is_managed() || vram_texture == new_texture); vram_texture = new_texture; + verify(HERE), rsx_pitch; + width = w; height = h; this->depth = depth; this->mipmaps = mipmaps; + this->rsx_pitch = rsx_pitch; this->gcm_format = gcm_format; this->pack_unpack_swap_bytes = pack_swap_bytes; @@ -63,12 +66,6 @@ namespace vk managed_texture.reset(vram_texture); } - //TODO: Properly compute these values - if (rsx_pitch > 0) - this->rsx_pitch = rsx_pitch; - else - this->rsx_pitch = get_section_size() / height; - //Even if we are managing the same vram section, we cannot guarantee contents are static //The create method is only invoked when a new managed session is required synchronized = false; @@ -770,8 +767,8 @@ namespace vk vk::change_image_layout(cmd, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range); } - cached_texture_section* create_new_texture(vk::command_buffer& cmd, const utils::address_range &rsx_range, 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) override + cached_texture_section* create_new_texture(vk::command_buffer& cmd, const utils::address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, + u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags) override { const u16 section_depth = depth; const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap; @@ -849,7 +846,7 @@ namespace vk region.set_gcm_format(gcm_format); region.set_image_type(type); - region.create(width, height, section_depth, mipmaps, image, 0, true, gcm_format); + region.create(width, height, section_depth, mipmaps, image, pitch, true, gcm_format); region.set_dirty(false); //Its not necessary to lock blit dst textures as they are just reused as necessary @@ -873,7 +870,7 @@ namespace vk cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range& rsx_range, 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, bool swizzled) override { - auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, gcm_format, context, type, + auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, pitch, gcm_format, context, type, rsx::texture_create_flags::default_component_order); auto image = section->get_raw_texture();