mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 12:56:53 +02:00
support 16-bit float video-out
This commit is contained in:
@@ -129,6 +129,7 @@ struct ColorComponentMapping {
|
|||||||
static_assert(sizeof(ColorComponentMapping) == sizeof(uint8_t));
|
static_assert(sizeof(ColorComponentMapping) == sizeof(uint8_t));
|
||||||
|
|
||||||
inline constexpr ColorComponentMapping ColorMappingAbgr {0x1bu}; // 3, 2, 1, 0
|
inline constexpr ColorComponentMapping ColorMappingAbgr {0x1bu}; // 3, 2, 1, 0
|
||||||
|
inline constexpr ColorComponentMapping ColorMappingBgra {0xc6u}; // 2, 1, 0, 3
|
||||||
|
|
||||||
enum class DepthFormat : uint32_t {
|
enum class DepthFormat : uint32_t {
|
||||||
kInvalid = 0,
|
kInvalid = 0,
|
||||||
|
|||||||
@@ -114,6 +114,10 @@ RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t raw_layout, uint32_
|
|||||||
Prospero::ChannelOrder::kStandard)) {
|
Prospero::ChannelOrder::kStandard)) {
|
||||||
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8};
|
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8};
|
||||||
}
|
}
|
||||||
|
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
|
||||||
|
Prospero::ChannelOrder::kAlt)) {
|
||||||
|
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8, Prospero::ColorMappingBgra};
|
||||||
|
}
|
||||||
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
|
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
|
||||||
Prospero::ChannelOrder::kReversed)) {
|
Prospero::ChannelOrder::kReversed)) {
|
||||||
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8, Prospero::ColorMappingAbgr};
|
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8, Prospero::ColorMappingAbgr};
|
||||||
|
|||||||
@@ -179,6 +179,10 @@ static float ColorClearF16(uint32_t value) {
|
|||||||
color.float32[1] = ColorClearF16((c0 >> 16u) & 0xffffu);
|
color.float32[1] = ColorClearF16((c0 >> 16u) & 0xffffu);
|
||||||
color.float32[2] = ColorClearF16(c1 & 0xffffu);
|
color.float32[2] = ColorClearF16(c1 & 0xffffu);
|
||||||
color.float32[3] = ColorClearF16((c1 >> 16u) & 0xffffu);
|
color.float32[3] = ColorClearF16((c1 >> 16u) & 0xffffu);
|
||||||
|
if (rt.info.channel_order ==
|
||||||
|
Prospero::GpuEnumValue(Prospero::ChannelOrder::kAlt)) {
|
||||||
|
std::swap(color.float32[0], color.float32[2]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Prospero::ChannelLayout::k32:
|
case Prospero::ChannelLayout::k32:
|
||||||
case Prospero::ChannelLayout::k11_11_10:
|
case Prospero::ChannelLayout::k11_11_10:
|
||||||
@@ -535,6 +539,10 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
|
|||||||
order == Prospero::ChannelOrder::kAlt)) ||
|
order == Prospero::ChannelOrder::kAlt)) ||
|
||||||
(layout == Prospero::ChannelLayout::k10_10_10_2 &&
|
(layout == Prospero::ChannelLayout::k10_10_10_2 &&
|
||||||
type == Prospero::ChannelType::kUNorm &&
|
type == Prospero::ChannelType::kUNorm &&
|
||||||
|
(order == Prospero::ChannelOrder::kStandard ||
|
||||||
|
order == Prospero::ChannelOrder::kAlt)) ||
|
||||||
|
(layout == Prospero::ChannelLayout::k16_16_16_16 &&
|
||||||
|
type == Prospero::ChannelType::kFloat &&
|
||||||
(order == Prospero::ChannelOrder::kStandard || order == Prospero::ChannelOrder::kAlt));
|
(order == Prospero::ChannelOrder::kStandard || order == Prospero::ChannelOrder::kAlt));
|
||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(!supported_display_format);
|
EXIT_NOT_IMPLEMENTED(!supported_display_format);
|
||||||
@@ -555,6 +563,9 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
|
|||||||
r->extent = video_image.image->extent;
|
r->extent = video_image.image->extent;
|
||||||
r->base_mip_level = 0;
|
r->base_mip_level = 0;
|
||||||
r->buffer_size = video_image.size;
|
r->buffer_size = video_image.size;
|
||||||
|
r->export_mapping = TextureGetRenderTargetFormat(rt.info.format, rt.info.channel_type,
|
||||||
|
rt.info.channel_order)
|
||||||
|
.export_mapping;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -321,12 +321,20 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource
|
|||||||
TileGetTexturePitch(descriptor.Format(), static_cast<uint32_t>(descriptor.Width5()) + 1u, 1,
|
TileGetTexturePitch(descriptor.Format(), static_cast<uint32_t>(descriptor.Width5()) + 1u, 1,
|
||||||
descriptor.TileMode());
|
descriptor.TileMode());
|
||||||
EXIT("unsupported sampled depth target: resource=%d descriptor=%d encoding=%d format=%d "
|
EXIT("unsupported sampled depth target: resource=%d descriptor=%d encoding=%d format=%d "
|
||||||
"image_format=%d view_format=%d descriptor_pitch=%u target_pitch=%u "
|
"kind=%u dimension=%u mip=%u read=%d written=%d atomic=%d compare=%d "
|
||||||
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
"image_format=%d view_format=%d image_layers=%u descriptor_type=%u base_array=%u "
|
||||||
|
"depth=%u descriptor_pitch=%u target_pitch=%u fields=%08x/%08x/%08x/%08x/%08x/"
|
||||||
|
"%08x/%08x/%08x addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
||||||
resource_ok, descriptor_ok, encoding_ok, format_ok,
|
resource_ok, descriptor_ok, encoding_ok, format_ok,
|
||||||
|
static_cast<uint32_t>(resource.kind), static_cast<uint32_t>(resource.dimension),
|
||||||
|
static_cast<uint32_t>(resource.mip_mode), resource.read, resource.written, resource.atomic,
|
||||||
|
resource.depth_compare,
|
||||||
image == nullptr ? static_cast<int>(VK_FORMAT_UNDEFINED) : static_cast<int>(image->format),
|
image == nullptr ? static_cast<int>(VK_FORMAT_UNDEFINED) : static_cast<int>(image->format),
|
||||||
static_cast<int>(view_format), descriptor_pitch,
|
static_cast<int>(view_format), image == nullptr ? 0u : image->layers, descriptor.Type(),
|
||||||
image == nullptr ? 0u : image->guest_pitch, descriptor.Base40(), size);
|
descriptor.BaseArray5(), descriptor.Depth(), descriptor_pitch,
|
||||||
|
image == nullptr ? 0u : image->guest_pitch, descriptor.fields[0], descriptor.fields[1],
|
||||||
|
descriptor.fields[2], descriptor.fields[3], descriptor.fields[4], descriptor.fields[5],
|
||||||
|
descriptor.fields[6], descriptor.fields[7], descriptor.Base40(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::ImageResource& resource,
|
static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::ImageResource& resource,
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ struct VideoOutInfo {
|
|||||||
uint32_t tile_mode = 0;
|
uint32_t tile_mode = 0;
|
||||||
uint32_t dcc_control = 0;
|
uint32_t dcc_control = 0;
|
||||||
VideoOutCompression compression = VideoOutCompression::Unsupported;
|
VideoOutCompression compression = VideoOutCompression::Unsupported;
|
||||||
|
bool bgra16 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline VideoOutCompression
|
[[nodiscard]] inline VideoOutCompression
|
||||||
@@ -265,48 +266,61 @@ CanUseVideoOutNativeWithoutUpload(VideoOutCompression compression, bool render_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct VideoOutPixelFormatInfo {
|
struct VideoOutPixelFormatInfo {
|
||||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||||
uint32_t guest_format = 0;
|
uint32_t guest_format = 0;
|
||||||
|
uint32_t bytes_per_element = 0;
|
||||||
|
bool bgra16 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VideoOutFormatPolicy {
|
||||||
|
uint64_t pixel_format;
|
||||||
|
VideoOutPixelFormatInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {{
|
||||||
|
{0x8000000022000000ull,
|
||||||
|
{VK_FORMAT_R8G8B8A8_SRGB, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4,
|
||||||
|
false}},
|
||||||
|
{0x8000000000000000ull,
|
||||||
|
{VK_FORMAT_B8G8R8A8_SRGB, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4,
|
||||||
|
false}},
|
||||||
|
{0x8100000022000000ull,
|
||||||
|
{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
|
||||||
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
|
||||||
|
{0x8100000000000000ull,
|
||||||
|
{VK_FORMAT_A2R10G10B10_UNORM_PACK32,
|
||||||
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
|
||||||
|
{0xc001000622000000ull,
|
||||||
|
{VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||||
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, false}},
|
||||||
|
{0xc001000600000000ull,
|
||||||
|
{VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||||
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, true}},
|
||||||
|
}};
|
||||||
|
|
||||||
[[nodiscard]] inline bool DecodeVideoOutPixelFormat(uint64_t pixel_format,
|
[[nodiscard]] inline bool DecodeVideoOutPixelFormat(uint64_t pixel_format,
|
||||||
VideoOutPixelFormatInfo* info) {
|
VideoOutPixelFormatInfo* info) {
|
||||||
if (info == nullptr) {
|
if (info == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VideoOutPixelFormatInfo next {};
|
for (const auto& policy: VIDEO_OUT_FORMAT_POLICIES) {
|
||||||
switch (pixel_format) {
|
if (policy.pixel_format == pixel_format) {
|
||||||
case 0x8000000022000000ull: // SCE_VIDEO_OUT_PIXEL_FORMAT2_R8_G8_B8_A8_SRGB
|
*info = policy.info;
|
||||||
next.format = VK_FORMAT_R8G8B8A8_SRGB;
|
return true;
|
||||||
next.guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb);
|
}
|
||||||
break;
|
|
||||||
case 0x8000000000000000ull: // SCE_VIDEO_OUT_PIXEL_FORMAT2_B8_G8_R8_A8_SRGB
|
|
||||||
next.format = VK_FORMAT_B8G8R8A8_SRGB;
|
|
||||||
next.guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb);
|
|
||||||
break;
|
|
||||||
case 0x8100000022000000ull: // SCE_VIDEO_OUT_PIXEL_FORMAT2_R10_G10_B10_A2_SRGB
|
|
||||||
next.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
|
||||||
next.guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm);
|
|
||||||
break;
|
|
||||||
case 0x8100000000000000ull: // SCE_VIDEO_OUT_PIXEL_FORMAT2_B10_G10_R10_A2_SRGB
|
|
||||||
next.format = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
|
|
||||||
next.guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm);
|
|
||||||
break;
|
|
||||||
default: return false;
|
|
||||||
}
|
}
|
||||||
*info = next;
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool IsSupportedVideoOutFormat(uint32_t guest_format, VkFormat format) {
|
[[nodiscard]] inline bool IsSupportedVideoOutFormat(const VideoOutInfo& info) {
|
||||||
const bool rgba8 =
|
for (const auto& policy: VIDEO_OUT_FORMAT_POLICIES) {
|
||||||
guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb) &&
|
if (info.format == policy.info.format && info.guest_format == policy.info.guest_format &&
|
||||||
(format == VK_FORMAT_R8G8B8A8_SRGB || format == VK_FORMAT_B8G8R8A8_SRGB);
|
info.bytes_per_element == policy.info.bytes_per_element &&
|
||||||
const bool rgb10 =
|
info.bgra16 == policy.info.bgra16) {
|
||||||
guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm) &&
|
return true;
|
||||||
(format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
|
}
|
||||||
format == VK_FORMAT_A2R10G10B10_UNORM_PACK32);
|
}
|
||||||
return rgba8 || rgb10;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class DepthOverlap : uint8_t { None, RetireSampled, ExpandTarget, Unsupported };
|
enum class DepthOverlap : uint8_t { None, RetireSampled, ExpandTarget, Unsupported };
|
||||||
|
|||||||
@@ -1142,9 +1142,8 @@ void ValidateVideoOutInfo(GraphicContext* ctx, const VideoOutInfo& info) {
|
|||||||
(info.address & 0xffffu) != 0 || info.width == 0 || info.height == 0 ||
|
(info.address & 0xffffu) != 0 || info.width == 0 || info.height == 0 ||
|
||||||
info.width > 16384 || info.height > 16384 || info.pitch < info.width ||
|
info.width > 16384 || info.height > 16384 || info.pitch < info.width ||
|
||||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
|
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
|
||||||
info.bytes_per_element != 4 || compression == VideoOutCompression::Unsupported ||
|
compression == VideoOutCompression::Unsupported || compression != info.compression ||
|
||||||
compression != info.compression || metadata_invalid ||
|
metadata_invalid || !IsSupportedVideoOutFormat(info)) {
|
||||||
!IsSupportedVideoOutFormat(info.guest_format, info.format)) {
|
|
||||||
EXIT("TextureCache: unsupported video-out surface, ctx=%p addr=0x%016" PRIx64
|
EXIT("TextureCache: unsupported video-out surface, ctx=%p addr=0x%016" PRIx64
|
||||||
" size=0x%016" PRIx64 " metadata=0x%016" PRIx64 " dcc=0x%08" PRIx32
|
" size=0x%016" PRIx64 " metadata=0x%016" PRIx64 " dcc=0x%08" PRIx32
|
||||||
" extent=%ux%u pitch=%u tile=%u guest_format=%u bpe=%u vk_format=%d\n",
|
" extent=%ux%u pitch=%u tile=%u guest_format=%u bpe=%u vk_format=%d\n",
|
||||||
@@ -1211,6 +1210,12 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
|
|||||||
TileConvertTiledToLinearRenderTarget(
|
TileConvertTiledToLinearRenderTarget(
|
||||||
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
|
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
|
||||||
info.pitch, info.bytes_per_element, info.size);
|
info.pitch, info.bytes_per_element, info.size);
|
||||||
|
if (info.bgra16) {
|
||||||
|
auto* pixels = static_cast<uint16_t*>(scratch.Data());
|
||||||
|
for (uint64_t i = 0; i < info.size / sizeof(uint16_t); i += 4) {
|
||||||
|
std::swap(pixels[i], pixels[i + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch,
|
UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch,
|
||||||
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
|
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,7 +303,8 @@ static Graphics::VideoOutInfo MakeVideoOutInfo(const VideoOutBufferAttribute2& a
|
|||||||
if (!Graphics::DecodeVideoOutPixelFormat(attribute.pixel_format, &pixel_format)) {
|
if (!Graphics::DecodeVideoOutPixelFormat(attribute.pixel_format, &pixel_format)) {
|
||||||
EXIT("unsupported video-out pixel format: 0x%016" PRIx64 "\n", attribute.pixel_format);
|
EXIT("unsupported video-out pixel format: 0x%016" PRIx64 "\n", attribute.pixel_format);
|
||||||
}
|
}
|
||||||
const auto tile_mode = Graphics::Prospero::GpuEnumValue(Graphics::Prospero::TileMode::kRenderTarget);
|
const auto tile_mode =
|
||||||
|
Graphics::Prospero::GpuEnumValue(Graphics::Prospero::TileMode::kRenderTarget);
|
||||||
const auto pitch =
|
const auto pitch =
|
||||||
Graphics::TileGetTexturePitch(pixel_format.guest_format, attribute.width, 1, tile_mode);
|
Graphics::TileGetTexturePitch(pixel_format.guest_format, attribute.width, 1, tile_mode);
|
||||||
Graphics::TileSizeAlign total {};
|
Graphics::TileSizeAlign total {};
|
||||||
@@ -321,10 +322,11 @@ static Graphics::VideoOutInfo MakeVideoOutInfo(const VideoOutBufferAttribute2& a
|
|||||||
info.width = attribute.width;
|
info.width = attribute.width;
|
||||||
info.height = attribute.height;
|
info.height = attribute.height;
|
||||||
info.pitch = pitch;
|
info.pitch = pitch;
|
||||||
info.bytes_per_element = 4;
|
info.bytes_per_element = pixel_format.bytes_per_element;
|
||||||
info.tile_mode = tile_mode;
|
info.tile_mode = tile_mode;
|
||||||
info.dcc_control = attribute.dcc_control;
|
info.dcc_control = attribute.dcc_control;
|
||||||
info.compression = compression;
|
info.compression = compression;
|
||||||
|
info.bgra16 = pixel_format.bgra16;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10706,62 +10706,97 @@ void CheckBufferImageWrites() {
|
|||||||
|
|
||||||
void CheckImageOverlapResolution() {
|
void CheckImageOverlapResolution() {
|
||||||
CheckBufferImageWrites();
|
CheckBufferImageWrites();
|
||||||
VideoOutPixelFormatInfo video_format {};
|
VideoOutPixelFormatInfo video_format{};
|
||||||
Require("ImageOverlapResolution", "existing video-out formats",
|
Require(
|
||||||
DecodeVideoOutPixelFormat(0x8000000022000000ull, &video_format) &&
|
"ImageOverlapResolution", "existing video-out formats",
|
||||||
video_format.format == VK_FORMAT_R8G8B8A8_SRGB &&
|
DecodeVideoOutPixelFormat(0x8000000022000000ull, &video_format) &&
|
||||||
video_format.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb) &&
|
video_format.format == VK_FORMAT_R8G8B8A8_SRGB &&
|
||||||
DecodeVideoOutPixelFormat(0x8000000000000000ull, &video_format) &&
|
video_format.guest_format ==
|
||||||
video_format.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb) &&
|
||||||
video_format.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb) &&
|
DecodeVideoOutPixelFormat(0x8000000000000000ull, &video_format) &&
|
||||||
DecodeVideoOutPixelFormat(0x8100000022000000ull, &video_format) &&
|
video_format.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
||||||
video_format.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 &&
|
video_format.guest_format ==
|
||||||
video_format.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm),
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb) &&
|
||||||
"pre-existing PS5 video-out format mappings changed during decoder centralization");
|
DecodeVideoOutPixelFormat(0x8100000022000000ull, &video_format) &&
|
||||||
Require("ImageOverlapResolution", "B10G10R10A2 video-out format",
|
video_format.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 &&
|
||||||
DecodeVideoOutPixelFormat(0x8100000000000000ull, &video_format) &&
|
video_format.guest_format ==
|
||||||
video_format.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 &&
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm),
|
||||||
video_format.guest_format ==
|
"pre-existing PS5 video-out format mappings changed during decoder "
|
||||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm) &&
|
"centralization");
|
||||||
IsSupportedVideoOutFormat(video_format.guest_format, video_format.format),
|
Require(
|
||||||
"PS5 B10G10R10A2 sRGB video-out format did not preserve alternate channel order");
|
"ImageOverlapResolution", "B10G10R10A2 video-out format",
|
||||||
Require("ImageOverlapResolution", "video-out format guards",
|
DecodeVideoOutPixelFormat(0x8100000000000000ull, &video_format) &&
|
||||||
!DecodeVideoOutPixelFormat(0x8100070400000000ull, &video_format) &&
|
video_format.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 &&
|
||||||
!DecodeVideoOutPixelFormat(0x8100000000000000ull, nullptr) &&
|
video_format.guest_format ==
|
||||||
!IsSupportedVideoOutFormat(Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb),
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm),
|
||||||
VK_FORMAT_A2R10G10B10_UNORM_PACK32) &&
|
"PS5 B10G10R10A2 sRGB video-out format did not preserve alternate "
|
||||||
!IsSupportedVideoOutFormat(Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm),
|
"channel order");
|
||||||
VK_FORMAT_R8G8B8A8_SRGB),
|
Require(
|
||||||
"unsupported PS5 video-out formats or mismatched guest/host pairs were admitted");
|
"ImageOverlapResolution", "RGBA16 float video-out formats",
|
||||||
|
DecodeVideoOutPixelFormat(0xc001000622000000ull, &video_format) &&
|
||||||
|
video_format.format == VK_FORMAT_R16G16B16A16_SFLOAT &&
|
||||||
|
video_format.guest_format ==
|
||||||
|
Prospero::GpuEnumValue(
|
||||||
|
Prospero::BufferFormat::k16_16_16_16Float) &&
|
||||||
|
video_format.bytes_per_element == 8 &&
|
||||||
|
DecodeVideoOutPixelFormat(0xc001000600000000ull, &video_format) &&
|
||||||
|
video_format.bgra16,
|
||||||
|
"PS5 RGBA16-float video-out formats lost their 64-bpp storage contract");
|
||||||
|
VideoOutInfo supported_video_out{};
|
||||||
|
supported_video_out.format = video_format.format;
|
||||||
|
supported_video_out.guest_format = video_format.guest_format;
|
||||||
|
supported_video_out.bytes_per_element = video_format.bytes_per_element;
|
||||||
|
supported_video_out.bgra16 = video_format.bgra16;
|
||||||
|
Require(
|
||||||
|
"ImageOverlapResolution", "video-out format policy",
|
||||||
|
IsSupportedVideoOutFormat(supported_video_out),
|
||||||
|
"decoded PS5 video-out format was rejected by the centralized policy");
|
||||||
|
Require(
|
||||||
|
"ImageOverlapResolution", "video-out byte-size guards", ([&] {
|
||||||
|
auto mismatched = supported_video_out;
|
||||||
|
mismatched.bytes_per_element = 4;
|
||||||
|
return !IsSupportedVideoOutFormat(mismatched);
|
||||||
|
})(),
|
||||||
|
"video-out format validation admitted a mismatched storage element size");
|
||||||
|
Require(
|
||||||
|
"ImageOverlapResolution", "video-out format guards",
|
||||||
|
!DecodeVideoOutPixelFormat(0x8100070400000000ull, &video_format) &&
|
||||||
|
!DecodeVideoOutPixelFormat(0xc001070700000000ull, &video_format) &&
|
||||||
|
!DecodeVideoOutPixelFormat(0x8100000000000000ull, nullptr) && !([&] {
|
||||||
|
auto mismatched = supported_video_out;
|
||||||
|
mismatched.guest_format =
|
||||||
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb);
|
||||||
|
return IsSupportedVideoOutFormat(mismatched);
|
||||||
|
})(),
|
||||||
|
"unsupported PS5 video-out formats or mismatched guest/host pairs were "
|
||||||
|
"admitted");
|
||||||
TileSizeAlign render_target_layout{};
|
TileSizeAlign render_target_layout{};
|
||||||
Require("ImageOverlapResolution", "R8 render-target pitch",
|
Require("ImageOverlapResolution", "R8 render-target pitch",
|
||||||
TileGetRenderTargetPitch(1920, 1) == 2048,
|
TileGetRenderTargetPitch(1920, 1) == 2048,
|
||||||
"R8 target did not use native 256-pixel block width");
|
"R8 target did not use native 256-pixel block width");
|
||||||
Require("ImageOverlapResolution", "R8 render-target size",
|
Require("ImageOverlapResolution", "R8 render-target size",
|
||||||
TileGetRenderTargetSize(1920, 1080, 2048, 1,
|
TileGetRenderTargetSize(1920, 1080, 2048, 1, &render_target_layout) &&
|
||||||
&render_target_layout) &&
|
|
||||||
render_target_layout.size == 0x280000 &&
|
render_target_layout.size == 0x280000 &&
|
||||||
render_target_layout.align == 0x10000,
|
render_target_layout.align == 0x10000,
|
||||||
"R8 target did not use native 64-KiB block geometry");
|
"R8 target did not use native 64-KiB block geometry");
|
||||||
Require("ImageOverlapResolution", "RGBA8 render-target size",
|
Require(
|
||||||
TileGetRenderTargetPitch(1920, 4) == 1920 &&
|
"ImageOverlapResolution", "RGBA8 render-target size",
|
||||||
TileGetRenderTargetSize(1920, 1080, 1920, 4,
|
TileGetRenderTargetPitch(1920, 4) == 1920 &&
|
||||||
&render_target_layout) &&
|
TileGetRenderTargetSize(1920, 1080, 1920, 4, &render_target_layout) &&
|
||||||
render_target_layout.size == 0x870000,
|
render_target_layout.size == 0x870000,
|
||||||
"RGBA8 target layout regressed");
|
"RGBA8 target layout regressed");
|
||||||
Require("ImageOverlapResolution", "PPSA19268 render-target edge",
|
Require("ImageOverlapResolution", "PPSA19268 render-target edge",
|
||||||
TileGetRenderTargetPitch(120, 8) == 128 &&
|
TileGetRenderTargetPitch(120, 8) == 128 &&
|
||||||
TileGetRenderTargetSize(120, 67, 128, 8,
|
TileGetRenderTargetSize(120, 67, 128, 8, &render_target_layout) &&
|
||||||
&render_target_layout) &&
|
|
||||||
render_target_layout.size == 0x20000 &&
|
render_target_layout.size == 0x20000 &&
|
||||||
ImageRangeOverlaps(0x11029fff8ull, 1, 0x110280000ull,
|
ImageRangeOverlaps(0x11029fff8ull, 1, 0x110280000ull,
|
||||||
render_target_layout.size),
|
render_target_layout.size),
|
||||||
"title write did not land in the final native render-target block");
|
"title write did not land in the final native render-target block");
|
||||||
Require("ImageOverlapResolution", "render-target layout rejection",
|
Require(
|
||||||
TileGetRenderTargetPitch(1920, 3) == 0 &&
|
"ImageOverlapResolution", "render-target layout rejection",
|
||||||
!TileGetRenderTargetSize(1920, 1080, 1920, 1,
|
TileGetRenderTargetPitch(1920, 3) == 0 &&
|
||||||
&render_target_layout),
|
!TileGetRenderTargetSize(1920, 1080, 1920, 1, &render_target_layout),
|
||||||
"unsupported element size or mismatched pitch was admitted");
|
"unsupported element size or mismatched pitch was admitted");
|
||||||
|
|
||||||
TileSizeOffset mip_levels[16]{};
|
TileSizeOffset mip_levels[16]{};
|
||||||
TilePaddedSize mip_padded[16]{};
|
TilePaddedSize mip_padded[16]{};
|
||||||
|
|||||||
Reference in New Issue
Block a user