Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChip Davis <chip@holochip.com>2022-07-24 09:12:26 +0300
committerChip Davis <chip@holochip.com>2022-08-05 21:43:21 +0300
commitfaea931de341a6de7360d9d42fccd4b7b066c0f9 (patch)
tree48b79d7c8c204be65edbd0245a179c4a2271d8bd
parent0cccd0a65a67f33922f8d0742b5930fd15353fa7 (diff)
MSL: Also replace `bool` with `short` in structures.
Since `bool` is a logical type, it cannot be used in uniform or storage buffers. Therefore, replacing it in structures should not change the shader interface. We leave it alone for builtins. (FIXME: Should we also leave it for I/O varyings?) Fixes 24 CTS tests under `dEQP-VK.memory_model.shared`.
-rw-r--r--reference/opt/shaders-msl/comp/shared-struct-bool-cast.comp63
-rw-r--r--reference/shaders-msl/comp/shared-struct-bool-cast.comp110
-rw-r--r--shaders-msl/comp/shared-struct-bool-cast.comp35
-rw-r--r--spirv_msl.cpp29
-rw-r--r--spirv_msl.hpp1
5 files changed, 230 insertions, 8 deletions
diff --git a/reference/opt/shaders-msl/comp/shared-struct-bool-cast.comp b/reference/opt/shaders-msl/comp/shared-struct-bool-cast.comp
new file mode 100644
index 00000000..538ab0bd
--- /dev/null
+++ b/reference/opt/shaders-msl/comp/shared-struct-bool-cast.comp
@@ -0,0 +1,63 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct S1
+{
+ int3 a;
+ uint2 b;
+ short4 c;
+ uint d;
+};
+
+struct block
+{
+ uint passed;
+};
+
+constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(1u);
+
+kernel void main0(device block& _132 [[buffer(0)]])
+{
+ threadgroup S1 s1;
+ s1.a = int3(6, 8, 8);
+ s1.b = uint2(4u);
+ s1.c = short4(bool4(false, false, false, true));
+ s1.d = 6u;
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup | mem_flags::mem_texture);
+ bool _144 = all(int3(6, 8, 8) == s1.a);
+ bool _108;
+ if (_144)
+ {
+ _108 = all(uint2(4u) == s1.b);
+ }
+ else
+ {
+ _108 = _144;
+ }
+ bool _117;
+ if (_108)
+ {
+ _117 = all(bool4(false, false, false, true) == bool4(s1.c));
+ }
+ else
+ {
+ _117 = _108;
+ }
+ bool _126;
+ if (_117)
+ {
+ _126 = 6u == s1.d;
+ }
+ else
+ {
+ _126 = _117;
+ }
+ if (_126)
+ {
+ _132.passed++;
+ }
+}
+
diff --git a/reference/shaders-msl/comp/shared-struct-bool-cast.comp b/reference/shaders-msl/comp/shared-struct-bool-cast.comp
new file mode 100644
index 00000000..806cb0a8
--- /dev/null
+++ b/reference/shaders-msl/comp/shared-struct-bool-cast.comp
@@ -0,0 +1,110 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct S1
+{
+ int3 a;
+ uint2 b;
+ short4 c;
+ uint d;
+};
+
+struct block
+{
+ uint passed;
+};
+
+constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(1u);
+
+static inline __attribute__((always_inline))
+bool compare_ivec3(thread const int3& a, thread const int3& b)
+{
+ return all(a == b);
+}
+
+static inline __attribute__((always_inline))
+bool compare_uvec2(thread const uint2& a, thread const uint2& b)
+{
+ return all(a == b);
+}
+
+static inline __attribute__((always_inline))
+bool compare_bvec4(thread const bool4& a, thread const bool4& b)
+{
+ return all(a == b);
+}
+
+static inline __attribute__((always_inline))
+bool compare_uint(thread const uint& a, thread const uint& b)
+{
+ return a == b;
+}
+
+kernel void main0(device block& _132 [[buffer(0)]])
+{
+ threadgroup S1 s1;
+ s1.a = int3(6, 8, 8);
+ s1.b = uint2(4u);
+ s1.c = short4(bool4(false, false, false, true));
+ s1.d = 6u;
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup | mem_flags::mem_texture);
+ bool allOk = true;
+ bool _99;
+ if (allOk)
+ {
+ int3 param = int3(6, 8, 8);
+ int3 param_1 = s1.a;
+ _99 = compare_ivec3(param, param_1);
+ }
+ else
+ {
+ _99 = allOk;
+ }
+ allOk = _99;
+ bool _108;
+ if (allOk)
+ {
+ uint2 param_2 = uint2(4u);
+ uint2 param_3 = s1.b;
+ _108 = compare_uvec2(param_2, param_3);
+ }
+ else
+ {
+ _108 = allOk;
+ }
+ allOk = _108;
+ bool _117;
+ if (allOk)
+ {
+ bool4 param_4 = bool4(false, false, false, true);
+ bool4 param_5 = bool4(s1.c);
+ _117 = compare_bvec4(param_4, param_5);
+ }
+ else
+ {
+ _117 = allOk;
+ }
+ allOk = _117;
+ bool _126;
+ if (allOk)
+ {
+ uint param_6 = 6u;
+ uint param_7 = s1.d;
+ _126 = compare_uint(param_6, param_7);
+ }
+ else
+ {
+ _126 = allOk;
+ }
+ allOk = _126;
+ if (allOk)
+ {
+ _132.passed++;
+ }
+}
+
diff --git a/shaders-msl/comp/shared-struct-bool-cast.comp b/shaders-msl/comp/shared-struct-bool-cast.comp
new file mode 100644
index 00000000..d6479b3e
--- /dev/null
+++ b/shaders-msl/comp/shared-struct-bool-cast.comp
@@ -0,0 +1,35 @@
+#version 450
+layout(local_size_x = 1) in;
+
+layout(std140, binding = 0) buffer block { highp uint passed; };
+struct S1 {
+ mediump ivec3 a;
+ highp uvec2 b;
+ bvec4 c;
+ mediump uint d;
+};
+
+bool compare_ivec3 (highp ivec3 a, highp ivec3 b) { return a == b; }
+bool compare_uint (highp uint a, highp uint b) { return a == b; }
+bool compare_uvec2 (highp uvec2 a, highp uvec2 b) { return a == b; }
+bool compare_bvec4 (bvec4 a, bvec4 b) { return a == b; }
+
+shared S1 s1;
+
+void main (void) {
+ s1.a = ivec3(6, 8, 8);
+ s1.b = uvec2(4u, 4u);
+ s1.c = bvec4(false, false, false, true);
+ s1.d = 6u;
+
+ barrier();
+ memoryBarrier();
+ bool allOk = true;
+ allOk = allOk && compare_ivec3(ivec3(6, 8, 8), s1.a);
+ allOk = allOk && compare_uvec2(uvec2(4u, 4u), s1.b);
+ allOk = allOk && compare_bvec4(bvec4(false, false, false, true), s1.c);
+ allOk = allOk && compare_uint(6u, s1.d);
+ if (allOk)
+ passed++;
+
+}
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index efd29879..378c09a7 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -10907,8 +10907,8 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_
array_type = type_to_array_glsl(physical_type);
}
- auto result = join(pack_pfx, type_to_glsl(*declared_type, orig_id), " ", qualifier, to_member_name(type, index),
- member_attribute_qualifier(type, index), array_type, ";");
+ auto result = join(pack_pfx, type_to_glsl(*declared_type, orig_id, true), " ", qualifier,
+ to_member_name(type, index), member_attribute_qualifier(type, index), array_type, ";");
is_using_builtin_array = false;
return result;
@@ -13581,7 +13581,7 @@ string CompilerMSL::to_qualifiers_glsl(uint32_t id)
// The optional id parameter indicates the object whose type we are trying
// to find the description for. It is optional. Most type descriptions do not
// depend on a specific object's use of that type.
-string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
+string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
{
string type_name;
@@ -13671,9 +13671,7 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
// Need to special-case threadgroup booleans. They are supposed to be logical
// storage, but MSL compilers will sometimes crash if you use threadgroup bool.
// Workaround this by using 16-bit types instead and fixup on load-store to this data.
- // FIXME: We have no sane way of working around this problem if a struct member is boolean
- // and that struct is used as a threadgroup variable, but ... sigh.
- if ((var && var->storage == StorageClassWorkgroup) || type.storage == StorageClassWorkgroup)
+ if ((var && var->storage == StorageClassWorkgroup) || type.storage == StorageClassWorkgroup || member)
type_name = "short";
else
type_name = "bool";
@@ -13765,6 +13763,11 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
}
}
+string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
+{
+ return type_to_glsl(type, id, false);
+}
+
string CompilerMSL::type_to_array_glsl(const SPIRType &type)
{
// Allow Metal to use the array<T> template to make arrays a value type
@@ -15787,11 +15790,16 @@ void CompilerMSL::remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t
void CompilerMSL::cast_from_variable_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
{
auto *var = maybe_get_backing_variable(source_id);
+ SPIRType *var_type;
if (var)
+ {
source_id = var->self;
+ var_type = &get_variable_data_type(*var);
+ }
// Type fixups for workgroup variables if they are booleans.
- if (var && var->storage == StorageClassWorkgroup && expr_type.basetype == SPIRType::Boolean)
+ if (var && (var->storage == StorageClassWorkgroup || var_type->basetype == SPIRType::Struct) &&
+ expr_type.basetype == SPIRType::Boolean)
expr = join(type_to_glsl(expr_type), "(", expr, ")");
// Only interested in standalone builtin variables in the switch below.
@@ -15886,11 +15894,16 @@ void CompilerMSL::cast_from_variable_load(uint32_t source_id, std::string &expr,
void CompilerMSL::cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
{
auto *var = maybe_get_backing_variable(target_id);
+ SPIRType *var_type;
if (var)
+ {
target_id = var->self;
+ var_type = &get_variable_data_type(*var);
+ }
// Type fixups for workgroup variables if they are booleans.
- if (var && var->storage == StorageClassWorkgroup && expr_type.basetype == SPIRType::Boolean)
+ if (var && (var->storage == StorageClassWorkgroup || var_type->basetype == SPIRType::Struct) &&
+ expr_type.basetype == SPIRType::Boolean)
{
auto short_type = expr_type;
short_type.basetype = SPIRType::Short;
diff --git a/spirv_msl.hpp b/spirv_msl.hpp
index c0317c7a..920f9fc0 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -736,6 +736,7 @@ protected:
void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
const std::string &qualifier = "", uint32_t base_offset = 0) override;
void emit_struct_padding_target(const SPIRType &type) override;
+ std::string type_to_glsl(const SPIRType &type, uint32_t id, bool member);
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
void emit_block_hints(const SPIRBlock &block) override;