mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
shader: separate comparison image bindings
This commit is contained in:
@@ -158,7 +158,8 @@ uint32_t ImageType(EmitterState& state, const IR::ImageResource& image) {
|
|||||||
}
|
}
|
||||||
const auto& info = ImageDimensionInfoFor(image.dimension);
|
const auto& info = ImageDimensionInfoFor(image.dimension);
|
||||||
return state.builder.Type(OpTypeImage,
|
return state.builder.Type(OpTypeImage,
|
||||||
{ImageScalarType(state, image.numeric_class), info.spirv_dimension, 0,
|
{ImageScalarType(state, image.numeric_class), info.spirv_dimension,
|
||||||
|
image.depth_compare ? 1u : 0u,
|
||||||
info.arrayed, info.multisampled, sampled, format});
|
info.arrayed, info.multisampled, sampled, format});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -253,9 +253,10 @@ struct StageOutput {
|
|||||||
bool operator==(const StageOutput& other) const = default;
|
bool operator==(const StageOutput& other) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr uint32_t FirstImageBinding = 1u;
|
inline constexpr uint32_t FirstImageBinding = 1u;
|
||||||
inline constexpr uint32_t FirstStorageImageBinding = 22u;
|
inline constexpr uint32_t FirstDepthComparisonImageBinding = 22u;
|
||||||
inline constexpr uint32_t ImageBindingCount = 36u;
|
inline constexpr uint32_t FirstStorageImageBinding = 29u;
|
||||||
|
inline constexpr uint32_t ImageBindingCount = 43u;
|
||||||
|
|
||||||
enum class DescriptorBindingKind : uint32_t {
|
enum class DescriptorBindingKind : uint32_t {
|
||||||
Buffers = 0u,
|
Buffers = 0u,
|
||||||
@@ -268,8 +269,8 @@ enum class DescriptorBindingKind : uint32_t {
|
|||||||
Count,
|
Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 37u);
|
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 44u);
|
||||||
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 43u);
|
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 50u);
|
||||||
|
|
||||||
struct PushData {
|
struct PushData {
|
||||||
static constexpr uint32_t DwordCount = 32;
|
static constexpr uint32_t DwordCount = 32;
|
||||||
@@ -313,9 +314,10 @@ DescriptorBindingForImage(const ImageResource& image) {
|
|||||||
constexpr uint32_t SampledFloatBinding = 1u;
|
constexpr uint32_t SampledFloatBinding = 1u;
|
||||||
constexpr uint32_t SampledUintBinding = 8u;
|
constexpr uint32_t SampledUintBinding = 8u;
|
||||||
constexpr uint32_t SampledSintBinding = 15u;
|
constexpr uint32_t SampledSintBinding = 15u;
|
||||||
constexpr uint32_t StorageFloatBinding = 22u;
|
constexpr uint32_t SampledDepthBinding = FirstDepthComparisonImageBinding;
|
||||||
constexpr uint32_t StorageUintBinding = 27u;
|
constexpr uint32_t StorageFloatBinding = FirstStorageImageBinding;
|
||||||
constexpr uint32_t AtomicUintBinding = 32u;
|
constexpr uint32_t StorageUintBinding = 34u;
|
||||||
|
constexpr uint32_t AtomicUintBinding = 39u;
|
||||||
|
|
||||||
uint32_t base = 0;
|
uint32_t base = 0;
|
||||||
bool sampled = false;
|
bool sampled = false;
|
||||||
@@ -324,12 +326,19 @@ DescriptorBindingForImage(const ImageResource& image) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
sampled = true;
|
sampled = true;
|
||||||
switch (image.numeric_class) {
|
if (image.depth_compare) {
|
||||||
case Prospero::TextureNumericClass::Float: base = SampledFloatBinding; break;
|
if (image.numeric_class != Prospero::TextureNumericClass::Float) {
|
||||||
case Prospero::TextureNumericClass::Uint: base = SampledUintBinding; break;
|
return std::nullopt;
|
||||||
case Prospero::TextureNumericClass::Sint: base = SampledSintBinding; break;
|
}
|
||||||
case Prospero::TextureNumericClass::Unsupported: return std::nullopt;
|
base = SampledDepthBinding;
|
||||||
default: return std::nullopt;
|
} else {
|
||||||
|
switch (image.numeric_class) {
|
||||||
|
case Prospero::TextureNumericClass::Float: base = SampledFloatBinding; break;
|
||||||
|
case Prospero::TextureNumericClass::Uint: base = SampledUintBinding; break;
|
||||||
|
case Prospero::TextureNumericClass::Sint: base = SampledSintBinding; break;
|
||||||
|
case Prospero::TextureNumericClass::Unsupported: return std::nullopt;
|
||||||
|
default: return std::nullopt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (image.resource_class == ImageResourceClass::Storage) {
|
} else if (image.resource_class == ImageResourceClass::Storage) {
|
||||||
if (image.atomic) {
|
if (image.atomic) {
|
||||||
|
|||||||
@@ -1240,15 +1240,15 @@ void TestShaderInfoAndBindingLayout() {
|
|||||||
void TestImageBindingAbi() {
|
void TestImageBindingAbi() {
|
||||||
using NumericClass = Libs::Graphics::Prospero::TextureNumericClass;
|
using NumericClass = Libs::Graphics::Prospero::TextureNumericClass;
|
||||||
|
|
||||||
Check(ImageBindingCount == 36u &&
|
Check(ImageBindingCount == 43u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::Buffers) == 0u &&
|
static_cast<uint32_t>(DescriptorBindingKind::Buffers) == 0u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 37u &&
|
static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 44u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::Gds) == 38u &&
|
static_cast<uint32_t>(DescriptorBindingKind::Gds) == 45u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::BdaPagetable) == 39u &&
|
static_cast<uint32_t>(DescriptorBindingKind::BdaPagetable) == 46u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::FaultBuffer) == 40u &&
|
static_cast<uint32_t>(DescriptorBindingKind::FaultBuffer) == 47u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::FlattenedSrt) == 41u &&
|
static_cast<uint32_t>(DescriptorBindingKind::FlattenedSrt) == 48u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::ShaderData) == 42u &&
|
static_cast<uint32_t>(DescriptorBindingKind::ShaderData) == 49u &&
|
||||||
static_cast<uint32_t>(DescriptorBindingKind::Count) == 43u,
|
static_cast<uint32_t>(DescriptorBindingKind::Count) == 50u,
|
||||||
"native descriptor binding anchors changed");
|
"native descriptor binding anchors changed");
|
||||||
|
|
||||||
const std::array sampled_dimensions{
|
const std::array sampled_dimensions{
|
||||||
@@ -1271,12 +1271,14 @@ void TestImageBindingAbi() {
|
|||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
const auto CheckBinding =
|
const auto CheckBinding =
|
||||||
[&](ImageResourceClass resource_class, NumericClass numeric_class,
|
[&](ImageResourceClass resource_class, NumericClass numeric_class,
|
||||||
Decoder::ImageDimension dimension, bool atomic) {
|
Decoder::ImageDimension dimension, bool atomic,
|
||||||
|
bool depth_compare = false) {
|
||||||
ImageResource image;
|
ImageResource image;
|
||||||
image.resource_class = resource_class;
|
image.resource_class = resource_class;
|
||||||
image.numeric_class = numeric_class;
|
image.numeric_class = numeric_class;
|
||||||
image.dimension = dimension;
|
image.dimension = dimension;
|
||||||
image.atomic = atomic;
|
image.atomic = atomic;
|
||||||
|
image.depth_compare = depth_compare;
|
||||||
const auto kind = DescriptorBindingForImage(image);
|
const auto kind = DescriptorBindingForImage(image);
|
||||||
Check(kind.has_value() &&
|
Check(kind.has_value() &&
|
||||||
static_cast<uint32_t>(*kind) == FirstImageBinding + index &&
|
static_cast<uint32_t>(*kind) == FirstImageBinding + index &&
|
||||||
@@ -1296,6 +1298,10 @@ void TestImageBindingAbi() {
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto dimension : sampled_dimensions) {
|
||||||
|
CheckBinding(ImageResourceClass::Sampled, NumericClass::Float, dimension,
|
||||||
|
false, true);
|
||||||
|
}
|
||||||
for (const auto numeric_class : storage_classes) {
|
for (const auto numeric_class : storage_classes) {
|
||||||
for (const auto dimension : storage_dimensions) {
|
for (const auto dimension : storage_dimensions) {
|
||||||
CheckBinding(ImageResourceClass::Storage, numeric_class, dimension,
|
CheckBinding(ImageResourceClass::Storage, numeric_class, dimension,
|
||||||
@@ -1322,6 +1328,11 @@ void TestImageBindingAbi() {
|
|||||||
image.numeric_class = NumericClass::Unsupported;
|
image.numeric_class = NumericClass::Unsupported;
|
||||||
Check(Invalid(image),
|
Check(Invalid(image),
|
||||||
"unsupported sampled class received a descriptor binding");
|
"unsupported sampled class received a descriptor binding");
|
||||||
|
image.numeric_class = NumericClass::Uint;
|
||||||
|
image.depth_compare = true;
|
||||||
|
Check(Invalid(image),
|
||||||
|
"integer comparison image received a descriptor binding");
|
||||||
|
image.depth_compare = false;
|
||||||
image.numeric_class = static_cast<NumericClass>(UINT32_MAX);
|
image.numeric_class = static_cast<NumericClass>(UINT32_MAX);
|
||||||
Check(Invalid(image), "invalid sampled class received a descriptor binding");
|
Check(Invalid(image), "invalid sampled class received a descriptor binding");
|
||||||
image.numeric_class = NumericClass::Float;
|
image.numeric_class = NumericClass::Float;
|
||||||
|
|||||||
@@ -20425,7 +20425,7 @@ TestCase ImageSampleOpcodeAliasUsesNormalCoords() {
|
|||||||
test.code = code;
|
test.code = code;
|
||||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD,
|
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD,
|
||||||
O::S_ENDPGM};
|
O::S_ENDPGM};
|
||||||
test.required_spirv = {"OpImageSampleExplicitLod"};
|
test.required_spirv = {"OpTypeImage %float 2D 0", "OpImageSampleExplicitLod"};
|
||||||
test.forbidden_spirv = {"UnpackHalf2x16"};
|
test.forbidden_spirv = {"UnpackHalf2x16"};
|
||||||
test.compile_only = true;
|
test.compile_only = true;
|
||||||
return test;
|
return test;
|
||||||
@@ -20479,7 +20479,8 @@ TestCase ImageSampleA16CompareBiasRdna2AddressOrder() {
|
|||||||
test.code = code;
|
test.code = code;
|
||||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD,
|
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD,
|
||||||
O::S_ENDPGM};
|
O::S_ENDPGM};
|
||||||
test.required_spirv = {"OpImageSampleDrefExplicitLod", "UnpackHalf2x16"};
|
test.required_spirv = {"OpTypeImage %float 2D 1",
|
||||||
|
"OpImageSampleDrefExplicitLod", "UnpackHalf2x16"};
|
||||||
test.compile_only = true;
|
test.compile_only = true;
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
@@ -24025,6 +24026,42 @@ void CheckNativeImageDescriptorTypes() {
|
|||||||
std::printf("[host] %-32s ok\n", "NativeImageDescriptorTypes");
|
std::printf("[host] %-32s ok\n", "NativeImageDescriptorTypes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckDepthComparisonBindings() {
|
||||||
|
using namespace ShaderRecompiler::IR;
|
||||||
|
|
||||||
|
ImageResource color{};
|
||||||
|
color.resource_class = ImageResourceClass::Sampled;
|
||||||
|
color.numeric_class = Prospero::TextureNumericClass::Float;
|
||||||
|
color.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||||
|
color.read = true;
|
||||||
|
auto depth = color;
|
||||||
|
depth.depth_compare = true;
|
||||||
|
|
||||||
|
const auto color_kind = DescriptorBindingForImage(color);
|
||||||
|
const auto depth_kind = DescriptorBindingForImage(depth);
|
||||||
|
Program program;
|
||||||
|
program.info.images = {color, depth};
|
||||||
|
program.shader_info_complete = true;
|
||||||
|
AllocateBindings(program);
|
||||||
|
|
||||||
|
Require("DepthComparisonBindings", "separate classes",
|
||||||
|
color_kind.has_value() && depth_kind.has_value() &&
|
||||||
|
color_kind != depth_kind &&
|
||||||
|
ImageBindingResourceClass(*color_kind) ==
|
||||||
|
ImageResourceClass::Sampled &&
|
||||||
|
ImageBindingResourceClass(*depth_kind) ==
|
||||||
|
ImageResourceClass::Sampled,
|
||||||
|
"ordinary and comparison images share a descriptor class");
|
||||||
|
const auto *color_binding = FindBinding(program.bindings, *color_kind);
|
||||||
|
const auto *depth_binding = FindBinding(program.bindings, *depth_kind);
|
||||||
|
Require("DepthComparisonBindings", "separate arrays",
|
||||||
|
color_binding != nullptr && depth_binding != nullptr &&
|
||||||
|
color_binding->resources == std::vector<uint32_t>{0u} &&
|
||||||
|
depth_binding->resources == std::vector<uint32_t>{1u},
|
||||||
|
"ordinary and comparison images share a descriptor array");
|
||||||
|
std::printf("[host] %-32s ok\n", "DepthComparisonBindings");
|
||||||
|
}
|
||||||
|
|
||||||
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
|
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
|
||||||
void CheckShaderRecompilerFatalContracts() {
|
void CheckShaderRecompilerFatalContracts() {
|
||||||
ExpectFatal("InvalidDescriptorBindingRejection", [] {
|
ExpectFatal("InvalidDescriptorBindingRejection", [] {
|
||||||
@@ -26060,6 +26097,9 @@ int main(int argc, char **argv) {
|
|||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
CheckSampledDepthResource();
|
CheckSampledDepthResource();
|
||||||
CheckSampledDepthDescriptor(vulkan.RuntimeRenderer());
|
CheckSampledDepthDescriptor(vulkan.RuntimeRenderer());
|
||||||
|
CheckDepthComparisonBindings();
|
||||||
|
RunCase(nullptr, ImageSampleOpcodeAliasUsesNormalCoords());
|
||||||
|
RunCase(nullptr, ImageSampleA16CompareBiasRdna2AddressOrder());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--storage-bgra-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--storage-bgra-only") == 0) {
|
||||||
@@ -26135,6 +26175,7 @@ int main(int argc, char **argv) {
|
|||||||
#endif
|
#endif
|
||||||
CheckImageSamplerSpecialization();
|
CheckImageSamplerSpecialization();
|
||||||
CheckNativeImageDescriptorTypes();
|
CheckNativeImageDescriptorTypes();
|
||||||
|
CheckDepthComparisonBindings();
|
||||||
CheckClipControlDepthClipState();
|
CheckClipControlDepthClipState();
|
||||||
CheckReferenceClockScale();
|
CheckReferenceClockScale();
|
||||||
CheckVulkan13FeatureRequirements();
|
CheckVulkan13FeatureRequirements();
|
||||||
|
|||||||
Reference in New Issue
Block a user