mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
D16S8 support
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <mutex>
|
||||||
#include <vulkan/vk_enum_string_helper.h>
|
#include <vulkan/vk_enum_string_helper.h>
|
||||||
|
|
||||||
namespace Libs::Graphics {
|
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);
|
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)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,
|
void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,
|
||||||
RenderDepthInfo* r) {
|
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))) {
|
(z.pitch_div8_minus1 != 0 || z.height_div8_minus1 != 0 || z.slice_div64_minus1 != 0))) {
|
||||||
DepthFatal("inconsistent depth extent or encoded layout");
|
DepthFatal("inconsistent depth extent or encoded layout");
|
||||||
}
|
}
|
||||||
uint32_t guest_format = 0;
|
const auto* policy = FindDepthFormatPolicy(z.z_info.format);
|
||||||
uint32_t bytes = 0;
|
if (policy == nullptr) {
|
||||||
switch (static_cast<Prospero::DepthFormat>(z.z_info.format)) {
|
DepthFatal("unsupported depth/stencil format pair");
|
||||||
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 pitch = TileGetTexturePitch(guest_format, width, 1,
|
const auto ideal_format = DepthAttachmentFormat(*policy, has_stencil);
|
||||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
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 ||
|
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>(z.height_div8_minus1) + 1u) * 8u !=
|
||||||
((static_cast<uint64_t>(height) + 7u) & ~7ull))) {
|
((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,
|
bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor,
|
||||||
const VulkanImage& image) {
|
const VulkanImage& image) {
|
||||||
const auto width = static_cast<uint32_t>(descriptor.Width5()) + 1u;
|
const auto width = static_cast<uint32_t>(descriptor.Width5()) + 1u;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "graphics/guest_gpu/gpu_defs.h"
|
#include "graphics/guest_gpu/gpu_defs.h"
|
||||||
#include "graphics/host_gpu/regionDefinitions.h"
|
#include "graphics/host_gpu/regionDefinitions.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -91,6 +92,139 @@ struct DepthTargetInfo {
|
|||||||
bool stencil_htile_compressed = false;
|
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 };
|
enum class VideoOutCompression : uint8_t { Uncompressed, Dcc256_64_64, Unsupported };
|
||||||
|
|
||||||
struct VideoOutInfo {
|
struct VideoOutInfo {
|
||||||
@@ -205,13 +339,13 @@ SelectStorageSampledViewShape(uint32_t type, uint32_t depth, uint32_t backing_la
|
|||||||
switch (static_cast<Prospero::ImageType>(type)) {
|
switch (static_cast<Prospero::ImageType>(type)) {
|
||||||
case Prospero::ImageType::kColor2D:
|
case Prospero::ImageType::kColor2D:
|
||||||
return depth == 1 && backing_layers == 1 ? StorageSampledViewShape::Image2D
|
return depth == 1 && backing_layers == 1 ? StorageSampledViewShape::Image2D
|
||||||
: StorageSampledViewShape::Unsupported;
|
: StorageSampledViewShape::Unsupported;
|
||||||
case Prospero::ImageType::kColor2DArray:
|
case Prospero::ImageType::kColor2DArray:
|
||||||
return depth != 0 && depth == backing_layers ? StorageSampledViewShape::Image2DArray
|
return depth != 0 && depth == backing_layers ? StorageSampledViewShape::Image2DArray
|
||||||
: StorageSampledViewShape::Unsupported;
|
: StorageSampledViewShape::Unsupported;
|
||||||
case Prospero::ImageType::kColor3D:
|
case Prospero::ImageType::kColor3D:
|
||||||
return depth != 0 && backing_layers == 1 ? StorageSampledViewShape::Image3D
|
return depth != 0 && backing_layers == 1 ? StorageSampledViewShape::Image3D
|
||||||
: StorageSampledViewShape::Unsupported;
|
: StorageSampledViewShape::Unsupported;
|
||||||
default: return StorageSampledViewShape::Unsupported;
|
default: return StorageSampledViewShape::Unsupported;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,12 +577,12 @@ ClassifyBufferImageWrite(uint64_t buffer_address, uint64_t buffer_size, uint64_t
|
|||||||
return BufferImageWrite::None;
|
return BufferImageWrite::None;
|
||||||
}
|
}
|
||||||
const bool exact = buffer_address == image_address && buffer_size == image_size;
|
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 contained = offset <= image_size && buffer_size <= image_size - offset;
|
||||||
const bool buffer_page_aligned =
|
const bool buffer_page_aligned =
|
||||||
((buffer_address | buffer_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
((buffer_address | buffer_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
||||||
const bool image_page_aligned =
|
const bool image_page_aligned = ((image_address | image_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
||||||
((image_address | image_size) & (TRACKER_PAGE_SIZE - 1)) == 0;
|
|
||||||
switch (binding) {
|
switch (binding) {
|
||||||
case BufferImageBinding::Texture:
|
case BufferImageBinding::Texture:
|
||||||
return contained && image_page_aligned && !image_gpu_modified
|
return contained && image_page_aligned && !image_gpu_modified
|
||||||
|
|||||||
@@ -3,21 +3,22 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "graphics/host_gpu/graphicContext.h"
|
#include "graphics/host_gpu/graphicContext.h"
|
||||||
|
#include "graphics/host_gpu/renderer/imageInfo.h"
|
||||||
#include "graphics/shader/recompiler/ShaderIR.h"
|
#include "graphics/shader/recompiler/ShaderIR.h"
|
||||||
#include "graphics/shader/shader.h"
|
#include "graphics/shader/shader.h"
|
||||||
|
|
||||||
namespace Libs::Graphics {
|
namespace Libs::Graphics {
|
||||||
|
|
||||||
[[nodiscard]] inline bool IsSupportedStorageSwizzle(uint32_t format, uint32_t swizzle) noexcept {
|
[[nodiscard]] inline bool IsSupportedStorageSwizzle(uint32_t format, uint32_t swizzle) noexcept {
|
||||||
const bool single_channel = format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) ||
|
const bool single_channel =
|
||||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) ||
|
||||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
|
||||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
|
||||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
|
||||||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
|
||||||
|
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
|
||||||
return swizzle == DstSel(4, 5, 6, 7) ||
|
return swizzle == DstSel(4, 5, 6, 7) ||
|
||||||
(single_channel &&
|
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
|
||||||
(swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
|
|
||||||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UNorm) &&
|
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UNorm) &&
|
||||||
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
|
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
|
||||||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32_32_32Float) &&
|
(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,
|
[[nodiscard]] inline int SelectSampledDepthView(VkFormat image_format, VkFormat view_format,
|
||||||
uint32_t swizzle) noexcept {
|
uint32_t swizzle) noexcept {
|
||||||
const bool d16 = image_format == VK_FORMAT_D16_UNORM && view_format == VK_FORMAT_R16_UNORM;
|
if (IsSupportedSampledDepthFormat(image_format, view_format)) {
|
||||||
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) {
|
|
||||||
switch (swizzle) {
|
switch (swizzle) {
|
||||||
case DstSel(4, 4, 4, 4): return VulkanImage::VIEW_DEPTH_TEXTURE;
|
case DstSel(4, 4, 4, 4): return VulkanImage::VIEW_DEPTH_TEXTURE;
|
||||||
case DstSel(4, 0, 0, 0): return VulkanImage::VIEW_R000;
|
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,
|
[[nodiscard]] inline int SelectStorageColorView(VkFormat image_format, VkFormat view_format,
|
||||||
uint32_t swizzle) noexcept {
|
uint32_t swizzle) noexcept {
|
||||||
const bool single_channel = view_format == VK_FORMAT_R8_UNORM ||
|
const bool single_channel =
|
||||||
view_format == VK_FORMAT_R8_UINT ||
|
view_format == VK_FORMAT_R8_UNORM || view_format == VK_FORMAT_R8_UINT ||
|
||||||
view_format == VK_FORMAT_R16_UINT ||
|
view_format == VK_FORMAT_R16_UINT || view_format == VK_FORMAT_R32_UINT ||
|
||||||
view_format == VK_FORMAT_R32_UINT ||
|
view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT;
|
||||||
view_format == VK_FORMAT_R16_SFLOAT ||
|
|
||||||
view_format == VK_FORMAT_R32_SFLOAT;
|
|
||||||
const bool swizzle_ok =
|
const bool swizzle_ok =
|
||||||
swizzle == DstSel(4, 5, 6, 7) ||
|
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))) ||
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "graphics/host_gpu/objects/label.h"
|
#include "graphics/host_gpu/objects/label.h"
|
||||||
#include "graphics/host_gpu/renderer/descriptorCache.h"
|
#include "graphics/host_gpu/renderer/descriptorCache.h"
|
||||||
#include "graphics/host_gpu/renderer/framebufferCache.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/pipelineCache.h"
|
||||||
#include "graphics/host_gpu/renderer/render.h"
|
#include "graphics/host_gpu/renderer/render.h"
|
||||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||||
@@ -59,22 +60,19 @@ bool ResolveHtileClearTarget(const HW::DepthRenderTarget& z, uint64_t descriptor
|
|||||||
*resolved = {};
|
*resolved = {};
|
||||||
const bool has_stencil =
|
const bool has_stencil =
|
||||||
z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid);
|
z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid);
|
||||||
const bool depth_format_supported =
|
const auto* depth_policy = FindDepthFormatPolicy(z.z_info.format);
|
||||||
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16) ||
|
const bool msaa_compat = depth_msaa_single_sample_compatible(z.z_info.num_samples);
|
||||||
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F);
|
const bool supported_depth_state =
|
||||||
const bool msaa_compat = depth_msaa_single_sample_compatible(z.z_info.num_samples);
|
z.z_info.tile_surface_enable && depth_policy != nullptr && z.z_info.tile_mode_index == 0 &&
|
||||||
const bool supported_depth_state =
|
(z.z_info.num_samples == 0 || msaa_compat) && z.z_info.zrange_precision <= 1 &&
|
||||||
z.z_info.tile_surface_enable && depth_format_supported &&
|
!z.z_info.expclear_enabled && !z.z_info.embedded_sample_locations &&
|
||||||
!(z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16) && has_stencil) &&
|
!z.z_info.partially_resident && z.z_info.num_mip_levels == 0 &&
|
||||||
z.z_info.tile_mode_index == 0 && (z.z_info.num_samples == 0 || msaa_compat) &&
|
z.z_info.plane_compression == 0 && z.depth_view.current_mip_level == 0 &&
|
||||||
z.z_info.zrange_precision <= 1 && !z.z_info.expclear_enabled &&
|
z.depth_view.slice_start == 0 && z.depth_view.slice_max == 0 &&
|
||||||
!z.z_info.embedded_sample_locations && !z.z_info.partially_resident &&
|
z.depth_info.addr5_swizzle_mask == 0 && z.depth_info.array_mode == 0 &&
|
||||||
z.z_info.num_mip_levels == 0 && z.z_info.plane_compression == 0 &&
|
z.depth_info.pipe_config == 0 && z.depth_info.bank_width == 0 &&
|
||||||
z.depth_view.current_mip_level == 0 && z.depth_view.slice_start == 0 &&
|
z.depth_info.bank_height == 0 && z.depth_info.macro_tile_aspect == 0 &&
|
||||||
z.depth_view.slice_max == 0 && z.depth_info.addr5_swizzle_mask == 0 &&
|
z.depth_info.num_banks == 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 =
|
const bool supported_stencil_state =
|
||||||
z.stencil_info.tile_mode_index == 0 && z.stencil_info.tile_split == 0 &&
|
z.stencil_info.tile_mode_index == 0 && z.stencil_info.tile_split == 0 &&
|
||||||
!z.stencil_info.expclear_enabled &&
|
!z.stencil_info.expclear_enabled &&
|
||||||
@@ -138,10 +136,8 @@ bool ResolveHtileClearTarget(const HW::DepthRenderTarget& z, uint64_t descriptor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool z16 = z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16);
|
const uint32_t guest_format = Prospero::GpuEnumValue(depth_policy->guest_format);
|
||||||
const uint32_t guest_format = Prospero::GpuEnumValue(z16 ? Prospero::BufferFormat::k16UNorm
|
const uint32_t bytes = depth_policy->bytes_per_element;
|
||||||
: Prospero::BufferFormat::k32Float);
|
|
||||||
const uint32_t bytes = z16 ? 2u : 4u;
|
|
||||||
const uint32_t pitch = TileGetTexturePitch(guest_format, width, 1,
|
const uint32_t pitch = TileGetTexturePitch(guest_format, width, 1,
|
||||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||||
if (z.pitch_height_valid && ((static_cast<uint64_t>(z.pitch_div8_minus1) + 1u) * 8u != pitch ||
|
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))) {
|
((static_cast<uint64_t>(height) + 7u) & ~7ull))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint32_t block_width = z16 ? 256u : 128u;
|
const uint32_t block_width = bytes == 2 ? 256u : 128u;
|
||||||
const uint64_t padded_width =
|
const uint64_t padded_width =
|
||||||
(static_cast<uint64_t>(pitch) + block_width - 1u) & ~(block_width - 1u);
|
(static_cast<uint64_t>(pitch) + block_width - 1u) & ~(block_width - 1u);
|
||||||
const uint64_t padded_height = (static_cast<uint64_t>(height) + 127u) & ~127ull;
|
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.format = info.format;
|
||||||
create.tiling = VK_IMAGE_TILING_OPTIMAL;
|
create.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
create.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
create.usage = DepthTargetImageUsage();
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
create.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
create.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
VkImageFormatProperties properties {};
|
VkImageFormatProperties properties {};
|
||||||
if (vkGetPhysicalDeviceImageFormatProperties(ctx->physical_device, info.format,
|
if (vkGetPhysicalDeviceImageFormatProperties(ctx->physical_device, info.format,
|
||||||
VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
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,
|
(has_stencil && PageOverlaps(info.stencil_address, info.stencil_size, info.htile_address,
|
||||||
info.htile_size)))) ||
|
info.htile_size)))) ||
|
||||||
(info.stencil_htile_compressed && (!has_stencil || !has_htile)) ||
|
(info.stencil_htile_compressed && (!has_stencil || !has_htile)) ||
|
||||||
!(info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm)
|
!IsSupportedDepthTargetFormat(info)) {
|
||||||
? !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))) {
|
|
||||||
EXIT("TextureCache: unsupported depth target, command=%p ctx=%p depth=0x%016" PRIx64
|
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 " 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",
|
"+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);
|
RequireRetirementIsolation(retire, "depth target", info.address, info.size);
|
||||||
RetireImages(retire, native_depth_source.get());
|
RetireImages(retire, native_depth_source.get());
|
||||||
if (!CanLoadStencilAttachment(info, native_depth_source != nullptr &&
|
const bool coherent_guest_stencil =
|
||||||
native_depth_source->stencil_initialized)) {
|
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, "
|
EXIT("TextureCache: new stencil target requires a clear before stencil access, "
|
||||||
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
||||||
info.stencil_address, info.stencil_size);
|
info.stencil_address, info.stencil_size);
|
||||||
|
|||||||
@@ -12,6 +12,46 @@
|
|||||||
|
|
||||||
namespace Libs::Graphics {
|
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,
|
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
|
||||||
const BufferImageCopySource& source, bool refresh, bool storage) const {
|
const BufferImageCopySource& source, bool refresh, bool storage) const {
|
||||||
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
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,
|
void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||||
bool refresh, uint32_t base_layer) const {
|
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 ||
|
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.width == 0 || info.height == 0 || info.pitch < info.width || info.layers == 0 ||
|
||||||
info.size % info.layers != 0 || base_layer > image->layers ||
|
info.size % info.layers != 0 || base_layer > image->layers ||
|
||||||
info.layers > image->layers - base_layer || info.size > UINT32_MAX ||
|
info.layers > image->layers - base_layer || info.size > UINT32_MAX ||
|
||||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || (!d16 && !d32) ||
|
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
||||||
!source.cpu_current || source.address != info.address || source.size != info.size ||
|
!IsSupportedDepthTargetFormat(info) || !source.cpu_current ||
|
||||||
|
source.address != info.address || source.size != info.size ||
|
||||||
(source.buffer == nullptr && source.offset != 0)) {
|
(source.buffer == nullptr && source.offset != 0)) {
|
||||||
EXIT("Tiler: unsupported depth detile, ctx=%p image=%p source_buffer=%p "
|
EXIT("Tiler: unsupported depth detile, ctx=%p image=%p source_buffer=%p "
|
||||||
"source=0x%016" PRIx64 "+0x%016" PRIx64 " offset=0x%016" PRIx64
|
"source=0x%016" PRIx64 "+0x%016" PRIx64 " offset=0x%016" PRIx64
|
||||||
@@ -80,6 +114,19 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
|||||||
if (refresh) {
|
if (refresh) {
|
||||||
VulkanDeviceWaitIdle(ctx);
|
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;
|
const auto slice_size = info.size / info.layers;
|
||||||
UtilScratchBuffer linear(info.size);
|
UtilScratchBuffer linear(info.size);
|
||||||
std::vector<BufferImageCopy> regions;
|
std::vector<BufferImageCopy> regions;
|
||||||
@@ -109,11 +156,12 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
|||||||
TileSizeAlign htile_size {};
|
TileSizeAlign htile_size {};
|
||||||
TileSizeAlign depth_size {};
|
TileSizeAlign depth_size {};
|
||||||
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
|
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
|
||||||
|
const auto* policy = FindGuestDepthFormatPolicy(info.guest_format);
|
||||||
const auto stencil_pitch = TileGetTexturePitch(
|
const auto stencil_pitch = TileGetTexturePitch(
|
||||||
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||||
const bool supported_layout =
|
const bool supported_layout =
|
||||||
TileGetDepthSize(info.width, info.height, 0,
|
policy != nullptr && IsSupportedDepthTargetFormat(info) &&
|
||||||
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
TileGetDepthSize(info.width, info.height, 0, Prospero::GpuEnumValue(policy->depth_format),
|
||||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
|
||||||
info.htile_address != 0, &stencil_size, &htile_size, &depth_size) &&
|
info.htile_address != 0, &stencil_size, &htile_size, &depth_size) &&
|
||||||
info.layers != 0 && info.stencil_size % info.layers == 0 &&
|
info.layers != 0 && info.stencil_size % info.layers == 0 &&
|
||||||
@@ -121,9 +169,7 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
|||||||
stencil_pitch != 0;
|
stencil_pitch != 0;
|
||||||
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
|
||||||
info.stencil_address == 0 || info.stencil_size == 0 || info.width == 0 ||
|
info.stencil_address == 0 || info.stencil_size == 0 || info.width == 0 ||
|
||||||
info.height == 0 || info.format != VK_FORMAT_D32_SFLOAT_S8_UINT ||
|
info.height == 0 || base_layer > image->layers ||
|
||||||
info.guest_format != Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) ||
|
|
||||||
info.bytes_per_element != 4 || base_layer > image->layers ||
|
|
||||||
info.layers > image->layers - base_layer || info.stencil_size > UINT32_MAX ||
|
info.layers > image->layers - base_layer || info.stencil_size > UINT32_MAX ||
|
||||||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
||||||
info.stencil_htile_compressed || !supported_layout || !source.cpu_current ||
|
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 {
|
void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) const {
|
||||||
const bool supported_format =
|
const bool supported_format = IsSupportedDepthTargetFormat(info);
|
||||||
(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);
|
|
||||||
if (dst == nullptr || src == nullptr || info.address == 0 || info.size == 0 ||
|
if (dst == nullptr || src == nullptr || info.address == 0 || info.size == 0 ||
|
||||||
info.stencil_address != 0 || info.stencil_size != 0 || info.width == 0 ||
|
info.stencil_address != 0 || info.stencil_size != 0 || info.width == 0 ||
|
||||||
info.height == 0 || info.pitch < info.width ||
|
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,
|
VK_FORMAT_A2R10G10B10_UNORM_PACK32,
|
||||||
DstSel(6, 5, 4, 7));
|
DstSel(6, 5, 4, 7));
|
||||||
} else if (std::strcmp(kind, "sampled-depth-format") == 0) {
|
} else if (std::strcmp(kind, "sampled-depth-format") == 0) {
|
||||||
(void)SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
(void)SelectSampledDepthView(VK_FORMAT_D24_UNORM_S8_UINT,
|
||||||
VK_FORMAT_R16_UNORM, DstSel(4, 4, 4, 4));
|
VK_FORMAT_R32_SFLOAT, 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_D32_SFLOAT_S8_UINT,
|
(void)SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||||
VK_FORMAT_R32_SFLOAT, DstSel(4, 5, 6, 7));
|
VK_FORMAT_R32_SFLOAT, DstSel(4, 5, 6, 7));
|
||||||
@@ -8806,6 +8806,21 @@ void CheckSampledColorViews() {
|
|||||||
DstSel(4, 0, 0, 0)) ==
|
DstSel(4, 0, 0, 0)) ==
|
||||||
VulkanImage::VIEW_R000,
|
VulkanImage::VIEW_R000,
|
||||||
"D16 depth target did not select its R000 depth-aspect view");
|
"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",
|
Require("SampledColorViews", "D32S8 R001 depth target",
|
||||||
SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||||
VK_FORMAT_R32_SFLOAT,
|
VK_FORMAT_R32_SFLOAT,
|
||||||
@@ -11094,20 +11109,38 @@ void CheckImageOverlapResolution() {
|
|||||||
mismatched_depth) ==
|
mismatched_depth) ==
|
||||||
DepthOverlap::Unsupported,
|
DepthOverlap::Unsupported,
|
||||||
"mipmapped or format-mismatched depth load was admitted");
|
"mipmapped or format-mismatched depth load was admitted");
|
||||||
Require("ImageOverlapResolution", "depth transition source",
|
struct DepthTransitionCase {
|
||||||
SelectDepthTransitionSource(true, true, false, false, false, true) ==
|
const char *name;
|
||||||
DepthTransitionSource::None &&
|
bool clear;
|
||||||
SelectDepthTransitionSource(false, true, false, false, false, true) ==
|
bool native;
|
||||||
DepthTransitionSource::Native &&
|
bool sampled_cpu_dirty;
|
||||||
SelectDepthTransitionSource(false, false, false, false, false, false) ==
|
bool sampled_buffer_modified;
|
||||||
DepthTransitionSource::Guest &&
|
bool buffer_overlap;
|
||||||
SelectDepthTransitionSource(false, true, true, false, false, false) ==
|
bool buffer_cpu_dirty;
|
||||||
DepthTransitionSource::Guest &&
|
DepthTransitionSource expected;
|
||||||
SelectDepthTransitionSource(false, true, false, true, false, false) ==
|
};
|
||||||
DepthTransitionSource::Guest &&
|
constexpr DepthTransitionCase transition_cases[] = {
|
||||||
SelectDepthTransitionSource(false, true, false, false, true, true) ==
|
{"clear", true, true, false, false, false, true,
|
||||||
DepthTransitionSource::Guest,
|
DepthTransitionSource::None},
|
||||||
"clear, clean-native, or overlapping dirty-buffer depth preservation policy regressed");
|
{"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.depth_load_clear = true;
|
||||||
depth.stencil_address = sampled.address + 0x6000;
|
depth.stencil_address = sampled.address + 0x6000;
|
||||||
depth.stencil_size = 0x2000;
|
depth.stencil_size = 0x2000;
|
||||||
@@ -11136,6 +11169,7 @@ void CheckImageOverlapResolution() {
|
|||||||
Require("ImageOverlapResolution", "stencil clear initializes",
|
Require("ImageOverlapResolution", "stencil clear initializes",
|
||||||
CanLoadStencilAttachment(depth, false),
|
CanLoadStencilAttachment(depth, false),
|
||||||
"stencil clear did not initialize the attachment");
|
"stencil clear did not initialize the attachment");
|
||||||
|
depth.stencil_load_clear = false;
|
||||||
depth.stencil_htile_compressed = false;
|
depth.stencil_htile_compressed = false;
|
||||||
Require("ImageOverlapResolution", "raw stencil load",
|
Require("ImageOverlapResolution", "raw stencil load",
|
||||||
CanLoadRawStencilPlane(depth),
|
CanLoadRawStencilPlane(depth),
|
||||||
@@ -11253,6 +11287,122 @@ void CheckDepthTargetFootprints() {
|
|||||||
TileSizeAlign stencil{};
|
TileSizeAlign stencil{};
|
||||||
TileSizeAlign htile{};
|
TileSizeAlign htile{};
|
||||||
TileSizeAlign depth{};
|
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",
|
Require("DepthTargetFootprints", "640x360 Z32S8 without HTile",
|
||||||
TileGetDepthSize(640, 360, 0, Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
TileGetDepthSize(640, 360, 0, Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
|
||||||
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt), false,
|
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt), false,
|
||||||
@@ -11396,6 +11546,18 @@ void CheckHtileClearTargetResolution() {
|
|||||||
resolved.address == derived_z16.htile_data_base_addr &&
|
resolved.address == derived_z16.htile_data_base_addr &&
|
||||||
resolved.size == htile_size.size,
|
resolved.size == htile_size.size,
|
||||||
"extent-derived Z16 depth-only HTile target was rejected");
|
"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");
|
std::printf("[host] %-32s ok\n", "HtileClearTargetResolution");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user