diff options
author | Chip Davis <chip@holochip.com> | 2022-07-24 09:12:26 +0300 |
---|---|---|
committer | Chip Davis <chip@holochip.com> | 2022-08-05 21:43:21 +0300 |
commit | faea931de341a6de7360d9d42fccd4b7b066c0f9 (patch) | |
tree | 48b79d7c8c204be65edbd0245a179c4a2271d8bd | |
parent | 0cccd0a65a67f33922f8d0742b5930fd15353fa7 (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.comp | 63 | ||||
-rw-r--r-- | reference/shaders-msl/comp/shared-struct-bool-cast.comp | 110 | ||||
-rw-r--r-- | shaders-msl/comp/shared-struct-bool-cast.comp | 35 | ||||
-rw-r--r-- | spirv_msl.cpp | 29 | ||||
-rw-r--r-- | spirv_msl.hpp | 1 |
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; |