mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
renderer: support depth-compatible uint image views
This commit is contained in:
@@ -212,7 +212,6 @@ struct DepthFormatPolicy {
|
|||||||
Prospero::DepthFormat depth_format;
|
Prospero::DepthFormat depth_format;
|
||||||
Prospero::BufferFormat guest_format;
|
Prospero::BufferFormat guest_format;
|
||||||
uint32_t bytes_per_element;
|
uint32_t bytes_per_element;
|
||||||
vk::Format sampled_view_format;
|
|
||||||
vk::Format depth_attachment_format;
|
vk::Format depth_attachment_format;
|
||||||
std::array<vk::Format, 3> stencil_attachment_formats;
|
std::array<vk::Format, 3> stencil_attachment_formats;
|
||||||
};
|
};
|
||||||
@@ -221,13 +220,11 @@ inline constexpr std::array<DepthFormatPolicy, 2> DEPTH_FORMAT_POLICIES {{
|
|||||||
{Prospero::DepthFormat::kZ16,
|
{Prospero::DepthFormat::kZ16,
|
||||||
Prospero::BufferFormat::k16UNorm,
|
Prospero::BufferFormat::k16UNorm,
|
||||||
2,
|
2,
|
||||||
vk::Format::eR16Unorm,
|
|
||||||
vk::Format::eD16Unorm,
|
vk::Format::eD16Unorm,
|
||||||
{vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}},
|
{vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}},
|
||||||
{Prospero::DepthFormat::kZ32F,
|
{Prospero::DepthFormat::kZ32F,
|
||||||
Prospero::BufferFormat::k32Float,
|
Prospero::BufferFormat::k32Float,
|
||||||
4,
|
4,
|
||||||
vk::Format::eR32Sfloat,
|
|
||||||
vk::Format::eD32Sfloat,
|
vk::Format::eD32Sfloat,
|
||||||
{vk::Format::eD32SfloatS8Uint, vk::Format::eUndefined, vk::Format::eUndefined}},
|
{vk::Format::eD32SfloatS8Uint, vk::Format::eUndefined, vk::Format::eUndefined}},
|
||||||
}};
|
}};
|
||||||
@@ -317,25 +314,6 @@ inline bool ImageInfo::IsDepth() const noexcept {
|
|||||||
return std::bit_cast<uint32_t>(static_cast<float>(value) / 65535.0f);
|
return std::bit_cast<uint32_t>(static_cast<float>(value) / 65535.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline constexpr bool
|
|
||||||
IsSupportedSampledDepthFormat(vk::Format image_format, Prospero::BufferFormat guest_format,
|
|
||||||
vk::Format view_format) noexcept {
|
|
||||||
const auto* policy = FindGuestDepthFormatPolicy(guest_format);
|
|
||||||
return policy != nullptr && view_format == policy->sampled_view_format &&
|
|
||||||
(image_format == policy->depth_attachment_format ||
|
|
||||||
IsStencilAttachmentFormat(*policy, image_format));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format,
|
|
||||||
vk::Format view_format) noexcept {
|
|
||||||
for (const auto& policy: DEPTH_FORMAT_POLICIES) {
|
|
||||||
if (IsSupportedSampledDepthFormat(image_format, policy.guest_format, view_format)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline constexpr bool IsSupportedDepthTargetFormat(const ImageInfo& info) {
|
[[nodiscard]] inline constexpr bool IsSupportedDepthTargetFormat(const ImageInfo& info) {
|
||||||
const auto* policy = FindGuestDepthFormatPolicy(info.guest_format);
|
const auto* policy = FindGuestDepthFormatPolicy(info.guest_format);
|
||||||
return policy != nullptr && info.bytes_per_block == policy->bytes_per_element &&
|
return policy != nullptr && info.bytes_per_block == policy->bytes_per_element &&
|
||||||
|
|||||||
@@ -36,17 +36,6 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsDepthViewFormat(vk::Format format) {
|
|
||||||
switch (format) {
|
|
||||||
case vk::Format::eD16Unorm:
|
|
||||||
case vk::Format::eR16Unorm:
|
|
||||||
case vk::Format::eD32Sfloat:
|
|
||||||
case vk::Format::eR32Sfloat:
|
|
||||||
case vk::Format::eR32Uint: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsValidViewType(const VulkanImage& image, const ImageViewInfo& info) {
|
[[nodiscard]] bool IsValidViewType(const VulkanImage& image, const ImageViewInfo& info) {
|
||||||
switch (image.image_type) {
|
switch (image.image_type) {
|
||||||
case vk::ImageType::e1D:
|
case vk::ImageType::e1D:
|
||||||
@@ -328,7 +317,8 @@ vk::ImageView Image::FindView(const ImageViewInfo& view_info) {
|
|||||||
auto normalized = view_info;
|
auto normalized = view_info;
|
||||||
const bool is_storage = static_cast<bool>(normalized.usage & vk::ImageUsageFlagBits::eStorage);
|
const bool is_storage = static_cast<bool>(normalized.usage & vk::ImageUsageFlagBits::eStorage);
|
||||||
const auto image_aspect = FullAspectMask(image.format);
|
const auto image_aspect = FullAspectMask(image.format);
|
||||||
if (image_aspect & vk::ImageAspectFlagBits::eDepth && IsDepthViewFormat(normalized.format)) {
|
if (image_aspect & vk::ImageAspectFlagBits::eDepth &&
|
||||||
|
ImageViewOps::IsFormatDepthCompatible(normalized.format)) {
|
||||||
normalized.format = image.format;
|
normalized.format = image.format;
|
||||||
normalized.aspect = vk::ImageAspectFlagBits::eDepth;
|
normalized.aspect = vk::ImageAspectFlagBits::eDepth;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,25 @@ namespace ImageViewOps {
|
|||||||
|
|
||||||
[[nodiscard]] vk::ImageAspectFlags DepthAspectMask(vk::Format format);
|
[[nodiscard]] vk::ImageAspectFlags DepthAspectMask(vk::Format format);
|
||||||
[[nodiscard]] bool FormatsCompatible(vk::Format base, vk::Format view) noexcept;
|
[[nodiscard]] bool FormatsCompatible(vk::Format base, vk::Format view) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool IsFormatDepthCompatible(vk::Format format) noexcept {
|
||||||
|
switch (format) {
|
||||||
|
case vk::Format::eD32Sfloat:
|
||||||
|
case vk::Format::eR32Sfloat:
|
||||||
|
case vk::Format::eR32Uint:
|
||||||
|
case vk::Format::eD16Unorm:
|
||||||
|
case vk::Format::eR16Unorm: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace ImageViewOps
|
} // namespace ImageViewOps
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool IsSupportedSampledDepthFormat(vk::Format image_format,
|
||||||
|
vk::Format view_format) noexcept {
|
||||||
|
return DepthAspectTransferFormat(image_format) != vk::Format::eUndefined &&
|
||||||
|
ImageViewOps::IsFormatDepthCompatible(view_format);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool IsValidImageSwizzle(uint32_t swizzle) noexcept {
|
[[nodiscard]] inline bool IsValidImageSwizzle(uint32_t swizzle) noexcept {
|
||||||
if ((swizzle & ~0xfffu) != 0) {
|
if ((swizzle & ~0xfffu) != 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -86,8 +103,14 @@ SelectSampledDepthView(vk::Format image_format, vk::Format view_format, uint32_t
|
|||||||
|
|
||||||
[[nodiscard]] inline bool
|
[[nodiscard]] inline bool
|
||||||
IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept {
|
IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept {
|
||||||
return resource.kind == ShaderRecompiler::IR::ResourceKind::Image &&
|
if (resource.kind != ShaderRecompiler::IR::ResourceKind::Image &&
|
||||||
(resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D ||
|
resource.kind != ShaderRecompiler::IR::ResourceKind::ImageUint) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint && resource.depth_compare) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D ||
|
||||||
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray ||
|
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray ||
|
||||||
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa ||
|
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa ||
|
||||||
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaaArray) &&
|
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaaArray) &&
|
||||||
@@ -95,14 +118,6 @@ IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resou
|
|||||||
!resource.written && !resource.atomic;
|
!resource.written && !resource.atomic;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
IsSupportedSampledDepthUintResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept {
|
|
||||||
return resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint &&
|
|
||||||
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
|
|
||||||
resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::None && resource.read &&
|
|
||||||
!resource.written && !resource.atomic && !resource.depth_compare;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ValidateStorageColorView(vk::Format image_format, vk::Format view_format,
|
inline void ValidateStorageColorView(vk::Format image_format, vk::Format view_format,
|
||||||
uint32_t swizzle) noexcept {
|
uint32_t swizzle) noexcept {
|
||||||
if (!ImageViewOps::FormatsCompatible(image_format, view_format) ||
|
if (!ImageViewOps::FormatsCompatible(image_format, view_format) ||
|
||||||
|
|||||||
@@ -316,8 +316,7 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource
|
|||||||
const bool encoding_ok =
|
const bool encoding_ok =
|
||||||
image != nullptr && IsSupportedDepthTextureEncoding(descriptor, *image);
|
image != nullptr && IsSupportedDepthTextureEncoding(descriptor, *image);
|
||||||
const bool format_ok =
|
const bool format_ok =
|
||||||
image != nullptr &&
|
image != nullptr && IsSupportedSampledDepthFormat(image->info.pixel_format, view_format);
|
||||||
IsSupportedSampledDepthFormat(image->info.pixel_format, descriptor.Format(), view_format);
|
|
||||||
if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) {
|
if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7344,6 +7344,71 @@ public:
|
|||||||
"attachment");
|
"attachment");
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
|
||||||
|
const auto sampled_width = depth_only.desc.info.extent.width - 1u;
|
||||||
|
const auto sampled_height = depth_only.desc.info.extent.height - 1u;
|
||||||
|
const auto sampled_address = depth_only_address >> 8u;
|
||||||
|
ShaderTextureResource sampled_depth_descriptor{};
|
||||||
|
sampled_depth_descriptor.fields[0] =
|
||||||
|
static_cast<uint32_t>(sampled_address);
|
||||||
|
sampled_depth_descriptor.fields[1] =
|
||||||
|
static_cast<uint32_t>(sampled_address >> 32u) |
|
||||||
|
(static_cast<uint32_t>(Prospero::BufferFormat::k32UInt) << 20u) |
|
||||||
|
((sampled_width & 3u) << 30u);
|
||||||
|
sampled_depth_descriptor.fields[2] =
|
||||||
|
(sampled_width >> 2u) | (sampled_height << 14u);
|
||||||
|
sampled_depth_descriptor.fields[3] =
|
||||||
|
DstSel(4, 4, 4, 4) |
|
||||||
|
(static_cast<uint32_t>(Prospero::TileMode::kDepth) << 20u) |
|
||||||
|
(static_cast<uint32_t>(Prospero::ImageType::kColor2D) << 28u);
|
||||||
|
sampled_depth_descriptor.fields[5] = 0x00700000u;
|
||||||
|
ShaderRecompiler::IR::DescriptorValue sampled_depth_value{};
|
||||||
|
std::copy(std::begin(sampled_depth_descriptor.fields),
|
||||||
|
std::end(sampled_depth_descriptor.fields),
|
||||||
|
sampled_depth_value.dwords.begin());
|
||||||
|
sampled_depth_value.dword_count = 8;
|
||||||
|
ShaderRecompiler::IR::ImageResource sampled_depth_resource{};
|
||||||
|
sampled_depth_resource.kind =
|
||||||
|
ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||||
|
sampled_depth_resource.dimension =
|
||||||
|
ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||||
|
sampled_depth_resource.read = true;
|
||||||
|
const auto sampled_depth_backing =
|
||||||
|
texture_cache.GetImage(depth_only.image_id).backing.image;
|
||||||
|
auto sampled_depth_binding = RenderExecutorTestAccess::ResolveTexture(
|
||||||
|
executor, sampled_depth_resource, sampled_depth_value);
|
||||||
|
const auto sampled_depth_view = texture_cache.FindTexture(
|
||||||
|
sampled_depth_binding.image_id, sampled_depth_binding.desc);
|
||||||
|
const auto &sampled_depth_image =
|
||||||
|
texture_cache.GetImage(sampled_depth_binding.image_id);
|
||||||
|
const bool normalized_depth_view = std::ranges::any_of(
|
||||||
|
sampled_depth_image.views.views, [&](const auto &cached) {
|
||||||
|
return cached.view == sampled_depth_view &&
|
||||||
|
cached.info.format == vk::Format::eD32Sfloat &&
|
||||||
|
cached.info.aspect == vk::ImageAspectFlagBits::eDepth &&
|
||||||
|
cached.info.usage == vk::ImageUsageFlags{};
|
||||||
|
});
|
||||||
|
Require(
|
||||||
|
name, "R32 uint depth-backed view",
|
||||||
|
sampled_depth_binding.image_id == depth_only.image_id &&
|
||||||
|
sampled_depth_binding.desc.info.guest_format ==
|
||||||
|
Prospero::BufferFormat::k32UInt &&
|
||||||
|
sampled_depth_binding.desc.info.pixel_format ==
|
||||||
|
vk::Format::eR32Uint &&
|
||||||
|
sampled_depth_binding.desc.view_info.format ==
|
||||||
|
vk::Format::eR32Uint &&
|
||||||
|
sampled_depth_binding.desc.view_info.aspect ==
|
||||||
|
vk::ImageAspectFlagBits::eColor &&
|
||||||
|
sampled_depth_binding.desc.view_info.usage ==
|
||||||
|
vk::ImageUsageFlagBits::eSampled &&
|
||||||
|
sampled_depth_image.info.pixel_format ==
|
||||||
|
vk::Format::eD32Sfloat &&
|
||||||
|
sampled_depth_image.backing.format == vk::Format::eD32Sfloat &&
|
||||||
|
sampled_depth_image.backing.image == sampled_depth_backing &&
|
||||||
|
sampled_depth_view != nullptr && normalized_depth_view,
|
||||||
|
"uint T# did not retain its requested format while the concrete "
|
||||||
|
"view followed the D32 backing");
|
||||||
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
|
||||||
auto video_subresource =
|
auto video_subresource =
|
||||||
make_target_desc(base + 0x20000, target_mip_size, {1, 1, 1});
|
make_target_desc(base + 0x20000, target_mip_size, {1, 1, 1});
|
||||||
video_subresource.type = BindingType::VideoOut;
|
video_subresource.type = BindingType::VideoOut;
|
||||||
@@ -16650,7 +16715,8 @@ TestCase ImageLoadR32UintUsesIntegerSampledImage() {
|
|||||||
test.sampled_image_dwords_per_pixel = 1;
|
test.sampled_image_dwords_per_pixel = 1;
|
||||||
test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32UInt);
|
test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32UInt);
|
||||||
test.has_user_data = true;
|
test.has_user_data = true;
|
||||||
test.required_spirv = {"sampled_uint_2d"};
|
test.required_spirv = {"sampled_uint_2d", "OpTypeImage %uint",
|
||||||
|
"OpImageFetch %v4uint"};
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18398,7 +18464,7 @@ void CheckRenderTargetFormatContract() {
|
|||||||
DstSel(7, 6, 5, 3));
|
DstSel(7, 6, 5, 3));
|
||||||
} else if (std::strcmp(kind, "sampled-depth-format") == 0) {
|
} else if (std::strcmp(kind, "sampled-depth-format") == 0) {
|
||||||
(void)SelectSampledDepthView(vk::Format::eD24UnormS8Uint,
|
(void)SelectSampledDepthView(vk::Format::eD24UnormS8Uint,
|
||||||
vk::Format::eR32Sfloat, DstSel(4, 4, 4, 4));
|
vk::Format::eR8Unorm, DstSel(4, 4, 4, 4));
|
||||||
} else if (std::strcmp(kind, "sampled-depth-swizzle") == 0) {
|
} else if (std::strcmp(kind, "sampled-depth-swizzle") == 0) {
|
||||||
(void)SelectSampledDepthView(vk::Format::eD32SfloatS8Uint,
|
(void)SelectSampledDepthView(vk::Format::eD32SfloatS8Uint,
|
||||||
vk::Format::eR32Sfloat, DstSel(4, 5, 6, 7));
|
vk::Format::eR32Sfloat, DstSel(4, 5, 6, 7));
|
||||||
@@ -18767,12 +18833,19 @@ void CheckSampledDepthResource() {
|
|||||||
"array shader resource accepted a non-array descriptor view");
|
"array shader resource accepted a non-array descriptor view");
|
||||||
resource = basic;
|
resource = basic;
|
||||||
resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||||
Require("SampledDepthResource", "integer rejected",
|
Require("SampledDepthResource", "integer read",
|
||||||
|
IsSupportedSampledDepthResource(resource),
|
||||||
|
"read-only uint depth resource was rejected");
|
||||||
|
resource.depth_compare = true;
|
||||||
|
Require("SampledDepthResource", "integer comparison rejected",
|
||||||
!IsSupportedSampledDepthResource(resource),
|
!IsSupportedSampledDepthResource(resource),
|
||||||
"integer depth resource was accepted");
|
"uint depth resource accepted comparison sampling");
|
||||||
Require("SampledDepthResource", "integer reinterpret resource",
|
Require("SampledDepthResource", "R32 uint depth view",
|
||||||
IsSupportedSampledDepthUintResource(resource),
|
IsSupportedSampledDepthFormat(vk::Format::eD32Sfloat,
|
||||||
"read-only uint depth reinterpretation resource was rejected");
|
vk::Format::eR32Uint) &&
|
||||||
|
!IsSupportedSampledDepthFormat(vk::Format::eR32Uint,
|
||||||
|
vk::Format::eR32Uint),
|
||||||
|
"R32 uint depth-view compatibility diverged from its backing role");
|
||||||
std::printf("[host] %-32s ok\n", "SampledDepthResource");
|
std::printf("[host] %-32s ok\n", "SampledDepthResource");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user