diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 859baca0b0..21eac8bf78 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -58,7 +58,6 @@ struct copy_unmodified_block_vtc template static void copy_mipmap_level(gsl::span dst, gsl::span src, u16 width_in_block, u16 row_count, u16 depth, u32 dst_pitch_in_block, u32 src_pitch_in_block) { - static_assert(sizeof(T) == sizeof(U), "Type size doesn't match."); u32 row_element_count = width_in_block * row_count; u32 dst_offset = 0; @@ -66,19 +65,30 @@ struct copy_unmodified_block_vtc const u32 vtc_tile_row_count = 4; // Undo Nvidia VTC tiling - place each 2D texture slice back to back in linear memory - for (int d = 0; d < depth; d++) { - - // copy one slice of the 3d texture - for (u32 i = 0; i < row_element_count; i += 1) { + // + // More info: + // https://www.khronos.org/registry/OpenGL/extensions/NV/NV_texture_compression_vtc.txt + // + // Note that the memory is tiled 4 planes at a time in the depth direction. + // e.g. d0, d1, d2, d3 is tiled as a group then d4, d5, d6, d7 + // + for (int d = 0; d < depth; d++) + { + // Copy one slice of the 3d texture + for (u32 i = 0; i < row_element_count; i += 1) + { copy(dst.subspan(dst_offset + i, 1), src.subspan(src_offset + i * vtc_tile_row_count, 1)); } dst_offset += row_element_count; - if (d && ((d & (vtc_tile_row_count - 1)) == 0)) { + // Last plane in the group of 4? + if (d && ((d & (vtc_tile_row_count - 1)) == 0)) + { src_offset += row_element_count; } - else { + else + { src_offset += 1; } } @@ -302,28 +312,31 @@ void upload_texture_subresource(gsl::span dst_buffer, const rsx_subre break; case CELL_GCM_TEXTURE_COMPRESSED_DXT1: - if (depth > 1 && !vtc_support) { - // PS3 uses VTC memory layout for compressed 3d texture - // Remove the VTC tiling to support ATI and Vulkan + if (depth > 1 && !vtc_support) + { + // PS3 uses the Nvidia VTC memory layout for compressed 3D textures. + // This is only supported using Nvidia OpenGL. + // Remove the VTC tiling to support ATI and Vulkan. copy_unmodified_block_vtc::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); } - else { + else + { copy_unmodified_block::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); } break; case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT45: - if (depth > 1 && !vtc_support) { - // PS3 uses VTC memory layout for compressed 3d texture + if (depth > 1 && !vtc_support) + { + // PS3 uses the Nvidia VTC memory layout for compressed 3D textures. // This is only supported using Nvidia OpenGL. - // Remove the VTC tiling to support ATI and Vulkan + // Remove the VTC tiling to support ATI and Vulkan. copy_unmodified_block_vtc::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); - } - else { + else + { copy_unmodified_block::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); - } break;