Merge pull request #1653 from tambry/cloud

HLE: cellPngDec fixes, Common/DX12/Vulkan: texture formats improved
This commit is contained in:
vlj 2016-04-07 21:31:54 +02:00
commit 960f4ceefc
10 changed files with 346 additions and 234 deletions

View File

@ -616,6 +616,8 @@ std::string FragmentProgramDecompiler::Decompile()
case RSX_FP_OPCODE_KIL: SetDst("discard", false); break; case RSX_FP_OPCODE_KIL: SetDst("discard", false); break;
default: default:
int prev_force_unit = forced_unit;
if (forced_unit == FORCE_NONE) if (forced_unit == FORCE_NONE)
{ {
if (SIP()) break; if (SIP()) break;
@ -634,7 +636,7 @@ std::string FragmentProgramDecompiler::Decompile()
if (handle_scb(opcode)) break; if (handle_scb(opcode)) break;
} }
LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, forced_unit); LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, prev_force_unit);
break; break;
} }

View File

@ -150,17 +150,30 @@ std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &
bool is_swizzled = !(texture.format() & CELL_GCM_TEXTURE_LN); bool is_swizzled = !(texture.format() & CELL_GCM_TEXTURE_LN);
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_D8R8G8B8: case CELL_GCM_TEXTURE_B8:
case CELL_GCM_TEXTURE_A8R8G8B8: return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // Untested
case CELL_GCM_TEXTURE_D1R5G5B5: case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5: case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_R5G6B5: case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_G8B8: case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_X16:
return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_DEPTH24_D8: // Untested
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // Untested
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
@ -168,10 +181,8 @@ std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
case CELL_GCM_TEXTURE_B8:
return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled);
} }
throw EXCEPTION("Wrong format %d", format); throw EXCEPTION("Wrong format 0x%x", format);
} }
void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of) void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of)
@ -181,43 +192,69 @@ void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subre
u16 depth = src_layout.depth; u16 depth = src_layout.depth;
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
if (is_swizzled)
copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u32>(dst_buffer), gsl::as_span<const u32>(src_layout.data), w, h, depth, get_row_pitch_in_block<u32>(w, dst_row_pitch_multiple_of));
else
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u32>(dst_buffer), gsl::as_span<const u32>(src_layout.data), w, h, depth, get_row_pitch_in_block<u32>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_G8B8:
if (is_swizzled)
copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u16>(dst_buffer), gsl::as_span<const be_t<u16>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u16>(w, dst_row_pitch_multiple_of));
else
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u16>(dst_buffer), gsl::as_span<const be_t<u16>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u16>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u64>(dst_buffer), gsl::as_span<const be_t<u64>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u64>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u64>(dst_buffer), gsl::as_span<const u64>(src_layout.data), w, h, depth, get_row_pitch_in_block<u64>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u128>(dst_buffer), gsl::as_span<const u128>(src_layout.data), w, h, depth, get_row_pitch_in_block<u128>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_B8: case CELL_GCM_TEXTURE_B8:
{
if (is_swizzled) if (is_swizzled)
copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u8>(dst_buffer), gsl::as_span<const u8>(src_layout.data), w, h, depth, get_row_pitch_in_block<u8>(w, dst_row_pitch_multiple_of)); copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u8>(dst_buffer), gsl::as_span<const u8>(src_layout.data), w, h, depth, get_row_pitch_in_block<u8>(w, dst_row_pitch_multiple_of));
else else
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u8>(dst_buffer), gsl::as_span<const u8>(src_layout.data), w, h, depth, get_row_pitch_in_block<u8>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); copy_unmodified_block::copy_mipmap_level(as_span_workaround<u8>(dst_buffer), gsl::as_span<const u8>(src_layout.data), w, h, depth, get_row_pitch_in_block<u8>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break; break;
}
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
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:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_X16:
{
if (is_swizzled)
copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u16>(dst_buffer), gsl::as_span<const be_t<u16>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u16>(w, dst_row_pitch_multiple_of));
else
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u16>(dst_buffer), gsl::as_span<const be_t<u16>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u16>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
}
case CELL_GCM_TEXTURE_DEPTH24_D8: // Untested
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // Untested
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
{
if (is_swizzled)
copy_unmodified_block_swizzled::copy_mipmap_level(as_span_workaround<u32>(dst_buffer), gsl::as_span<const u32>(src_layout.data), w, h, depth, get_row_pitch_in_block<u32>(w, dst_row_pitch_multiple_of));
else
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u32>(dst_buffer), gsl::as_span<const u32>(src_layout.data), w, h, depth, get_row_pitch_in_block<u32>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
}
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u32>(dst_buffer), gsl::as_span<const be_t<u32>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u32>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u64>(dst_buffer), gsl::as_span<const be_t<u64>>(src_layout.data), w, h, depth, get_row_pitch_in_block<u64>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u64>(dst_buffer), gsl::as_span<const u64>(src_layout.data), w, h, depth, get_row_pitch_in_block<u64>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
copy_unmodified_block::copy_mipmap_level(as_span_workaround<u128>(dst_buffer), gsl::as_span<const u128>(src_layout.data), w, h, depth, get_row_pitch_in_block<u128>(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes);
break;
default: default:
throw EXCEPTION("Wrong format %d", format); throw EXCEPTION("Wrong format 0x%x", format);
} }
} }
@ -230,37 +267,37 @@ u8 get_format_block_size_in_bytes(int format)
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_B8: return 1; case CELL_GCM_TEXTURE_B8: return 1;
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_A1R5G5B5: case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5: return 2;
case CELL_GCM_TEXTURE_A8R8G8B8: return 4;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return 8;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return 16;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return 16;
case CELL_GCM_TEXTURE_G8B8: return 2;
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return 4;
case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X16: return 2;
case CELL_GCM_TEXTURE_Y16_X16: return 4;
case CELL_GCM_TEXTURE_R5G5B5A1: return 2;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return 8;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return 16;
case CELL_GCM_TEXTURE_X32_FLOAT: return 4;
case CELL_GCM_TEXTURE_D1R5G5B5: return 2;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 4;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 2;
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 4;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return 8;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return 16;
default: default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format); LOG_ERROR(RSX, "Unimplemented block size in bytes for texture format: 0x%x", format);
return 0; return 1;
} }
} }
@ -269,37 +306,37 @@ u8 get_format_block_size_in_texel(int format)
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_B8: case CELL_GCM_TEXTURE_B8:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5: case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5: case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_A8R8G8B8: return 1; case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return 4;
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R6G5B5: case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X16: case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_Y16_X16: case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_R5G5B5A1: case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
case CELL_GCM_TEXTURE_X32_FLOAT: case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_D8R8G8B8: return 1;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 2;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 1;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 2;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return 4;
default: default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format); LOG_ERROR(RSX, "Unimplemented block size in texels for texture format: 0x%x", format);
return 0; return 1;
} }
} }
@ -337,62 +374,65 @@ size_t get_texture_size(const rsx::texture &texture)
// TODO: Take mipmaps into account // TODO: Take mipmaps into account
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format);
return 0;
case CELL_GCM_TEXTURE_B8: case CELL_GCM_TEXTURE_B8:
return w * h; return w * h;
case CELL_GCM_TEXTURE_G8B8:
return w * h * 2;
case CELL_GCM_TEXTURE_R5G5B5A1:
return w * h * 4;
case CELL_GCM_TEXTURE_D8R8G8B8:
return w * h * 4;
case CELL_GCM_TEXTURE_A8R8G8B8:
return w * h * 4;
case CELL_GCM_TEXTURE_D1R5G5B5:
return w * h * 2;
case CELL_GCM_TEXTURE_A1R5G5B5: case CELL_GCM_TEXTURE_A1R5G5B5:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A4R4G4B4:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_R6G5B5:
return w * h * 2;
case CELL_GCM_TEXTURE_R5G6B5: case CELL_GCM_TEXTURE_R5G6B5:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_A8R8G8B8:
return w * h * 4;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
return w * h / 6; return w * h / 6;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
return w * h / 4; return w * h / 4;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
return w * h / 4; return w * h / 4;
case CELL_GCM_TEXTURE_G8B8: case CELL_GCM_TEXTURE_DEPTH16:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_R6G5B5: case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH24_D8:
return w * h * 4; return w * h * 4;
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
return w * h * 4; return w * h * 4;
case CELL_GCM_TEXTURE_DEPTH16:
return w * h * 2;
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
return w * h * 2;
case CELL_GCM_TEXTURE_X16: case CELL_GCM_TEXTURE_X16:
return w * h * 2; return w * h * 2;
case CELL_GCM_TEXTURE_Y16_X16: case CELL_GCM_TEXTURE_Y16_X16:
return w * h * 4; return w * h * 4;
case CELL_GCM_TEXTURE_R5G5B5A1: case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return w * h * 2; return w * h * 4;
case CELL_GCM_TEXTURE_X32_FLOAT:
return w * h * 4;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return w * h * 8; return w * h * 8;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return w * h * 16; return w * h * 16;
case CELL_GCM_TEXTURE_X32_FLOAT:
return w * h * 4;
case CELL_GCM_TEXTURE_D1R5G5B5:
return w * h * 2;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return w * h * 4;
case CELL_GCM_TEXTURE_D8R8G8B8:
return w * h * 4;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
return w * h * 4; return w * h * 4;
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return w * h * 4; return w * h * 4;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
return w * h;
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
return w * h;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return w * h * 2;
default:
LOG_ERROR(RSX, "Unimplemented texture size for texture format: 0x%x", format);
return 0;
} }
} }

View File

@ -147,26 +147,26 @@ DXGI_FORMAT get_texture_format(u8 format)
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return DXGI_FORMAT_BC2_UNORM; case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return DXGI_FORMAT_BC2_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return DXGI_FORMAT_BC3_UNORM; case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return DXGI_FORMAT_BC3_UNORM;
case CELL_GCM_TEXTURE_G8B8: return DXGI_FORMAT_G8R8_G8B8_UNORM; case CELL_GCM_TEXTURE_G8B8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
case CELL_GCM_TEXTURE_R6G5B5: /*Not native*/ return DXGI_FORMAT_R8G8B8A8_UNORM; case CELL_GCM_TEXTURE_R6G5B5: return DXGI_FORMAT_B5G6R5_UNORM;
case CELL_GCM_TEXTURE_DEPTH24_D8: return DXGI_FORMAT_R32_UINT; case CELL_GCM_TEXTURE_DEPTH24_D8: return DXGI_FORMAT_R32_UINT; // Untested
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return DXGI_FORMAT_R32_FLOAT; case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return DXGI_FORMAT_R32_FLOAT; // Untested
case CELL_GCM_TEXTURE_DEPTH16: return DXGI_FORMAT_R16_UNORM; case CELL_GCM_TEXTURE_DEPTH16: return DXGI_FORMAT_R16_UINT; // Untested
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return DXGI_FORMAT_R16_FLOAT; case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return DXGI_FORMAT_R16_FLOAT; // Untested
case CELL_GCM_TEXTURE_X16: return DXGI_FORMAT_R16_UNORM; case CELL_GCM_TEXTURE_X16: return DXGI_FORMAT_R16_UNORM;
case CELL_GCM_TEXTURE_Y16_X16: return DXGI_FORMAT_R16G16_UNORM; case CELL_GCM_TEXTURE_Y16_X16: return DXGI_FORMAT_R16G16_UNORM;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT;
case CELL_GCM_TEXTURE_X32_FLOAT: return DXGI_FORMAT_R32_FLOAT;
case CELL_GCM_TEXTURE_R5G5B5A1: return DXGI_FORMAT_B5G5R5A1_UNORM; case CELL_GCM_TEXTURE_R5G5B5A1: return DXGI_FORMAT_B5G5R5A1_UNORM;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case CELL_GCM_TEXTURE_X32_FLOAT: return DXGI_FORMAT_R32_FLOAT;
case CELL_GCM_TEXTURE_D1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM; case CELL_GCM_TEXTURE_D1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM;
case CELL_GCM_TEXTURE_D8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM; case CELL_GCM_TEXTURE_D8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return DXGI_FORMAT_G8R8_G8B8_UNORM; case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return DXGI_FORMAT_R8G8_B8G8_UNORM; case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return DXGI_FORMAT_R8G8_B8G8_UNORM;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return DXGI_FORMAT_R8G8_SNORM;
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return DXGI_FORMAT_R8G8_B8G8_UNORM;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
break; break;
} }
throw EXCEPTION("Invalid or unsupported texture format (0x%x)", format); throw EXCEPTION("Invalid or unsupported texture format (0x%x)", format);

View File

@ -251,13 +251,30 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
default: default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format); LOG_ERROR(RSX, "Unimplemented mapping for texture format: 0x%x", format);
break; break;
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
break;
case CELL_GCM_TEXTURE_B8: case CELL_GCM_TEXTURE_B8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
@ -265,11 +282,65 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0); D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
break; break;
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R5G6B5: shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2);
break; break;
case CELL_GCM_TEXTURE_R6G5B5: // TODO: Remap it to another format here, so it's not glitched out
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0);
break;
case CELL_GCM_TEXTURE_X16:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
break;
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
break;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1);
break;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
break;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0);
break;
case CELL_GCM_TEXTURE_A8R8G8B8: case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8: case CELL_GCM_TEXTURE_D8R8G8B8:
{ {
@ -279,6 +350,7 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
u8 remap_r = (textures[i].remap() >> 2) & 0x3; u8 remap_r = (textures[i].remap() >> 2) & 0x3;
u8 remap_g = (textures[i].remap() >> 4) & 0x3; u8 remap_g = (textures[i].remap() >> 4) & 0x3;
u8 remap_b = (textures[i].remap() >> 6) & 0x3; u8 remap_b = (textures[i].remap() >> 6) & 0x3;
if (is_render_target) if (is_render_target)
{ {
// ARGB format // ARGB format
@ -327,33 +399,6 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
break; break;
} }
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_D1R5G5B5:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
break;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
break;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
break;
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
break;
} }
m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc, m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc,

View File

@ -248,7 +248,7 @@ namespace rsx
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
default: default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format); LOG_ERROR(RSX, "Unimplemented pitch modifier for texture format: 0x%x", format);
return 0; return 0;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:

View File

@ -108,40 +108,69 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask)
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_B8: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A1R5G5B5: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_A4R4G4B4: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_R5G6B5: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_B8:
return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R };
case CELL_GCM_TEXTURE_G8B8:
return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G };
case CELL_GCM_TEXTURE_X16:
return { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R };
case CELL_GCM_TEXTURE_Y16_X16:
return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R };
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G };
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R };
case CELL_GCM_TEXTURE_A4R4G4B4:
{
VkComponentSwizzle map_table[] = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
return { map_table[remap_r], map_table[remap_g], map_table[remap_b], map_table[remap_a] };
}
case CELL_GCM_TEXTURE_D1R5G5B5:
return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE };
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R };
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R };
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO };
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_A8R8G8B8: case CELL_GCM_TEXTURE_A8R8G8B8:
{ {
VkComponentSwizzle map_table[] = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; VkComponentSwizzle map_table[] = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A };
return { map_table[remap_r], map_table[remap_g], map_table[remap_b], map_table[remap_a] }; return { map_table[remap_r], map_table[remap_g], map_table[remap_b], map_table[remap_a] };
} }
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };;
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_G8B8: return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE };
case CELL_GCM_TEXTURE_R6G5B5: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_DEPTH24_D8: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_DEPTH16: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_X16: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_Y16_X16: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_R5G5B5A1: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_X32_FLOAT: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
case CELL_GCM_TEXTURE_D1R5G5B5: return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE };
case CELL_GCM_TEXTURE_D8R8G8B8:
{
VkComponentSwizzle map_table[] = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE };
return{ map_table[remap_r], map_table[remap_g], map_table[remap_b], map_table[remap_a] };
} }
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; throw EXCEPTION("Invalid or unsupported component mapping for texture format (0x%x)", format);
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:return{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
}
throw EXCEPTION("Invalid or unsupported texture format (0x%x)", format);
} }
} }

View File

@ -65,30 +65,35 @@ namespace vk
{ {
case CELL_GCM_TEXTURE_B8: return VK_FORMAT_R8_UNORM; case CELL_GCM_TEXTURE_B8: return VK_FORMAT_R8_UNORM;
case CELL_GCM_TEXTURE_A1R5G5B5: 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_B4G4R4A4_UNORM_PACK16; case CELL_GCM_TEXTURE_A4R4G4B4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
case CELL_GCM_TEXTURE_R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; case CELL_GCM_TEXTURE_R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16;
case CELL_GCM_TEXTURE_A8R8G8B8: return VK_FORMAT_B8G8R8A8_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_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_DXT23: return VK_FORMAT_BC2_UNORM_BLOCK;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return VK_FORMAT_BC3_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_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_R6G5B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // Expand, discard high bit?
case CELL_GCM_TEXTURE_DEPTH24_D8: return VK_FORMAT_R32_UINT; case CELL_GCM_TEXTURE_DEPTH24_D8: return VK_FORMAT_R32_UINT;
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return VK_FORMAT_R32_SFLOAT; case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return VK_FORMAT_R32_SFLOAT;
case CELL_GCM_TEXTURE_DEPTH16: return VK_FORMAT_R16_UNORM; case CELL_GCM_TEXTURE_DEPTH16: return VK_FORMAT_R16_UINT;
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return VK_FORMAT_R16_SFLOAT; case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return VK_FORMAT_R16_SFLOAT;
case CELL_GCM_TEXTURE_X16: return VK_FORMAT_R16_UNORM; 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: return VK_FORMAT_R16G16_UNORM;
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return VK_FORMAT_R16G16_UNORM;
case CELL_GCM_TEXTURE_R5G5B5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; 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_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_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_X32_FLOAT: return VK_FORMAT_R32_SFLOAT;
case CELL_GCM_TEXTURE_D1R5G5B5: return VK_FORMAT_A1R5G5B5_UNORM_PACK16; 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_D8R8G8B8: return VK_FORMAT_B8G8R8A8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return VK_FORMAT_A8B8G8R8_UNORM_PACK32; //Expand case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return VK_FORMAT_A8B8G8R8_UNORM_PACK32; // Expand
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return VK_FORMAT_R8G8B8A8_UNORM; //Expand case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return VK_FORMAT_R8G8B8A8_UNORM; // Expand
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return VK_FORMAT_R8G8_UNORM;
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return VK_FORMAT_R8G8_SNORM;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return VK_FORMAT_R8G8_UNORM; // Not right
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return VK_FORMAT_R8G8_UNORM; // Not right
} }
throw EXCEPTION("Invalid or unsupported texture format (0x%x)", format); throw EXCEPTION("Invalid or unsupported sampler format for texture format (0x%x)", format);
} }
VkAllocationCallbacks default_callbacks() VkAllocationCallbacks default_callbacks()

View File

@ -721,8 +721,9 @@ s32 UTF8toUTF32()
s32 jstrchk(vm::cptr<void> jstr) s32 jstrchk(vm::cptr<void> jstr)
{ {
cellL10n.warning("jstrchk(jstr=*0x%x) -> utf8", jstr); cellL10n.todo("jstrchk(jstr=*0x%x) -> utf8", jstr);
// TODO: Actually detect the type of the string
return L10N_STR_UTF8; return L10N_STR_UTF8;
} }

View File

@ -25,7 +25,8 @@ enum
}; };
// CodePages // CodePages
enum { enum
{
L10N_UTF8 = 0, L10N_UTF8 = 0,
L10N_UTF16, L10N_UTF16,
L10N_UTF32, L10N_UTF32,

View File

@ -316,7 +316,7 @@ s32 pngDecOpen(PPUThread& ppu, PHandle handle, PPStream png_stream, PSrc source,
// Check for if the buffer structure allocation failed // Check for if the buffer structure allocation failed
if (!buffer) if (!buffer)
{ {
throw EXCEPTION("Memory allocation for the buffer PNG reading structure failed."); throw EXCEPTION("Memory allocation for the PNG buffer structure failed.");
} }
// We might not be reading from a file stream // We might not be reading from a file stream
@ -328,6 +328,12 @@ s32 pngDecOpen(PPUThread& ppu, PHandle handle, PPStream png_stream, PSrc source,
// Open the buffer/file and check the header // Open the buffer/file and check the header
u8 header[8]; u8 header[8];
// Need to test it somewhere
if (stream->source.fileOffset != 0)
{
throw EXCEPTION("Non-0 file offset not supported.");
}
// Depending on the source type, get the first 8 bytes // Depending on the source type, get the first 8 bytes
if (source->srcSelect == CELL_PNGDEC_FILE) if (source->srcSelect == CELL_PNGDEC_FILE)
{ {
@ -564,7 +570,11 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
// Get the amount of output bytes per line // Get the amount of output bytes per line
const u32 bytes_per_line = data_control_param->outputBytesPerLine; const u32 bytes_per_line = data_control_param->outputBytesPerLine;
// Whether to recaculate bytes per row
bool recalculate_bytes_per_row = false;
// Check if the game is expecting the number of bytes per line to be lower, than the actual bytes per line on the image. (Arkedo Pixel for example) // Check if the game is expecting the number of bytes per line to be lower, than the actual bytes per line on the image. (Arkedo Pixel for example)
// In such case we strip the bit depth to be lower.
if ((bytes_per_line < stream->out_param.outputWidthByte) && stream->out_param.outputBitDepth != 8) if ((bytes_per_line < stream->out_param.outputWidthByte) && stream->out_param.outputBitDepth != 8)
{ {
// Check if the packing is really 1 byte per 1 pixel // Check if the packing is really 1 byte per 1 pixel
@ -575,18 +585,7 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
// Scale 16 bit depth down to 8 bit depth. PS3 uses png_set_strip_16, since png_set_scale_16 wasn't available back then. // Scale 16 bit depth down to 8 bit depth. PS3 uses png_set_strip_16, since png_set_scale_16 wasn't available back then.
png_set_strip_16(stream->png_ptr); png_set_strip_16(stream->png_ptr);
recalculate_bytes_per_row = true;
// We need to tell libpng to update the info structure, since we modified the info
png_read_update_info(stream->png_ptr, stream->info_ptr);
// Recalculate the outputWidthByte value, and recalculate the image size
stream->out_param.outputWidthByte = png_get_rowbytes(stream->png_ptr, stream->info_ptr);
// What do we do if bytes_per_line is still samller? Something probably went wrong, but this should never happen anyway.
if (bytes_per_line < stream->out_param.outputWidthByte)
{
throw EXCEPTION("bytesPerLine is still smaller than outputWidthByte: %d", stream->out_param.outputWidthByte);
}
} }
// Check if the outputWidthByte is smaller than the intended output length of a line. For example an image might be in RGB, but we need to output 4 components, so we need to perform alpha padding. // Check if the outputWidthByte is smaller than the intended output length of a line. For example an image might be in RGB, but we need to output 4 components, so we need to perform alpha padding.
else if (stream->out_param.outputWidthByte < (stream->out_param.outputWidth * stream->out_param.outputComponents)) else if (stream->out_param.outputWidthByte < (stream->out_param.outputWidth * stream->out_param.outputComponents))
@ -600,18 +599,31 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
// We need to fill alpha (before or after, depending on the output colour format) using the fixed alpha value passed by the game. // We need to fill alpha (before or after, depending on the output colour format) using the fixed alpha value passed by the game.
png_set_add_alpha(stream->png_ptr, stream->fixed_alpha_colour, stream->out_param.outputColorSpace == CELL_PNGDEC_RGBA ? PNG_FILLER_AFTER : PNG_FILLER_BEFORE); png_set_add_alpha(stream->png_ptr, stream->fixed_alpha_colour, stream->out_param.outputColorSpace == CELL_PNGDEC_RGBA ? PNG_FILLER_AFTER : PNG_FILLER_BEFORE);
recalculate_bytes_per_row = true;
// We need to tell libpng to update the info structure, since we modified the info
png_read_update_info(stream->png_ptr, stream->info_ptr);
// Calculate the actual needed output image size
stream->out_param.outputWidthByte = stream->out_param.outputWidth * stream->out_param.outputComponents;
} }
// We decode as RGBA, so we need to swap the alpha
else if (stream->out_param.outputColorSpace == CELL_PNGDEC_ARGB) else if (stream->out_param.outputColorSpace == CELL_PNGDEC_ARGB)
{ {
// Swap the alpha channel for the ARGB output format, if the padding isn't needed // Swap the alpha channel for the ARGB output format, if the padding isn't needed
png_set_swap_alpha(stream->png_ptr); png_set_swap_alpha(stream->png_ptr);
} }
// Sometimes games pass in a RBG/RGBA image and want it as grayscale
else if ((stream->out_param.outputColorSpace == CELL_PNGDEC_GRAYSCALE_ALPHA || stream->out_param.outputColorSpace == CELL_PNGDEC_GRAYSCALE)
&& (stream->info.colorSpace == CELL_PNGDEC_RGB || stream->info.colorSpace == CELL_PNGDEC_RGBA))
{
// Tell libpng to convert it to grayscale
png_set_rgb_to_gray(stream->png_ptr, PNG_ERROR_ACTION_NONE, PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
recalculate_bytes_per_row = true;
}
if (recalculate_bytes_per_row)
{
// Update the info structure
png_read_update_info(stream->png_ptr, stream->info_ptr);
// Recalculate the bytes per row
stream->out_param.outputWidthByte = png_get_rowbytes(stream->png_ptr, stream->info_ptr);
}
// Calculate the image size // Calculate the image size
u32 image_size = stream->out_param.outputWidthByte * stream->out_param.outputHeight; u32 image_size = stream->out_param.outputWidthByte * stream->out_param.outputHeight;
@ -634,23 +646,22 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
// Check if the image needs to be flipped // Check if the image needs to be flipped
const bool flip = stream->out_param.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP; const bool flip = stream->out_param.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP;
// Copy the result to the output buffer
switch (stream->out_param.outputColorSpace) switch (stream->out_param.outputColorSpace)
{ {
case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGB:
{
throw EXCEPTION("RGB colour format.");
break;
}
case CELL_PNGDEC_RGBA: case CELL_PNGDEC_RGBA:
case CELL_PNGDEC_ARGB:
case CELL_PNGDEC_GRAYSCALE_ALPHA:
{ {
// Check if we need to flip the image or leave empty space at the end of a line // Check if we need to flip the image or need to leave empty bytes at the end of a line
if ((bytes_per_line > stream->out_param.outputWidthByte) || flip) if ((bytes_per_line > stream->out_param.outputWidthByte) || flip)
{ {
// Get how many bytes per line we need to output - bytesPerLine is total amount of bytes per line, rest is unused and the game can do as it pleases. // Get how many bytes per line we need to output - bytesPerLine is total amount of bytes per line, rest is unused and the game can do as it pleases.
const u32 line_size = std::min(bytes_per_line, stream->out_param.outputWidth * 4); const u32 line_size = std::min(bytes_per_line, stream->out_param.outputWidth * 4);
// If the game wants more bytes per line to be output, than the image has, then we simply copy what we have for each line, and continue on the next line, leaving empty space at the end of the line. // If the game wants more bytes per line to be output, than the image has, then we simply copy what we have for each line,
// and continue on the next line, thus leaving empty bytes at the end of the line.
for (u32 i = 0; i < stream->out_param.outputHeight; i++) for (u32 i = 0; i < stream->out_param.outputHeight; i++)
{ {
const u32 dst = i * bytes_per_line; const u32 dst = i * bytes_per_line;
@ -666,28 +677,6 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
break; break;
} }
case CELL_PNGDEC_ARGB:
{
// Check if we need to flip the image or leave empty space at the end of a line
if ((bytes_per_line > stream->out_param.outputWidthByte) || flip)
{
// Haven't found a game to test this with
throw EXCEPTION("ARGB is big.");
// Flipping is untested
if (flip)
{
throw EXCEPTION("Flipping is not yet supported.");
}
}
else
{
// We can simply copy the output to the data pointer specified by the game, since we already do alpha channel transformations in libpng, if needed
memcpy(data.get_ptr(), png.data(), image_size);
}
break;
}
default: throw EXCEPTION("Unsupported color space (%d)", stream->out_param.outputColorSpace); default: throw EXCEPTION("Unsupported color space (%d)", stream->out_param.outputColorSpace);
} }
@ -696,7 +685,7 @@ s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> da
png_get_text(stream->png_ptr, stream->info_ptr, nullptr, &text_chunks); png_get_text(stream->png_ptr, stream->info_ptr, nullptr, &text_chunks);
// Set the chunk information and the previously obtained number of text chunks // Set the chunk information and the previously obtained number of text chunks
data_out_info->numText = text_chunks; data_out_info->numText = (u32)text_chunks;
data_out_info->chunkInformation = pngDecGetChunkInformation(stream, true); data_out_info->chunkInformation = pngDecGetChunkInformation(stream, true);
data_out_info->numUnknownChunk = 0; // TODO: Get this somehow. Does anything even use or need this? data_out_info->numUnknownChunk = 0; // TODO: Get this somehow. Does anything even use or need this?