1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

macOS: Implement texture converter for Metal (2) (#11289)

* macOS: Implement texture converter for Metal (2)

* Fix texture conversion formatting
This commit is contained in:
nastys 2021-12-24 13:46:37 +01:00 committed by GitHub
parent 28d7af313b
commit a0040e6fb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 195 additions and 18 deletions

View File

@ -24,12 +24,128 @@ namespace utils
namespace
{
#ifndef __APPLE__
u16 convert_rgb655_to_rgb565(const u16 bits)
{
// g6 = g5
// r5 = (((bits & 0xFC00) >> 1) & 0xFC00) << 1 is equivalent to truncating the least significant bit
return (bits & 0xF81F) | (bits & 0x3E0) << 1;
}
#else
u32 convert_rgb565_to_bgra8(const u16 bits)
{
const u8 r5 = ((bits >> 11) & 0x1F);
const u8 g6 = ((bits >> 5) & 0x3F);
const u8 b5 = (bits & 0x1F);
const u8 b8 = ((b5 * 527) + 23) >> 6;
const u8 g8 = ((g6 * 259) + 33) >> 6;
const u8 r8 = ((r5 * 527) + 23) >> 6;
const u8 a8 = 255;
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
u32 convert_argb4_to_bgra8(const u16 bits)
{
const u8 b8 = (bits & 0xF0);
const u8 g8 = ((bits >> 4) & 0xF0);
const u8 r8 = ((bits >> 8) & 0xF0);
const u8 a8 = ((bits << 4) & 0xF0);
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
u32 convert_a1rgb5_to_bgra8(const u16 bits)
{
const u8 a1 = ((bits >> 11) & 0x80);
const u8 r5 = ((bits >> 10) & 0x1F);
const u8 g5 = ((bits >> 5) & 0x1F);
const u8 b5 = (bits & 0x1F);
const u8 b8 = ((b5 * 527) + 23) >> 6;
const u8 g8 = ((g5 * 527) + 23) >> 6;
const u8 r8 = ((r5 * 527) + 23) >> 6;
const u8 a8 = a1;
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
u32 convert_rgb5a1_to_bgra8(const u16 bits)
{
const u8 r5 = ((bits >> 11) & 0x1F);
const u8 g5 = ((bits >> 6) & 0x1F);
const u8 b5 = ((bits >> 1) & 0x1F);
const u8 a1 = (bits & 0x80);
const u8 b8 = ((b5 * 527) + 23) >> 6;
const u8 g8 = ((g5 * 527) + 23) >> 6;
const u8 r8 = ((r5 * 527) + 23) >> 6;
const u8 a8 = a1;
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
u32 convert_rgb655_to_bgra8(const u16 bits)
{
const u8 r6 = ((bits >> 10) & 0x3F);
const u8 g5 = ((bits >> 5) & 0x1F);
const u8 b5 = ((bits) & 0x1F);
const u8 b8 = ((b5 * 527) + 23) >> 6;
const u8 g8 = ((g5 * 527) + 23) >> 6;
const u8 r8 = ((r6 * 259) + 33) >> 6;
const u8 a8 = 1;
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
u32 convert_d1rgb5_to_bgra8(const u16 bits)
{
const u8 r5 = ((bits >> 10) & 0x1F);
const u8 g5 = ((bits >> 5) & 0x1F);
const u8 b5 = (bits & 0x1F);
const u8 b8 = ((b5 * 527) + 23) >> 6;
const u8 g8 = ((g5 * 527) + 23) >> 6;
const u8 r8 = ((r5 * 527) + 23) >> 6;
const u8 a8 = 1;
return b8 | (g8 << 8) | (r8 << 16) | (a8 << 24);
}
struct convert_16_block_32
{
template<typename T>
static void copy_mipmap_level(std::span<u32> dst, std::span<const T> src, u16 width_in_block, u16 row_count, u16 depth, u8 border, u32 dst_pitch_in_block, u32 src_pitch_in_block, u32 (*converter)(const u16))
{
static_assert(sizeof(T) == 2, "Type size doesn't match.");
u32 src_offset = 0, dst_offset = 0;
const u32 v_porch = src_pitch_in_block * border;
for (int layer = 0; layer < depth; ++layer)
{
// Front
src_offset += v_porch;
for (u32 row = 0; row < row_count; ++row)
{
for (int col = 0; col < width_in_block; ++col)
{
dst[dst_offset + col] = converter(src[src_offset + col + border]);
}
src_offset += src_pitch_in_block;
dst_offset += dst_pitch_in_block;
}
// Back
src_offset += v_porch;
}
}
};
#endif
struct copy_unmodified_block
{
@ -692,6 +808,7 @@ namespace rsx
break;
}
#ifndef __APPLE__
case CELL_GCM_TEXTURE_R6G5B5:
{
if (is_swizzled)
@ -701,16 +818,49 @@ namespace rsx
break;
}
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
// TODO: Test if the HILO compressed formats support swizzling (other compressed_* formats ignore this option)
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // Untested
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_R5G6B5:
#else
// convert the following formats to B8G8R8A8_UNORM, because they are not supported by Metal
case CELL_GCM_TEXTURE_R6G5B5:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_rgb655_to_bgra8);
break;
}
case CELL_GCM_TEXTURE_D1R5G5B5:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_d1rgb5_to_bgra8);
break;
}
case CELL_GCM_TEXTURE_A1R5G5B5:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_a1rgb5_to_bgra8);
break;
}
case CELL_GCM_TEXTURE_A4R4G4B4:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_argb4_to_bgra8);
break;
}
case CELL_GCM_TEXTURE_R5G5B5A1:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_rgb5a1_to_bgra8);
break;
}
case CELL_GCM_TEXTURE_R5G6B5:
{
convert_16_block_32::copy_mipmap_level(utils::bless<u32>(dst_buffer), utils::bless<const be_t<u16>>(src_layout.data), w, h, depth, src_layout.border, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block, &convert_rgb565_to_bgra8);
break;
}
#endif
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
// TODO: Test if the HILO compressed formats support swizzling (other compressed_* formats ignore this option)
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // Untested
case CELL_GCM_TEXTURE_G8B8:
{
word_size = 2;

View File

@ -205,16 +205,28 @@ namespace vk
{
switch (format)
{
case CELL_GCM_TEXTURE_B8: return VK_FORMAT_R8_UNORM;
#ifndef __APPLE__
case CELL_GCM_TEXTURE_R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16;
case CELL_GCM_TEXTURE_R6G5B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // Expand, discard high bit?
case CELL_GCM_TEXTURE_R5G5B5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
case CELL_GCM_TEXTURE_D1R5G5B5: return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
case CELL_GCM_TEXTURE_A1R5G5B5: return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
case CELL_GCM_TEXTURE_A4R4G4B4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
case CELL_GCM_TEXTURE_R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16;
#else
// assign B8G8R8A8_UNORM to formats that are not supported by Metal
case CELL_GCM_TEXTURE_R6G5B5: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_R5G6B5: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_R5G5B5A1: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_D1R5G5B5: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_A1R5G5B5: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_A4R4G4B4: return VK_FORMAT_B8G8R8A8_UNORM;
#endif
case CELL_GCM_TEXTURE_B8: return VK_FORMAT_R8_UNORM;
case CELL_GCM_TEXTURE_A8R8G8B8: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return VK_FORMAT_BC2_UNORM_BLOCK;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return VK_FORMAT_BC3_UNORM_BLOCK;
case CELL_GCM_TEXTURE_G8B8: return VK_FORMAT_R8G8_UNORM;
case CELL_GCM_TEXTURE_R6G5B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // Expand, discard high bit?
case CELL_GCM_TEXTURE_DEPTH24_D8: return support.d24_unorm_s8? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT;
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
case CELL_GCM_TEXTURE_DEPTH16: return VK_FORMAT_D16_UNORM;
@ -222,11 +234,9 @@ namespace vk
case CELL_GCM_TEXTURE_X16: return VK_FORMAT_R16_UNORM;
case CELL_GCM_TEXTURE_Y16_X16: return VK_FORMAT_R16G16_UNORM;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return VK_FORMAT_R16G16_SFLOAT;
case CELL_GCM_TEXTURE_R5G5B5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return VK_FORMAT_R16G16B16A16_SFLOAT;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return VK_FORMAT_R32G32B32A32_SFLOAT;
case CELL_GCM_TEXTURE_X32_FLOAT: return VK_FORMAT_R32_SFLOAT;
case CELL_GCM_TEXTURE_D1R5G5B5: return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
case CELL_GCM_TEXTURE_D8R8G8B8: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return VK_FORMAT_R8G8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return VK_FORMAT_R8G8_SNORM;

View File

@ -32,9 +32,26 @@ namespace vk
switch (color_format)
{
#ifndef __APPLE__
case rsx::surface_color_format::r5g6b5:
return std::make_pair(VK_FORMAT_R5G6B5_UNORM_PACK16, vk::default_component_map);
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
return std::make_pair(VK_FORMAT_A1R5G5B5_UNORM_PACK16, o_rgb);
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
return std::make_pair(VK_FORMAT_A1R5G5B5_UNORM_PACK16, z_rgb);
#else
// assign B8G8R8A8_UNORM to formats that are not supported by Metal
case rsx::surface_color_format::r5g6b5:
return std::make_pair(VK_FORMAT_B8G8R8A8_UNORM, vk::default_component_map);
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
return std::make_pair(VK_FORMAT_B8G8R8A8_UNORM, o_rgb);
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
return std::make_pair(VK_FORMAT_B8G8R8A8_UNORM, z_rgb);
#endif
case rsx::surface_color_format::a8r8g8b8:
return std::make_pair(VK_FORMAT_B8G8R8A8_UNORM, vk::default_component_map);
@ -59,12 +76,6 @@ namespace vk
case rsx::surface_color_format::w32z32y32x32:
return std::make_pair(VK_FORMAT_R32G32B32A32_SFLOAT, vk::default_component_map);
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
return std::make_pair(VK_FORMAT_A1R5G5B5_UNORM_PACK16, o_rgb);
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
return std::make_pair(VK_FORMAT_A1R5G5B5_UNORM_PACK16, z_rgb);
case rsx::surface_color_format::b8:
{
const VkComponentMapping no_alpha = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE };

View File

@ -999,14 +999,20 @@ namespace vk
//TODO
warn_once("Format incompatibility detected, reporting failure to force data copy (VK_FORMAT=0x%X, GCM_FORMAT=0x%X)", static_cast<u32>(vk_format), gcm_format);
return false;
#ifndef __APPLE__
case CELL_GCM_TEXTURE_R5G6B5:
return (vk_format == VK_FORMAT_R5G6B5_UNORM_PACK16);
#else
// R5G6B5 is not supported by Metal
case CELL_GCM_TEXTURE_R5G6B5:
return (vk_format == VK_FORMAT_B8G8R8A8_UNORM);
#endif
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return (vk_format == VK_FORMAT_R16G16B16A16_SFLOAT);
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return (vk_format == VK_FORMAT_R32G32B32A32_SFLOAT);
case CELL_GCM_TEXTURE_X32_FLOAT:
return (vk_format == VK_FORMAT_R32_SFLOAT);
case CELL_GCM_TEXTURE_R5G6B5:
return (vk_format == VK_FORMAT_R5G6B5_UNORM_PACK16);
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
return (vk_format == VK_FORMAT_B8G8R8A8_UNORM || vk_format == VK_FORMAT_D24_UNORM_S8_UINT || vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT);