D16S8 support

This commit is contained in:
nmzik committed 2026-07-17 08:39:57 +02:00
1 parent 13499502c9
commit dd58deae15
8 files changed
+469 -124

No files matched your search

+140 -6
View File
@@ -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