D16S8 support

This commit is contained in:
nmzik
2026-07-17 08:39:57 +02:00
parent 13499502c9
commit dd58deae15
8 changed files with 469 additions and 124 deletions
@@ -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))) {