mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-03 11:23:49 +00:00
D16S8 support
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <vulkan/vk_enum_string_helper.h>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
@@ -59,6 +60,38 @@ static bool UsesStencilOpValue(uint8_t fail, uint8_t pass, uint8_t depth_fail) {
|
||||
depth_fail == Prospero::GpuEnumValue(Prospero::StencilOp::kReplaceOp);
|
||||
}
|
||||
|
||||
[[nodiscard]] static VkFormat ResolveHostDepthAttachmentFormat(GraphicContext* ctx,
|
||||
const DepthFormatPolicy& policy,
|
||||
bool has_stencil) {
|
||||
if (!has_stencil) {
|
||||
return policy.depth_attachment_format;
|
||||
}
|
||||
switch (policy.depth_format) {
|
||||
case Prospero::DepthFormat::kZ32F: return policy.stencil_attachment_formats.front();
|
||||
case Prospero::DepthFormat::kZ16: {
|
||||
if (ctx == nullptr) {
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
// Kyty selects one physical device. Query its optional D16S8-compatible formats once.
|
||||
static std::once_flag once;
|
||||
static VkFormat selected = VK_FORMAT_UNDEFINED;
|
||||
std::call_once(once, [&] {
|
||||
for (const auto format: policy.stencil_attachment_formats) {
|
||||
VkImageFormatProperties properties {};
|
||||
if (vkGetPhysicalDeviceImageFormatProperties(
|
||||
ctx->physical_device, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
||||
DepthTargetImageUsage(), 0, &properties) == VK_SUCCESS) {
|
||||
selected = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return selected;
|
||||
}
|
||||
default: return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,
|
||||
RenderDepthInfo* r) {
|
||||
@@ -200,26 +233,21 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
|
||||
(z.pitch_div8_minus1 != 0 || z.height_div8_minus1 != 0 || z.slice_div64_minus1 != 0))) {
|
||||
DepthFatal("inconsistent depth extent or encoded layout");
|
||||
}
|
||||
uint32_t guest_format = 0;
|
||||
uint32_t bytes = 0;
|
||||
switch (static_cast<Prospero::DepthFormat>(z.z_info.format)) {
|
||||
case Prospero::DepthFormat::kZ16:
|
||||
if (has_stencil) {
|
||||
DepthFatal("Z16 plus stencil is unsupported");
|
||||
}
|
||||
r->format = VK_FORMAT_D16_UNORM;
|
||||
guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm);
|
||||
bytes = 2;
|
||||
break;
|
||||
case Prospero::DepthFormat::kZ32F:
|
||||
r->format = has_stencil ? VK_FORMAT_D32_SFLOAT_S8_UINT : VK_FORMAT_D32_SFLOAT;
|
||||
guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
|
||||
bytes = 4;
|
||||
break;
|
||||
default: DepthFatal("unsupported depth format");
|
||||
const auto* policy = FindDepthFormatPolicy(z.z_info.format);
|
||||
if (policy == nullptr) {
|
||||
DepthFatal("unsupported depth/stencil format pair");
|
||||
}
|
||||
const auto pitch = TileGetTexturePitch(guest_format, width, 1,
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
const auto ideal_format = DepthAttachmentFormat(*policy, has_stencil);
|
||||
r->format =
|
||||
ResolveHostDepthAttachmentFormat(g_render_ctx->GetGraphicCtx(), *policy, has_stencil);
|
||||
if (r->format == VK_FORMAT_UNDEFINED) {
|
||||
DepthFatal("no host depth/stencil format supports required usage for %s",
|
||||
string_VkFormat(ideal_format));
|
||||
}
|
||||
const uint32_t guest_format = Prospero::GpuEnumValue(policy->guest_format);
|
||||
const uint32_t bytes = policy->bytes_per_element;
|
||||
const auto pitch = TileGetTexturePitch(guest_format, width, 1,
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
if (z.pitch_height_valid && ((static_cast<uint64_t>(z.pitch_div8_minus1) + 1u) * 8u != pitch ||
|
||||
(static_cast<uint64_t>(z.height_div8_minus1) + 1u) * 8u !=
|
||||
((static_cast<uint64_t>(height) + 7u) & ~7ull))) {
|
||||
|
||||
@@ -276,18 +276,6 @@ ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource,
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSupportedSampledDepthFormat(VkFormat image_format, uint32_t guest_format,
|
||||
VkFormat view_format) {
|
||||
const bool d16 = image_format == VK_FORMAT_D16_UNORM &&
|
||||
guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
|
||||
view_format == VK_FORMAT_R16_UNORM;
|
||||
const bool d32 =
|
||||
(image_format == VK_FORMAT_D32_SFLOAT || image_format == VK_FORMAT_D32_SFLOAT_S8_UINT) &&
|
||||
guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
|
||||
view_format == VK_FORMAT_R32_SFLOAT;
|
||||
return d16 || d32;
|
||||
}
|
||||
|
||||
bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor,
|
||||
const VulkanImage& image) {
|
||||
const auto width = static_cast<uint32_t>(descriptor.Width5()) + 1u;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/host_gpu/regionDefinitions.h"
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -91,6 +92,139 @@ struct DepthTargetInfo {
|
||||
bool stencil_htile_compressed = false;
|
||||
};
|
||||
|
||||
struct DepthFormatPolicy {
|
||||
Prospero::DepthFormat depth_format;
|
||||
Prospero::BufferFormat guest_format;
|
||||
uint32_t bytes_per_element;
|
||||
VkFormat sampled_view_format;
|
||||
VkFormat depth_attachment_format;
|
||||
std::array<VkFormat, 3> stencil_attachment_formats;
|
||||
};
|
||||
|
||||
inline constexpr std::array<DepthFormatPolicy, 2> DEPTH_FORMAT_POLICIES {{
|
||||
{Prospero::DepthFormat::kZ16,
|
||||
Prospero::BufferFormat::k16UNorm,
|
||||
2,
|
||||
VK_FORMAT_R16_UNORM,
|
||||
VK_FORMAT_D16_UNORM,
|
||||
{VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}},
|
||||
{Prospero::DepthFormat::kZ32F,
|
||||
Prospero::BufferFormat::k32Float,
|
||||
4,
|
||||
VK_FORMAT_R32_SFLOAT,
|
||||
VK_FORMAT_D32_SFLOAT,
|
||||
{VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED}},
|
||||
}};
|
||||
|
||||
[[nodiscard]] inline constexpr const DepthFormatPolicy*
|
||||
FindDepthFormatPolicy(uint32_t depth_format) noexcept {
|
||||
for (const auto& policy: DEPTH_FORMAT_POLICIES) {
|
||||
if (Prospero::GpuEnumValue(policy.depth_format) == depth_format) {
|
||||
return &policy;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr const DepthFormatPolicy*
|
||||
FindGuestDepthFormatPolicy(uint32_t guest_format) noexcept {
|
||||
for (const auto& policy: DEPTH_FORMAT_POLICIES) {
|
||||
if (Prospero::GpuEnumValue(policy.guest_format) == guest_format) {
|
||||
return &policy;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr bool IsStencilAttachmentFormat(const DepthFormatPolicy& policy,
|
||||
VkFormat format) noexcept {
|
||||
for (const auto candidate: policy.stencil_attachment_formats) {
|
||||
if (candidate != VK_FORMAT_UNDEFINED && candidate == format) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(const DepthFormatPolicy& policy,
|
||||
bool has_stencil) noexcept {
|
||||
return has_stencil ? policy.stencil_attachment_formats.front() : policy.depth_attachment_format;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(uint32_t depth_format,
|
||||
uint32_t stencil_format) noexcept {
|
||||
bool has_stencil = false;
|
||||
switch (static_cast<Prospero::StencilFormat>(stencil_format)) {
|
||||
case Prospero::StencilFormat::kInvalid: break;
|
||||
case Prospero::StencilFormat::k8UInt: has_stencil = true; break;
|
||||
default: return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
const auto* policy = FindDepthFormatPolicy(depth_format);
|
||||
return policy == nullptr ? VK_FORMAT_UNDEFINED : DepthAttachmentFormat(*policy, has_stencil);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr VkImageUsageFlags DepthTargetImageUsage() noexcept {
|
||||
return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr VkFormat DepthAspectTransferFormat(VkFormat format) noexcept {
|
||||
switch (format) {
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT: return VK_FORMAT_D16_UNORM;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT;
|
||||
default: return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr uint32_t DepthAspectTransferBytes(VkFormat format) noexcept {
|
||||
switch (DepthAspectTransferFormat(format)) {
|
||||
case VK_FORMAT_D16_UNORM: return 2;
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT: return 4;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr uint32_t EncodeD16AsD24(uint16_t value) noexcept {
|
||||
// Preserve the guest UNORM value when widening 16 bits to the 24-bit transfer plane.
|
||||
return static_cast<uint32_t>((static_cast<uint64_t>(value) * 0x00ffffffu + 0x7fffu) / 0xffffu);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uint32_t EncodeD16AsD32(uint16_t value) noexcept {
|
||||
return std::bit_cast<uint32_t>(static_cast<float>(value) / 65535.0f);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(VkFormat image_format,
|
||||
uint32_t guest_format,
|
||||
VkFormat 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(VkFormat image_format,
|
||||
VkFormat view_format) noexcept {
|
||||
for (const auto& policy: DEPTH_FORMAT_POLICIES) {
|
||||
if (IsSupportedSampledDepthFormat(image_format, Prospero::GpuEnumValue(policy.guest_format),
|
||||
view_format)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr bool IsSupportedDepthTargetFormat(const DepthTargetInfo& info) {
|
||||
const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0;
|
||||
const auto* policy = FindGuestDepthFormatPolicy(info.guest_format);
|
||||
return policy != nullptr && info.bytes_per_element == policy->bytes_per_element &&
|
||||
(has_stencil ? IsStencilAttachmentFormat(*policy, info.format)
|
||||
: info.format == policy->depth_attachment_format);
|
||||
}
|
||||
|
||||
enum class VideoOutCompression : uint8_t { Uncompressed, Dcc256_64_64, Unsupported };
|
||||
|
||||
struct VideoOutInfo {
|
||||
@@ -205,13 +339,13 @@ SelectStorageSampledViewShape(uint32_t type, uint32_t depth, uint32_t backing_la
|
||||
switch (static_cast<Prospero::ImageType>(type)) {
|
||||
case Prospero::ImageType::kColor2D:
|
||||
return depth == 1 && backing_layers == 1 ? StorageSampledViewShape::Image2D
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
case Prospero::ImageType::kColor2DArray:
|
||||
return depth != 0 && depth == backing_layers ? StorageSampledViewShape::Image2DArray
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
case Prospero::ImageType::kColor3D:
|
||||
return depth != 0 && backing_layers == 1 ? StorageSampledViewShape::Image3D
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
: StorageSampledViewShape::Unsupported;
|
||||
default: return StorageSampledViewShape::Unsupported;
|
||||
}
|
||||
}
|
||||
@@ -443,12 +577,12 @@ ClassifyBufferImageWrite(uint64_t buffer_address, uint64_t buffer_size, uint64_t
|
||||
return BufferImageWrite::None;
|
||||
}
|
||||
const bool exact = buffer_address == image_address && buffer_size == image_size;
|
||||
const auto offset = buffer_address >= image_address ? buffer_address - image_address : UINT64_MAX;
|
||||
const auto offset =
|
||||
buffer_address >= image_address ? buffer_address - image_address : UINT64_MAX;
|
||||
const bool contained = offset <= image_size && buffer_size <= image_size - offset;
|
||||
const bool buffer_page_aligned =
|
||||
((buffer_address | buffer_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
||||
const bool image_page_aligned =
|
||||
((image_address | image_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
||||
const bool image_page_aligned = ((image_address | image_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
||||
switch (binding) {
|
||||
case BufferImageBinding::Texture:
|
||||
return contained && image_page_aligned && !image_gpu_modified
|
||||
|
||||
@@ -3,21 +3,22 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/renderer/imageInfo.h"
|
||||
#include "graphics/shader/recompiler/ShaderIR.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
[[nodiscard]] inline bool IsSupportedStorageSwizzle(uint32_t format, uint32_t swizzle) noexcept {
|
||||
const bool single_channel = format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
|
||||
const bool single_channel =
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
|
||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
|
||||
return swizzle == DstSel(4, 5, 6, 7) ||
|
||||
(single_channel &&
|
||||
(swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
|
||||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
|
||||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UNorm) &&
|
||||
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
|
||||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32_32_32Float) &&
|
||||
@@ -91,11 +92,7 @@ namespace Libs::Graphics {
|
||||
|
||||
[[nodiscard]] inline int SelectSampledDepthView(VkFormat image_format, VkFormat view_format,
|
||||
uint32_t swizzle) noexcept {
|
||||
const bool d16 = image_format == VK_FORMAT_D16_UNORM && view_format == VK_FORMAT_R16_UNORM;
|
||||
const bool d32 =
|
||||
(image_format == VK_FORMAT_D32_SFLOAT || image_format == VK_FORMAT_D32_SFLOAT_S8_UINT) &&
|
||||
view_format == VK_FORMAT_R32_SFLOAT;
|
||||
if (d16 || d32) {
|
||||
if (IsSupportedSampledDepthFormat(image_format, view_format)) {
|
||||
switch (swizzle) {
|
||||
case DstSel(4, 4, 4, 4): return VulkanImage::VIEW_DEPTH_TEXTURE;
|
||||
case DstSel(4, 0, 0, 0): return VulkanImage::VIEW_R000;
|
||||
@@ -117,12 +114,10 @@ IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resou
|
||||
|
||||
[[nodiscard]] inline int SelectStorageColorView(VkFormat image_format, VkFormat view_format,
|
||||
uint32_t swizzle) noexcept {
|
||||
const bool single_channel = view_format == VK_FORMAT_R8_UNORM ||
|
||||
view_format == VK_FORMAT_R8_UINT ||
|
||||
view_format == VK_FORMAT_R16_UINT ||
|
||||
view_format == VK_FORMAT_R32_UINT ||
|
||||
view_format == VK_FORMAT_R16_SFLOAT ||
|
||||
view_format == VK_FORMAT_R32_SFLOAT;
|
||||
const bool single_channel =
|
||||
view_format == VK_FORMAT_R8_UNORM || view_format == VK_FORMAT_R8_UINT ||
|
||||
view_format == VK_FORMAT_R16_UINT || view_format == VK_FORMAT_R32_UINT ||
|
||||
view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT;
|
||||
const bool swizzle_ok =
|
||||
swizzle == DstSel(4, 5, 6, 7) ||
|
||||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "graphics/host_gpu/objects/label.h"
|
||||
#include "graphics/host_gpu/renderer/descriptorCache.h"
|
||||
#include "graphics/host_gpu/renderer/framebufferCache.h"
|
||||
#include "graphics/host_gpu/renderer/imageInfo.h"
|
||||
#include "graphics/host_gpu/renderer/pipelineCache.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
@@ -59,22 +60,19 @@ bool ResolveHtileClearTarget(const HW::DepthRenderTarget& z, uint64_t descriptor
|
||||
*resolved = {};
|
||||
const bool has_stencil =
|
||||
z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid);
|
||||
const bool depth_format_supported =
|
||||
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16) ||
|
||||
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F);
|
||||
const bool msaa_compat = depth_msaa_single_sample_compatible(z.z_info.num_samples);
|
||||
const bool supported_depth_state =
|
||||
z.z_info.tile_surface_enable && depth_format_supported &&
|
||||
!(z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16) && has_stencil) &&
|
||||
z.z_info.tile_mode_index == 0 && (z.z_info.num_samples == 0 || msaa_compat) &&
|
||||
z.z_info.zrange_precision <= 1 && !z.z_info.expclear_enabled &&
|
||||
!z.z_info.embedded_sample_locations && !z.z_info.partially_resident &&
|
||||
z.z_info.num_mip_levels == 0 && z.z_info.plane_compression == 0 &&
|
||||
z.depth_view.current_mip_level == 0 && z.depth_view.slice_start == 0 &&
|
||||
z.depth_view.slice_max == 0 && z.depth_info.addr5_swizzle_mask == 0 &&
|
||||
z.depth_info.array_mode == 0 && z.depth_info.pipe_config == 0 &&
|
||||
z.depth_info.bank_width == 0 && z.depth_info.bank_height == 0 &&
|
||||
z.depth_info.macro_tile_aspect == 0 && z.depth_info.num_banks == 0;
|
||||
const auto* depth_policy = FindDepthFormatPolicy(z.z_info.format);
|
||||
const bool msaa_compat = depth_msaa_single_sample_compatible(z.z_info.num_samples);
|
||||
const bool supported_depth_state =
|
||||
z.z_info.tile_surface_enable && depth_policy != nullptr && z.z_info.tile_mode_index == 0 &&
|
||||
(z.z_info.num_samples == 0 || msaa_compat) && z.z_info.zrange_precision <= 1 &&
|
||||
!z.z_info.expclear_enabled && !z.z_info.embedded_sample_locations &&
|
||||
!z.z_info.partially_resident && z.z_info.num_mip_levels == 0 &&
|
||||
z.z_info.plane_compression == 0 && z.depth_view.current_mip_level == 0 &&
|
||||
z.depth_view.slice_start == 0 && z.depth_view.slice_max == 0 &&
|
||||
z.depth_info.addr5_swizzle_mask == 0 && z.depth_info.array_mode == 0 &&
|
||||
z.depth_info.pipe_config == 0 && z.depth_info.bank_width == 0 &&
|
||||
z.depth_info.bank_height == 0 && z.depth_info.macro_tile_aspect == 0 &&
|
||||
z.depth_info.num_banks == 0;
|
||||
const bool supported_stencil_state =
|
||||
z.stencil_info.tile_mode_index == 0 && z.stencil_info.tile_split == 0 &&
|
||||
!z.stencil_info.expclear_enabled &&
|
||||
@@ -138,10 +136,8 @@ bool ResolveHtileClearTarget(const HW::DepthRenderTarget& z, uint64_t descriptor
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool z16 = z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16);
|
||||
const uint32_t guest_format = Prospero::GpuEnumValue(z16 ? Prospero::BufferFormat::k16UNorm
|
||||
: Prospero::BufferFormat::k32Float);
|
||||
const uint32_t bytes = z16 ? 2u : 4u;
|
||||
const uint32_t guest_format = Prospero::GpuEnumValue(depth_policy->guest_format);
|
||||
const uint32_t bytes = depth_policy->bytes_per_element;
|
||||
const uint32_t pitch = TileGetTexturePitch(guest_format, width, 1,
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
if (z.pitch_height_valid && ((static_cast<uint64_t>(z.pitch_div8_minus1) + 1u) * 8u != pitch ||
|
||||
@@ -149,7 +145,7 @@ bool ResolveHtileClearTarget(const HW::DepthRenderTarget& z, uint64_t descriptor
|
||||
((static_cast<uint64_t>(height) + 7u) & ~7ull))) {
|
||||
return false;
|
||||
}
|
||||
const uint32_t block_width = z16 ? 256u : 128u;
|
||||
const uint32_t block_width = bytes == 2 ? 256u : 128u;
|
||||
const uint64_t padded_width =
|
||||
(static_cast<uint64_t>(pitch) + block_width - 1u) & ~(block_width - 1u);
|
||||
const uint64_t padded_height = (static_cast<uint64_t>(height) + 127u) & ~127ull;
|
||||
|
||||
@@ -1109,10 +1109,9 @@ DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTarge
|
||||
create.format = info.format;
|
||||
create.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
create.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
create.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
create.usage = DepthTargetImageUsage();
|
||||
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
create.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
VkImageFormatProperties properties {};
|
||||
if (vkGetPhysicalDeviceImageFormatProperties(ctx->physical_device, info.format,
|
||||
VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
||||
@@ -2299,12 +2298,7 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
||||
(has_stencil && PageOverlaps(info.stencil_address, info.stencil_size, info.htile_address,
|
||||
info.htile_size)))) ||
|
||||
(info.stencil_htile_compressed && (!has_stencil || !has_htile)) ||
|
||||
!(info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm)
|
||||
? !has_stencil && info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2
|
||||
: info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
|
||||
info.bytes_per_element == 4 &&
|
||||
info.format ==
|
||||
(has_stencil ? VK_FORMAT_D32_SFLOAT_S8_UINT : VK_FORMAT_D32_SFLOAT))) {
|
||||
!IsSupportedDepthTargetFormat(info)) {
|
||||
EXIT("TextureCache: unsupported depth target, command=%p ctx=%p depth=0x%016" PRIx64
|
||||
"+0x%016" PRIx64 " stencil=0x%016" PRIx64 "+0x%016" PRIx64 " htile=0x%016" PRIx64
|
||||
"+0x%016" PRIx64 " extent=%ux%u pitch=%u tile=%u format=%d guest_format=%u bpe=%u\n",
|
||||
@@ -2449,8 +2443,14 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
||||
}
|
||||
RequireRetirementIsolation(retire, "depth target", info.address, info.size);
|
||||
RetireImages(retire, native_depth_source.get());
|
||||
if (!CanLoadStencilAttachment(info, native_depth_source != nullptr &&
|
||||
native_depth_source->stencil_initialized)) {
|
||||
const bool coherent_guest_stencil =
|
||||
has_stencil &&
|
||||
IsCoherentGuestImageSource(stencil_source, info.stencil_address, info.stencil_size);
|
||||
// Native expansion must preserve old layers. Guest data initializes only a wholly new image.
|
||||
const bool stencil_contents_available = native_depth_source != nullptr
|
||||
? native_depth_source->stencil_initialized
|
||||
: coherent_guest_stencil;
|
||||
if (!CanLoadStencilAttachment(info, stencil_contents_available)) {
|
||||
EXIT("TextureCache: new stencil target requires a clear before stencil access, "
|
||||
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
||||
info.stencil_address, info.stencil_size);
|
||||
|
||||
@@ -12,6 +12,46 @@
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
template <uint32_t (*Encode)(uint16_t)>
|
||||
static void UploadPromotedD16Depth(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
uint32_t base_layer) {
|
||||
const uint64_t slice_size = info.size / info.layers;
|
||||
const uint64_t texels = static_cast<uint64_t>(info.pitch) * info.height;
|
||||
const uint64_t host_slice_size = texels * sizeof(uint32_t);
|
||||
const uint64_t host_upload_size = host_slice_size * info.layers;
|
||||
if (slice_size % sizeof(uint16_t) != 0 || texels > slice_size / sizeof(uint16_t) ||
|
||||
host_upload_size > UINT32_MAX) {
|
||||
EXIT("Tiler: invalid D16 host-promotion footprint, guest_slice=0x%016" PRIx64
|
||||
" host_slice=0x%016" PRIx64 " layers=%u\n",
|
||||
slice_size, host_slice_size, info.layers);
|
||||
}
|
||||
UtilScratchBuffer host_linear(host_upload_size);
|
||||
std::vector<uint16_t> guest_linear(slice_size / sizeof(uint16_t));
|
||||
std::vector<BufferImageCopy> regions;
|
||||
regions.reserve(info.layers);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
|
||||
TileConvertTiledToLinearDepth(guest_linear.data(), guest_slice, info.guest_format,
|
||||
info.width, info.height, info.pitch, slice_size);
|
||||
auto* host_slice = reinterpret_cast<uint32_t*>(static_cast<uint8_t*>(host_linear.Data()) +
|
||||
host_slice_size * layer);
|
||||
for (uint64_t texel = 0; texel < texels; texel++) {
|
||||
host_slice[texel] = Encode(guest_linear[texel]);
|
||||
}
|
||||
BufferImageCopy region {};
|
||||
region.offset = static_cast<uint32_t>(host_slice_size * layer);
|
||||
region.pitch = info.pitch;
|
||||
region.width = info.width;
|
||||
region.height = info.height;
|
||||
region.dst_layer = base_layer + layer;
|
||||
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
regions.push_back(region);
|
||||
}
|
||||
UtilFillImage(ctx, image, host_linear.Data(), host_upload_size, regions,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
|
||||
const BufferImageCopySource& source, bool refresh, bool storage) const {
|
||||
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
||||
@@ -53,19 +93,13 @@ void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const
|
||||
void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
bool refresh, uint32_t base_layer) const {
|
||||
const bool d16 =
|
||||
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
|
||||
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2;
|
||||
const bool d32 =
|
||||
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
|
||||
(info.format == VK_FORMAT_D32_SFLOAT || info.format == VK_FORMAT_D32_SFLOAT_S8_UINT) &&
|
||||
info.bytes_per_element == 4;
|
||||
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
||||
info.width == 0 || info.height == 0 || info.pitch < info.width || info.layers == 0 ||
|
||||
info.size % info.layers != 0 || base_layer > image->layers ||
|
||||
info.layers > image->layers - base_layer || info.size > UINT32_MAX ||
|
||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || (!d16 && !d32) ||
|
||||
!source.cpu_current || source.address != info.address || source.size != info.size ||
|
||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
||||
!IsSupportedDepthTargetFormat(info) || !source.cpu_current ||
|
||||
source.address != info.address || source.size != info.size ||
|
||||
(source.buffer == nullptr && source.offset != 0)) {
|
||||
EXIT("Tiler: unsupported depth detile, ctx=%p image=%p source_buffer=%p "
|
||||
"source=0x%016" PRIx64 "+0x%016" PRIx64 " offset=0x%016" PRIx64
|
||||
@@ -80,6 +114,19 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
if (refresh) {
|
||||
VulkanDeviceWaitIdle(ctx);
|
||||
}
|
||||
if (DepthAspectTransferBytes(info.format) != info.bytes_per_element) {
|
||||
switch (info.format) {
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
UploadPromotedD16Depth<EncodeD16AsD24>(ctx, image, info, source, base_layer);
|
||||
return;
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
UploadPromotedD16Depth<EncodeD16AsD32>(ctx, image, info, source, base_layer);
|
||||
return;
|
||||
default:
|
||||
EXIT("Tiler: unsupported depth transfer conversion, format=%d guest_bpe=%u\n",
|
||||
static_cast<int>(info.format), info.bytes_per_element);
|
||||
}
|
||||
}
|
||||
const auto slice_size = info.size / info.layers;
|
||||
UtilScratchBuffer linear(info.size);
|
||||
std::vector<BufferImageCopy> regions;
|
||||
@@ -109,11 +156,12 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
TileSizeAlign htile_size {};
|
||||
TileSizeAlign depth_size {};
|
||||
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
|
||||
const auto* policy = FindGuestDepthFormatPolicy(info.guest_format);
|
||||
const auto stencil_pitch = TileGetTexturePitch(
|
||||
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
const bool supported_layout =
|
||||
TileGetDepthSize(info.width, info.height, 0,
|
||||
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
||||
policy != nullptr && IsSupportedDepthTargetFormat(info) &&
|
||||
TileGetDepthSize(info.width, info.height, 0, Prospero::GpuEnumValue(policy->depth_format),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
||||
info.htile_address != 0, &stencil_size, &htile_size, &depth_size) &&
|
||||
info.layers != 0 && info.stencil_size % info.layers == 0 &&
|
||||
@@ -121,9 +169,7 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
stencil_pitch != 0;
|
||||
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
||||
info.stencil_address == 0 || info.stencil_size == 0 || info.width == 0 ||
|
||||
info.height == 0 || info.format != VK_FORMAT_D32_SFLOAT_S8_UINT ||
|
||||
info.guest_format != Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) ||
|
||||
info.bytes_per_element != 4 || base_layer > image->layers ||
|
||||
info.height == 0 || base_layer > image->layers ||
|
||||
info.layers > image->layers - base_layer || info.stencil_size > UINT32_MAX ||
|
||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
||||
info.stencil_htile_compressed || !supported_layout || !source.cpu_current ||
|
||||
@@ -187,11 +233,7 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
|
||||
}
|
||||
|
||||
void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) const {
|
||||
const bool supported_format =
|
||||
(info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
|
||||
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2) ||
|
||||
(info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
|
||||
info.format == VK_FORMAT_D32_SFLOAT && info.bytes_per_element == 4);
|
||||
const bool supported_format = IsSupportedDepthTargetFormat(info);
|
||||
if (dst == nullptr || src == nullptr || info.address == 0 || info.size == 0 ||
|
||||
info.stencil_address != 0 || info.stencil_size != 0 || info.width == 0 ||
|
||||
info.height == 0 || info.pitch < info.width ||
|
||||
|
||||
@@ -8710,8 +8710,8 @@ bool CacheFault(void *opaque, PageFaultAccess access, uint64_t vaddr,
|
||||
VK_FORMAT_A2R10G10B10_UNORM_PACK32,
|
||||
DstSel(6, 5, 4, 7));
|
||||
} else if (std::strcmp(kind, "sampled-depth-format") == 0) {
|
||||
(void)SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_R16_UNORM, DstSel(4, 4, 4, 4));
|
||||
(void)SelectSampledDepthView(VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
VK_FORMAT_R32_SFLOAT, DstSel(4, 4, 4, 4));
|
||||
} else if (std::strcmp(kind, "sampled-depth-swizzle") == 0) {
|
||||
(void)SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_R32_SFLOAT, DstSel(4, 5, 6, 7));
|
||||
@@ -8806,6 +8806,21 @@ void CheckSampledColorViews() {
|
||||
DstSel(4, 0, 0, 0)) ==
|
||||
VulkanImage::VIEW_R000,
|
||||
"D16 depth target did not select its R000 depth-aspect view");
|
||||
Require("SampledColorViews", "D16S8 R001 depth target",
|
||||
SelectSampledDepthView(VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_R16_UNORM,
|
||||
DstSel(4, 0, 0, 1)) ==
|
||||
VulkanImage::VIEW_R001,
|
||||
"D16S8 depth target did not select its R001 depth-aspect view");
|
||||
Require("SampledColorViews", "promoted D24S8 R001 depth target",
|
||||
SelectSampledDepthView(VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_R16_UNORM,
|
||||
DstSel(4, 0, 0, 1)) ==
|
||||
VulkanImage::VIEW_R001,
|
||||
"D24S8 host fallback did not preserve the guest R16 depth view");
|
||||
Require("SampledColorViews", "promoted D32S8 R001 depth target",
|
||||
SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_R16_UNORM,
|
||||
DstSel(4, 0, 0, 1)) ==
|
||||
VulkanImage::VIEW_R001,
|
||||
"D32S8 host fallback did not preserve the guest R16 depth view");
|
||||
Require("SampledColorViews", "D32S8 R001 depth target",
|
||||
SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_R32_SFLOAT,
|
||||
@@ -11094,20 +11109,38 @@ void CheckImageOverlapResolution() {
|
||||
mismatched_depth) ==
|
||||
DepthOverlap::Unsupported,
|
||||
"mipmapped or format-mismatched depth load was admitted");
|
||||
Require("ImageOverlapResolution", "depth transition source",
|
||||
SelectDepthTransitionSource(true, true, false, false, false, true) ==
|
||||
DepthTransitionSource::None &&
|
||||
SelectDepthTransitionSource(false, true, false, false, false, true) ==
|
||||
DepthTransitionSource::Native &&
|
||||
SelectDepthTransitionSource(false, false, false, false, false, false) ==
|
||||
DepthTransitionSource::Guest &&
|
||||
SelectDepthTransitionSource(false, true, true, false, false, false) ==
|
||||
DepthTransitionSource::Guest &&
|
||||
SelectDepthTransitionSource(false, true, false, true, false, false) ==
|
||||
DepthTransitionSource::Guest &&
|
||||
SelectDepthTransitionSource(false, true, false, false, true, true) ==
|
||||
DepthTransitionSource::Guest,
|
||||
"clear, clean-native, or overlapping dirty-buffer depth preservation policy regressed");
|
||||
struct DepthTransitionCase {
|
||||
const char *name;
|
||||
bool clear;
|
||||
bool native;
|
||||
bool sampled_cpu_dirty;
|
||||
bool sampled_buffer_modified;
|
||||
bool buffer_overlap;
|
||||
bool buffer_cpu_dirty;
|
||||
DepthTransitionSource expected;
|
||||
};
|
||||
constexpr DepthTransitionCase transition_cases[] = {
|
||||
{"clear", true, true, false, false, false, true,
|
||||
DepthTransitionSource::None},
|
||||
{"clean native", false, true, false, false, false, true,
|
||||
DepthTransitionSource::Native},
|
||||
{"missing native", false, false, false, false, false, false,
|
||||
DepthTransitionSource::Guest},
|
||||
{"CPU-dirty native", false, true, true, false, false, false,
|
||||
DepthTransitionSource::Guest},
|
||||
{"buffer-modified native", false, true, false, true, false, false,
|
||||
DepthTransitionSource::Guest},
|
||||
{"dirty overlapping buffer", false, true, false, false, true, true,
|
||||
DepthTransitionSource::Guest},
|
||||
};
|
||||
for (const auto &test : transition_cases) {
|
||||
Require("ImageOverlapResolution", test.name,
|
||||
SelectDepthTransitionSource(
|
||||
test.clear, test.native, test.sampled_cpu_dirty,
|
||||
test.sampled_buffer_modified, test.buffer_overlap,
|
||||
test.buffer_cpu_dirty) == test.expected,
|
||||
"depth preservation source changed");
|
||||
}
|
||||
depth.depth_load_clear = true;
|
||||
depth.stencil_address = sampled.address + 0x6000;
|
||||
depth.stencil_size = 0x2000;
|
||||
@@ -11136,6 +11169,7 @@ void CheckImageOverlapResolution() {
|
||||
Require("ImageOverlapResolution", "stencil clear initializes",
|
||||
CanLoadStencilAttachment(depth, false),
|
||||
"stencil clear did not initialize the attachment");
|
||||
depth.stencil_load_clear = false;
|
||||
depth.stencil_htile_compressed = false;
|
||||
Require("ImageOverlapResolution", "raw stencil load",
|
||||
CanLoadRawStencilPlane(depth),
|
||||
@@ -11253,6 +11287,122 @@ void CheckDepthTargetFootprints() {
|
||||
TileSizeAlign stencil{};
|
||||
TileSizeAlign htile{};
|
||||
TileSizeAlign depth{};
|
||||
struct AttachmentFormatCase {
|
||||
const char *name;
|
||||
uint32_t depth_format;
|
||||
uint32_t stencil_format;
|
||||
VkFormat expected;
|
||||
};
|
||||
constexpr AttachmentFormatCase attachment_cases[] = {
|
||||
{"Z16", Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid),
|
||||
VK_FORMAT_D16_UNORM},
|
||||
{"Z16S8", Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
||||
VK_FORMAT_D16_UNORM_S8_UINT},
|
||||
{"Z32", Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid),
|
||||
VK_FORMAT_D32_SFLOAT},
|
||||
{"Z32S8", Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT},
|
||||
{"invalid depth", 2,
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
||||
VK_FORMAT_UNDEFINED},
|
||||
{"invalid stencil", Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16),
|
||||
2, VK_FORMAT_UNDEFINED},
|
||||
};
|
||||
for (const auto &test : attachment_cases) {
|
||||
Require("DepthTargetFootprints", test.name,
|
||||
DepthAttachmentFormat(test.depth_format, test.stencil_format) ==
|
||||
test.expected,
|
||||
"PS5 depth/stencil attachment mapping changed");
|
||||
}
|
||||
Require("DepthTargetFootprints", "1920x1080 Z16S8 without HTile",
|
||||
TileGetDepthSize(1920, 1080, 0,
|
||||
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt), false,
|
||||
&stencil, &htile, &depth) &&
|
||||
depth.size == 0x480000 && depth.align == 0x10000 &&
|
||||
stencil.size == 0x280000 && stencil.align == 0x10000 && htile.size == 0,
|
||||
"captured Z16S8 footprint disagrees with Prospero block rules");
|
||||
struct TargetFormatCase {
|
||||
const char *name;
|
||||
VkFormat host_format;
|
||||
uint32_t guest_format;
|
||||
uint32_t bytes_per_element;
|
||||
bool stencil;
|
||||
bool supported;
|
||||
};
|
||||
constexpr TargetFormatCase target_cases[] = {
|
||||
{"D16", VK_FORMAT_D16_UNORM,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, false, true},
|
||||
{"D16S8", VK_FORMAT_D16_UNORM_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, true, true},
|
||||
{"D16 via D24S8", VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, true, true},
|
||||
{"D16 via D32S8", VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, true, true},
|
||||
{"D32", VK_FORMAT_D32_SFLOAT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 4, false, true},
|
||||
{"D32S8", VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 4, true, true},
|
||||
{"D16 plus stencil mismatch", VK_FORMAT_D16_UNORM,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, true, false},
|
||||
{"fallback without stencil", VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 2, false, false},
|
||||
{"D32 guest via D24", VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 4, true, false},
|
||||
{"D16 byte mismatch", VK_FORMAT_D16_UNORM,
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm), 4, false, false},
|
||||
};
|
||||
for (const auto &test : target_cases) {
|
||||
DepthTargetInfo target{};
|
||||
target.format = test.host_format;
|
||||
target.guest_format = test.guest_format;
|
||||
target.bytes_per_element = test.bytes_per_element;
|
||||
target.stencil_address = test.stencil ? 0x10000 : 0;
|
||||
target.stencil_size = test.stencil ? 0x10000 : 0;
|
||||
Require("DepthTargetFootprints", test.name,
|
||||
IsSupportedDepthTargetFormat(target) == test.supported,
|
||||
"host/guest depth format policy changed");
|
||||
}
|
||||
struct TransferPlaneCase {
|
||||
const char *name;
|
||||
VkFormat attachment;
|
||||
VkFormat transfer;
|
||||
uint32_t bytes;
|
||||
};
|
||||
constexpr TransferPlaneCase transfer_cases[] = {
|
||||
{"D16S8 transfer", VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM, 2},
|
||||
{"D24S8 transfer", VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
VK_FORMAT_X8_D24_UNORM_PACK32, 4},
|
||||
{"D32S8 transfer", VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, 4},
|
||||
{"invalid transfer", VK_FORMAT_R16_UNORM, VK_FORMAT_UNDEFINED, 0},
|
||||
};
|
||||
for (const auto &test : transfer_cases) {
|
||||
Require("DepthTargetFootprints", test.name,
|
||||
DepthAspectTransferFormat(test.attachment) == test.transfer &&
|
||||
DepthAspectTransferBytes(test.attachment) == test.bytes,
|
||||
"combined depth transfer-plane layout changed");
|
||||
}
|
||||
struct PromotionCase {
|
||||
const char *name;
|
||||
uint16_t source;
|
||||
uint32_t d24;
|
||||
uint32_t d32;
|
||||
};
|
||||
constexpr PromotionCase promotion_cases[] = {
|
||||
{"zero", 0, 0, 0},
|
||||
{"midpoint", 0x8000, 0x00800080, 0x3f000080},
|
||||
{"maximum", 0xffff, 0x00ffffff, 0x3f800000},
|
||||
};
|
||||
for (const auto &test : promotion_cases) {
|
||||
Require("DepthTargetFootprints", test.name,
|
||||
EncodeD16AsD24(test.source) == test.d24 &&
|
||||
EncodeD16AsD32(test.source) == test.d32,
|
||||
"D16 host promotion changed the represented depth value");
|
||||
}
|
||||
Require("DepthTargetFootprints", "640x360 Z32S8 without HTile",
|
||||
TileGetDepthSize(640, 360, 0, Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt), false,
|
||||
@@ -11396,6 +11546,18 @@ void CheckHtileClearTargetResolution() {
|
||||
resolved.address == derived_z16.htile_data_base_addr &&
|
||||
resolved.size == htile_size.size,
|
||||
"extent-derived Z16 depth-only HTile target was rejected");
|
||||
|
||||
auto derived_z16s8 = derived;
|
||||
derived_z16s8.z_info.format = Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16);
|
||||
Require("HtileClearTargetResolution", "derived Z16S8 target",
|
||||
TileGetDepthSize(960, 540, 0, derived_z16s8.z_info.format,
|
||||
derived_z16s8.stencil_info.format, true, &stencil_size,
|
||||
&htile_size, &depth_size) &&
|
||||
stencil_size.size != 0 && stencil_size.align == 0x10000 &&
|
||||
ResolveHtileClearTarget(derived_z16s8, htile_size.size, &resolved) &&
|
||||
resolved.address == derived_z16s8.htile_data_base_addr &&
|
||||
resolved.size == htile_size.size,
|
||||
"extent-derived Z16S8 HTile target was rejected");
|
||||
std::printf("[host] %-32s ok\n", "HtileClearTargetResolution");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user