diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 382d762a52..f8bb47bc70 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -338,10 +338,6 @@ namespace std::vector result; size_t offset_in_src = 0; - // Always lower than width/height so fits in u16 - u16 texture_height_in_block = (height_in_texel + block_edge_in_texel - 1) / block_edge_in_texel; - u16 texture_width_in_block = (width_in_texel + block_edge_in_texel - 1) / block_edge_in_texel; - u8 border_size = border ? (padded_row ? 1 : 4) : 0; u32 src_pitch_in_block; u32 full_height_in_block; @@ -349,43 +345,58 @@ namespace for (unsigned layer = 0; layer < layer_count; layer++) { - u16 miplevel_height_in_block = texture_height_in_block, miplevel_width_in_block = texture_width_in_block; + u16 miplevel_width_in_texel = width_in_texel, miplevel_height_in_texel = height_in_texel; for (unsigned mip_level = 0; mip_level < mipmap_count; mip_level++) { - rsx_subresource_layout current_subresource_layout = {}; - // Since <= width/height, fits on 16 bits - current_subresource_layout.height_in_block = miplevel_height_in_block; - current_subresource_layout.width_in_block = miplevel_width_in_block; + result.push_back({}); + rsx_subresource_layout& current_subresource_layout = result.back(); + + current_subresource_layout.width_in_texel = miplevel_width_in_texel; + current_subresource_layout.height_in_texel = miplevel_height_in_texel; + current_subresource_layout.level = mip_level; + current_subresource_layout.layer = layer; current_subresource_layout.depth = depth; current_subresource_layout.border = border_size; + if constexpr (block_edge_in_texel == 1) + { + current_subresource_layout.width_in_block = miplevel_width_in_texel; + current_subresource_layout.height_in_block = miplevel_height_in_texel; + } + else + { + current_subresource_layout.width_in_block = rsx::aligned_div(miplevel_width_in_texel, block_edge_in_texel); + current_subresource_layout.height_in_block = rsx::aligned_div(miplevel_height_in_texel, block_edge_in_texel); + } + if (padded_row) { src_pitch_in_block = suggested_pitch_in_bytes / block_size_in_bytes; - full_height_in_block = miplevel_height_in_block + border_size + border_size; + full_height_in_block = current_subresource_layout.height_in_block + (border_size + border_size); } else if (!border) { - src_pitch_in_block = miplevel_width_in_block + border_size + border_size; - full_height_in_block = miplevel_height_in_block; + src_pitch_in_block = current_subresource_layout.width_in_block; + full_height_in_block = current_subresource_layout.height_in_block; } else { - src_pitch_in_block = rsx::next_pow2(miplevel_width_in_block + border_size + border_size); - full_height_in_block = rsx::next_pow2(miplevel_height_in_block + border_size + border_size); + src_pitch_in_block = rsx::next_pow2(current_subresource_layout.width_in_block + border_size + border_size); + full_height_in_block = rsx::next_pow2(current_subresource_layout.height_in_block + border_size + border_size); } slice_sz = src_pitch_in_block * block_size_in_bytes * full_height_in_block * depth; current_subresource_layout.pitch_in_block = src_pitch_in_block; current_subresource_layout.data = gsl::span(texture_data_pointer + offset_in_src, slice_sz); - result.push_back(current_subresource_layout); offset_in_src += slice_sz; - miplevel_height_in_block = std::max(miplevel_height_in_block / 2, 1); - miplevel_width_in_block = std::max(miplevel_width_in_block / 2, 1); + miplevel_width_in_texel = std::max(miplevel_width_in_texel / 2, 1); + miplevel_height_in_texel = std::max(miplevel_height_in_texel / 2, 1); } + offset_in_src = align(offset_in_src, 128); } + return result; } } diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index aeca9b0c86..0f59fe73d0 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -89,9 +89,13 @@ namespace rsx struct rsx_subresource_layout { gsl::span data; + u16 width_in_texel; + u16 height_in_texel; u16 width_in_block; u16 height_in_block; u16 depth; + u16 level; + u16 layer; u8 border; u8 reserved; u32 pitch_in_block; diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 988082522c..86a3f050a1 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2401,8 +2401,8 @@ namespace rsx std::vector subresource_layout; rsx_subresource_layout subres = {}; - subres.width_in_block = image_width; - subres.height_in_block = image_height; + subres.width_in_block = subres.width_in_texel = image_width; + subres.height_in_block = subres.height_in_texel = image_height; subres.pitch_in_block = full_width; subres.depth = 1; subres.data = { vm::_ptr(image_base), src.pitch * image_height }; @@ -2533,8 +2533,8 @@ namespace rsx const u16 pitch_in_block = dst.pitch / dst_bpp; std::vector subresource_layout; rsx_subresource_layout subres = {}; - subres.width_in_block = dst_dimensions.width; - subres.height_in_block = dst_dimensions.height; + subres.width_in_block = subres.width_in_texel = dst_dimensions.width; + subres.height_in_block = subres.height_in_texel = dst_dimensions.height; subres.pitch_in_block = pitch_in_block; subres.depth = 1; subres.data = { vm::get_super_ptr(dst.rsx_address), dst.pitch * dst_dimensions.height }; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 29a3d7e86b..58308b5927 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -241,8 +241,8 @@ namespace vk } rsx_subresource_layout subres{}; - subres.width_in_block = surface_width * samples_x; - subres.height_in_block = surface_height * samples_y; + subres.width_in_block = subres.width_in_texel = surface_width * samples_x; + subres.height_in_block = subres.height_in_texel = surface_height * samples_y; subres.pitch_in_block = rsx_pitch / get_bpp(); subres.depth = 1; subres.data = { (const gsl::byte*)vm::get_super_ptr(base_addr), s32(rsx_pitch * surface_height * samples_y) }; diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 94f827f953..0b74c792b8 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -542,7 +542,6 @@ namespace vk const std::vector& subresource_layout, int format, bool is_swizzled, u16 mipmap_count, VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align) { - u32 mipmap_level = 0; u32 block_in_pixel = get_format_block_size_in_texel(format); u8 block_size_in_bytes = get_format_block_size_in_bytes(format); @@ -591,13 +590,13 @@ namespace vk copy_regions.push_back({}); auto& copy_info = copy_regions.back(); copy_info.bufferOffset = offset_in_buffer; - copy_info.imageExtent.height = layout.height_in_block * block_in_pixel; - copy_info.imageExtent.width = std::min(layout.width_in_block, layout.pitch_in_block) * block_in_pixel; + copy_info.imageExtent.height = layout.height_in_texel; + copy_info.imageExtent.width = layout.width_in_texel; copy_info.imageExtent.depth = layout.depth; copy_info.imageSubresource.aspectMask = flags; copy_info.imageSubresource.layerCount = 1; - copy_info.imageSubresource.baseArrayLayer = mipmap_level / mipmap_count; - copy_info.imageSubresource.mipLevel = mipmap_level % mipmap_count; + copy_info.imageSubresource.baseArrayLayer = layout.layer; + copy_info.imageSubresource.mipLevel = layout.level; copy_info.bufferRowLength = block_in_pixel * row_pitch / block_size_in_bytes; if (opt.require_swap || dst_image->aspect() & VK_IMAGE_ASPECT_STENCIL_BIT) @@ -621,8 +620,6 @@ namespace vk scratch_offset += image_linear_size; verify("Out of scratch memory" HERE), (scratch_offset + image_linear_size) <= scratch_buf->size(); } - - mipmap_level++; } if (opt.require_swap || dst_image->aspect() & VK_IMAGE_ASPECT_STENCIL_BIT) diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 8e20f1666a..053fb22577 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -277,6 +277,13 @@ namespace rsx return ((value + alignment - 1) / alignment) * alignment; } + // General purpose aligned division, the result is rounded up not truncated + template + static inline T aligned_div(T value, U alignment) + { + return (value + alignment - 1) / alignment; + } + // Copy memory in inverse direction from source // Used to scale negatively x axis while transfering image data template