| // Copyright (c) 2018 Google LLC. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <sstream> |
| #include <string> |
| #include <tuple> |
| |
| #include "gmock/gmock.h" |
| #include "test/unit_spirv.h" |
| #include "test/val/val_fixtures.h" |
| |
| namespace spvtools { |
| namespace val { |
| namespace { |
| |
| using ::testing::Combine; |
| using ::testing::HasSubstr; |
| using ::testing::Values; |
| using ::testing::ValuesIn; |
| |
| std::string GenerateShaderCode( |
| const std::string& body, |
| const std::string& capabilities_and_extensions = "", |
| const std::string& execution_model = "GLCompute") { |
| std::ostringstream ss; |
| ss << R"( |
| OpCapability Shader |
| OpCapability GroupNonUniform |
| OpCapability GroupNonUniformVote |
| OpCapability GroupNonUniformBallot |
| OpCapability GroupNonUniformShuffle |
| OpCapability GroupNonUniformShuffleRelative |
| OpCapability GroupNonUniformArithmetic |
| OpCapability GroupNonUniformClustered |
| OpCapability GroupNonUniformQuad |
| OpCapability GroupNonUniformPartitionedNV |
| OpCapability QuadControlKHR |
| OpExtension "SPV_NV_shader_subgroup_partitioned" |
| OpExtension "SPV_KHR_quad_control" |
| )"; |
| |
| ss << capabilities_and_extensions; |
| ss << "OpMemoryModel Logical GLSL450\n"; |
| ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; |
| if (execution_model == "GLCompute") { |
| ss << "OpExecutionMode %main LocalSize 1 1 1\n"; |
| } |
| |
| ss << R"( |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %bool = OpTypeBool |
| %u32 = OpTypeInt 32 0 |
| %int = OpTypeInt 32 1 |
| %float = OpTypeFloat 32 |
| %u32vec4 = OpTypeVector %u32 4 |
| %u32vec3 = OpTypeVector %u32 3 |
| %v2bool = OpTypeVector %bool 2 |
| %v4float = OpTypeVector %float 4 |
| %struct = OpTypeStruct %int |
| %v4int = OpTypeVector %int 4 |
| |
| %true = OpConstantTrue %bool |
| %false = OpConstantFalse %bool |
| |
| %u32_0 = OpConstant %u32 0 |
| %int_0 = OpConstant %int 0 |
| |
| %float_0 = OpConstant %float 0 |
| |
| %u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0 |
| %u32vec3_null = OpConstantComposite %u32vec3 %u32_0 %u32_0 %u32_0 |
| %v2bool_false = OpConstantNull %v2bool |
| %v4float_null = OpConstantNull %v4float |
| %struct_null = OpConstantNull %struct |
| %v4int_null = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 |
| |
| %u32_undef = OpUndef %u32 |
| |
| %cross_device = OpConstant %u32 0 |
| %device = OpConstant %u32 1 |
| %workgroup = OpConstant %u32 2 |
| %subgroup = OpConstant %u32 3 |
| %invocation = OpConstant %u32 4 |
| |
| %reduce = OpConstant %u32 0 |
| %inclusive_scan = OpConstant %u32 1 |
| %exclusive_scan = OpConstant %u32 2 |
| %clustered_reduce = OpConstant %u32 3 |
| |
| %main = OpFunction %void None %func |
| %main_entry = OpLabel |
| )"; |
| |
| ss << body; |
| |
| ss << R"( |
| OpReturn |
| OpFunctionEnd)"; |
| |
| return ss.str(); |
| } |
| |
| spv::Scope scopes[] = {spv::Scope::CrossDevice, spv::Scope::Device, |
| spv::Scope::Workgroup, spv::Scope::Subgroup, |
| spv::Scope::Invocation}; |
| |
| using ValidateGroupNonUniform = spvtest::ValidateBase<bool>; |
| using GroupNonUniform = spvtest::ValidateBase< |
| std::tuple<std::string, std::string, spv::Scope, std::string, std::string>>; |
| |
| std::string ConvertScope(spv::Scope scope) { |
| switch (scope) { |
| case spv::Scope::CrossDevice: |
| return "%cross_device"; |
| case spv::Scope::Device: |
| return "%device"; |
| case spv::Scope::Workgroup: |
| return "%workgroup"; |
| case spv::Scope::Subgroup: |
| return "%subgroup"; |
| case spv::Scope::Invocation: |
| return "%invocation"; |
| default: |
| return ""; |
| } |
| } |
| |
| std::string ConvertMatch(const std::string& type) { |
| if (type == "%bool") { |
| return "%true"; |
| } else if (type == "%u32") { |
| return "%u32_0"; |
| } else if (type == "%int") { |
| return "%int_0"; |
| } else if (type == "%float") { |
| return "%float_0"; |
| } else if (type == "%u32vec4") { |
| return "%u32vec4_null"; |
| } else if (type == "%u32vec3") { |
| return "%u32vec3_null"; |
| } else if (type == "%v2bool") { |
| return "%v2bool_false"; |
| } else if (type == "%v4float") { |
| return "%v4float_null"; |
| } else if (type == "%struct") { |
| return "%struct_null"; |
| } else if (type == "%v4int") { |
| return "%v4int_null"; |
| } |
| |
| return "INVALID"; |
| } |
| |
| TEST_P(GroupNonUniform, Vulkan1p1) { |
| std::string opcode = std::get<0>(GetParam()); |
| std::string type = std::get<1>(GetParam()); |
| spv::Scope execution_scope = std::get<2>(GetParam()); |
| std::string args = std::get<3>(GetParam()); |
| std::string error = std::get<4>(GetParam()); |
| |
| const std::string match = "match_res"; |
| size_t pos = std::string::npos; |
| while ((pos = args.find(match)) != std::string::npos) { |
| const std::string replace = ConvertMatch(type); |
| args = args.substr(0, pos) + replace + args.substr(pos + match.size()); |
| } |
| |
| std::ostringstream sstr; |
| sstr << "%result = " << opcode << " "; |
| sstr << type << " "; |
| if (opcode != "OpGroupNonUniformQuadAllKHR" && |
| opcode != "OpGroupNonUniformQuadAnyKHR") { |
| sstr << ConvertScope(execution_scope) << " "; |
| } |
| sstr << args << "\n"; |
| |
| CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1); |
| spv_result_t result = ValidateInstructions(SPV_ENV_VULKAN_1_1); |
| if (error == "") { |
| if (execution_scope == spv::Scope::Subgroup) { |
| EXPECT_EQ(SPV_SUCCESS, result); |
| } else { |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); |
| EXPECT_THAT(getDiagnosticString(), |
| AnyVUID("VUID-StandaloneSpirv-None-04642")); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| HasSubstr( |
| "in Vulkan environment Execution scope is limited to Subgroup")); |
| } |
| } else { |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); |
| EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); |
| } |
| } |
| |
| TEST_P(GroupNonUniform, Spirv1p3) { |
| std::string opcode = std::get<0>(GetParam()); |
| std::string type = std::get<1>(GetParam()); |
| spv::Scope execution_scope = std::get<2>(GetParam()); |
| std::string args = std::get<3>(GetParam()); |
| std::string error = std::get<4>(GetParam()); |
| |
| const std::string match = "match_res"; |
| size_t pos = std::string::npos; |
| while ((pos = args.find(match)) != std::string::npos) { |
| const std::string replace = ConvertMatch(type); |
| args = args.substr(0, pos) + replace + args.substr(pos + match.size()); |
| } |
| |
| std::ostringstream sstr; |
| sstr << "%result = " << opcode << " "; |
| sstr << type << " "; |
| if (opcode != "OpGroupNonUniformQuadAllKHR" && |
| opcode != "OpGroupNonUniformQuadAnyKHR") { |
| sstr << ConvertScope(execution_scope) << " "; |
| } |
| sstr << args << "\n"; |
| |
| CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3); |
| spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3); |
| if (error == "") { |
| if (execution_scope == spv::Scope::Subgroup || |
| execution_scope == spv::Scope::Workgroup) { |
| EXPECT_EQ(SPV_SUCCESS, result); |
| } else { |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| HasSubstr("Execution scope is limited to Subgroup or Workgroup")); |
| } |
| } else { |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); |
| EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformElect, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformElect"), |
| Values("%bool"), ValuesIn(scopes), Values(""), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformVote, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAll", |
| "OpGroupNonUniformAny", |
| "OpGroupNonUniformAllEqual"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("%true"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcast, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("%true %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastFirst, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcastFirst"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("%true"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallot, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallot"), |
| Values("%u32vec4"), ValuesIn(scopes), |
| Values("%true"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformInverseBallot, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformInverseBallot"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("%u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitExtract, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitExtract"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("%u32vec4_null %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCount, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitCount"), |
| Values("%u32"), ValuesIn(scopes), |
| Values("Reduce %u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotFind, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotFindLSB", |
| "OpGroupNonUniformBallotFindMSB"), |
| Values("%u32"), ValuesIn(scopes), |
| Values("%u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformShuffle, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformShuffle", |
| "OpGroupNonUniformShuffleXor", |
| "OpGroupNonUniformShuffleUp", |
| "OpGroupNonUniformShuffleDown"), |
| Values("%u32"), ValuesIn(scopes), |
| Values("%u32_0 %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmetic, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), ValuesIn(scopes), Values("Reduce %u32_0"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmetic, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%float"), ValuesIn(scopes), Values("Reduce %float_0"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformLogicalArithmetic, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", |
| "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%bool"), ValuesIn(scopes), |
| Values("Reduce %true"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuad, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%u32"), ValuesIn(scopes), |
| Values("%u32_0 %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountScope, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitCount"), |
| Values("%u32"), ValuesIn(scopes), |
| Values("Reduce %u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotBitCountBadResultType, GroupNonUniform, |
| Combine( |
| Values("OpGroupNonUniformBallotBitCount"), Values("%float", "%int"), |
| Values(spv::Scope::Subgroup), Values("Reduce %u32vec4_null"), |
| Values("Expected Result Type to be an unsigned integer type scalar."))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountBadValue, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitCount"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("Reduce %u32vec3_null", "Reduce %u32_0", |
| "Reduce %float_0"), |
| Values("Expected Value to be a vector of four " |
| "components of integer type scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformElectGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformElect"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values(""), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformElectBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformElect"), |
| Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct"), |
| Values(spv::Scope::Subgroup), Values(""), |
| Values("Result must be a boolean scalar type"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformAnyAllGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAny", |
| "OpGroupNonUniformAll"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true", "%false"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformAnyAllBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAny", "OpGroupNonUniformAll"), |
| Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct"), |
| Values(spv::Scope::Subgroup), Values("%true"), |
| Values("Result must be a boolean scalar type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformAnyAllBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAny", "OpGroupNonUniformAll"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%u32_0", "%int_0", "%float_0", "%u32vec4_null", |
| "%u32vec3_null", "%v2bool_false", "%v4float_null", |
| "%struct_null"), |
| Values("Predicate must be a boolean scalar type"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformAllEqualGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAllEqual"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true", "%false"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformAllEqualBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAllEqual"), |
| Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct"), |
| Values(spv::Scope::Subgroup), Values("%true"), |
| Values("Result must be a boolean scalar type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformAllEqualBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformAllEqual"), Values("%bool"), |
| Values(spv::Scope::Subgroup), Values("%struct_null"), |
| Values("Value must be a scalar or vector of integer, " |
| "floating-point, or boolean type"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast", |
| "OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%bool", "%u32", "%int", "%float", |
| "%u32vec4", "%u32vec3", "%v2bool", |
| "%v4float", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("match_res %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBroadcastShuffleBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle", |
| "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp", |
| "OpGroupNonUniformShuffleDown", |
| "OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%void", "%struct"), Values(spv::Scope::Subgroup), |
| Values("%u32_0 %u32_0"), |
| Values("Result must be a scalar or vector of integer, " |
| "floating-point, or boolean type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBroadcastShuffleBadOperand1, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle", |
| "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp", |
| "OpGroupNonUniformShuffleDown", |
| "OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%u32_0 %u32_0", "%int_0 %u32_0", "%float_0 %u32_0", |
| "%u32vec4_null %u32_0", "%u32vec3_null %u32_0", |
| "%v2bool_false %u32_0", "%v4float_null %u32_0", |
| "%struct_null %u32_0", "%v4int_null %u32_0"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBroadcastShuffleBadOperand2, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle", |
| "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp", |
| "OpGroupNonUniformShuffleDown", |
| "OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true %true", "%true %int_0", "%true %float_0", |
| "%true %u32vec4_null", "%true %u32vec3_null", |
| "%true %v4float_null", "%true %v2bool_false", |
| "%true %struct_null", "%true %v4int_null"), |
| Values("must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastShuffleOperand2NotConstant, |
| GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcast", |
| "OpGroupNonUniformQuadBroadcast", |
| "OpGroupNonUniformQuadSwap"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true %u32_undef"), |
| Values("must be a constant instruction"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastFirstGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcastFirst"), |
| Values("%bool", "%u32", "%int", "%float", |
| "%u32vec4", "%u32vec3", "%v2bool", |
| "%v4float", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("match_res"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBroadcasFirsttBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcastFirst"), |
| Values("%void", "%struct"), Values(spv::Scope::Subgroup), |
| Values("%u32_0"), |
| Values("Result must be a scalar or vector of integer, " |
| "floating-point, or boolean type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBroadcastBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBroadcastFirst"), Values("%bool"), |
| Values(spv::Scope::Subgroup), |
| Values("%u32_0", "%int_0", "%float_0", "%u32vec4_null", |
| "%u32vec3_null", "%v2bool_false", "%v4float_null", |
| "%struct_null", "%v4int_null"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallot"), |
| Values("%u32vec4"), |
| Values(spv::Scope::Subgroup), |
| Values("%true", "%false"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallot"), |
| Values("%void", "%bool", "%u32", "%int", "%float", "%u32vec3", |
| "%v2bool", "%v4float", "%struct", "%v4int"), |
| Values(spv::Scope::Subgroup), Values("%true", "%false"), |
| Values("Result must be a 4-component unsigned integer vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallot"), |
| Values("%u32vec4"), |
| Values(spv::Scope::Subgroup), |
| Values("%u32_0", "%int_0", "%float_0", |
| "%u32vec4_null", "%u32vec3_null", |
| "%v2bool_false", "%v4float_null", |
| "%struct_null", "%v4int_null"), |
| Values("Predicate must be a boolean scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformInverseBallotGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformInverseBallot"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformInverseBallotBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformInverseBallot"), |
| Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct", "%v4int"), |
| Values(spv::Scope::Subgroup), Values("%u32vec4_null"), |
| Values("Result must be a boolean scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformInverseBallotBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformInverseBallot"), Values("%bool"), |
| Values(spv::Scope::Subgroup), |
| Values("%true", "%false", "%u32_0", "%int_0", "%float_0", |
| "%u32vec3_null", "%v2bool_false", "%v4float_null", |
| "%struct_null", "%v4int_null"), |
| Values("Value must be a 4-component unsigned integer vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitExtractGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitExtract"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%u32vec4_null %u32_0"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotBitExtractBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitExtract"), |
| Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct", "%v4int"), |
| Values(spv::Scope::Subgroup), Values("%u32vec4_null %u32_0"), |
| Values("Result must be a boolean scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotBitExtractBadOperand1, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitExtract"), Values("%bool"), |
| Values(spv::Scope::Subgroup), |
| Values("%true %u32_0", "%false %u32_0", "%u32_0 %u32_0", |
| "%int_0 %u32_0", "%float_0 %u32_0", "%u32vec3_null %u32_0", |
| "%v2bool_false %u32_0", "%v4float_null %u32_0", |
| "%struct_null %u32_0", "%v4int_null %u32_0"), |
| Values("Value must be a 4-component unsigned integer vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotBitExtractBadOperand2, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotBitExtract"), Values("%bool"), |
| Values(spv::Scope::Subgroup), |
| Values("%u32vec4_null %true", "%u32vec4_null %false", |
| "%u32vec4_null %int_0", "%u32vec4_null %float_0", |
| "%u32vec4_null %u32vec3_null", "%u32vec4_null %v2bool_false", |
| "%u32vec4_null %v4float_null", "%u32vec4_null %struct_null", |
| "%u32vec4_null %v4int_null"), |
| Values("Id must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotFindGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotFindLSB", |
| "OpGroupNonUniformBallotFindMSB"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("%u32vec4_null"), Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotFindBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotFindLSB", |
| "OpGroupNonUniformBallotFindMSB"), |
| Values("%void", "%bool", "%int", "%float", "%u32vec4", "%u32vec3", |
| "%v2bool", "%v4float", "%struct", "%v4int"), |
| Values(spv::Scope::Subgroup), Values("%u32vec4_null"), |
| Values("Result must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBallotFindBadOperand, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformBallotFindLSB", |
| "OpGroupNonUniformBallotFindMSB"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("%true", "%false", "%u32_0", "%int_0", "%float_0", |
| "%u32vec3_null", "%v2bool_false", "%v4float_null", |
| "%struct_null", "%v4int_null"), |
| Values("Value must be a 4-component unsigned integer vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformSMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32", "%int", "%u32vec4", "%u32vec3", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0", |
| "PartitionedReduceNV match_res %u32vec4_null", |
| "PartitionedInclusiveScanNV match_res %u32vec4_null", |
| "PartitionedExclusiveScanNV match_res %v4int_null"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformSMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%bool", "%float", "%v4float", "%struct"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values("Result must be an integer scalar or vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticBadValue, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformSMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%int", "%u32vec4", "%u32vec3", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce %u32_0", "InclusiveScan %u32_0", |
| "ExclusiveScan %u32_0", "ClusteredReduce %u32_0 %u32_0"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticMissingClusterSize, GroupNonUniform, |
| Combine( |
| Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res"), |
| Values( |
| "ClusterSize must be present when Operation is ClusteredReduce"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticMissingBallot, GroupNonUniform, |
| Combine( |
| Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("PartitionedReduceNV match_res", |
| "PartitionedInclusiveScanNV match_res", |
| "PartitionedExclusiveScanNV match_res"), |
| Values("Ballot must be present when Operation is PartitionedReduceNV, " |
| "PartitionedInclusiveScanNV, or PartitionedExclusiveScanNV"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticBadClusterSizeType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %true", |
| "ClusteredReduce match_res %false", |
| "ClusteredReduce match_res %int_0", |
| "ClusteredReduce match_res %float_0", |
| "ClusteredReduce match_res %u32vec4_null", |
| "ClusteredReduce match_res %u32vec3_null", |
| "ClusteredReduce match_res %v2bool_false", |
| "ClusteredReduce match_res %v4float_null", |
| "ClusteredReduce match_res %struct_null", |
| "ClusteredReduce match_res %v4int_null"), |
| Values("ClusterSize must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticBadBallotType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("PartitionedReduceNV match_res %true", |
| "PartitionedReduceNV match_res %false", |
| "PartitionedReduceNV match_res %int_0", |
| "PartitionedReduceNV match_res %float_0", |
| "PartitionedReduceNV match_res %u32_0", |
| "PartitionedReduceNV match_res %u32vec3_null", |
| "PartitionedReduceNV match_res %v2bool_false", |
| "PartitionedReduceNV match_res %v4float_null", |
| "PartitionedReduceNV match_res %struct_null"), |
| Values("Ballot must be a 4-component integer vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformIntegerArithmeticClusterSizeNotConstant, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", |
| "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", |
| "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", |
| "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", |
| "OpGroupNonUniformBitwiseXor"), |
| Values("%u32"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %u32_undef"), |
| Values("ClusterSize must be a constant instruction"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformUnsignedIntegerArithmeticGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"), |
| Values("%u32", "%u32vec4", "%u32vec3"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformUnsignedIntegerArithmeticBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"), |
| Values("%bool", "%int", "%float", "%v4float", "%struct", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values("Result must be an unsigned integer scalar or vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformUnsignedIntegerArithmeticBadValue, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"), |
| Values("%u32vec4", "%u32vec3"), Values(spv::Scope::Subgroup), |
| Values("Reduce %u32_0", "InclusiveScan %u32_0", |
| "ExclusiveScan %u32_0", "ClusteredReduce %u32_0 %u32_0"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%float", "%v4float"), Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%bool", "%u32", "%int", "%u32vec4", "%u32vec3", "%struct", |
| "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values("Result must be a floating-point scalar or vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticBadValue, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%v4float"), Values(spv::Scope::Subgroup), |
| Values("Reduce %float_0", "InclusiveScan %float_0", |
| "ExclusiveScan %float_0", "ClusteredReduce %float_0 %u32_0"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticMissingClusterSize, GroupNonUniform, |
| Combine( |
| Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%float"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res"), |
| Values( |
| "ClusterSize must be present when Operation is ClusteredReduce"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticBadClusterSizeType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%float"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %true", |
| "ClusteredReduce match_res %false", |
| "ClusteredReduce match_res %int_0", |
| "ClusteredReduce match_res %float_0", |
| "ClusteredReduce match_res %u32vec4_null", |
| "ClusteredReduce match_res %u32vec3_null", |
| "ClusteredReduce match_res %v2bool_false", |
| "ClusteredReduce match_res %v4float_null", |
| "ClusteredReduce match_res %struct_null", |
| "ClusteredReduce match_res %v4int_null"), |
| Values("ClusterSize must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformFloatArithmeticClusterSizeNotConstant, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", |
| "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), |
| Values("%float"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %u32_undef"), |
| Values("ClusterSize must be a constant instruction"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticGood, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%bool", "%v2bool"), Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values(""))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticBadResultType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%u32", "%int", "%float", "%u32vec4", "%u32vec3", "%struct", |
| "%v4float", "%v4int"), |
| Values(spv::Scope::Subgroup), |
| Values("Reduce match_res", "InclusiveScan match_res", |
| "ExclusiveScan match_res", |
| "ClusteredReduce match_res %u32_0"), |
| Values("Result must be a boolean scalar or vector"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticBadValue, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%v2bool"), Values(spv::Scope::Subgroup), |
| Values("Reduce %true", "InclusiveScan %true", |
| "ExclusiveScan %false", "ClusteredReduce %false %u32_0"), |
| Values("The type of Value must match the Result type"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticMissingClusterSize, GroupNonUniform, |
| Combine( |
| Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res"), |
| Values( |
| "ClusterSize must be present when Operation is ClusteredReduce"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticBadClusterSizeType, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %true", |
| "ClusteredReduce match_res %false", |
| "ClusteredReduce match_res %int_0", |
| "ClusteredReduce match_res %float_0", |
| "ClusteredReduce match_res %u32vec4_null", |
| "ClusteredReduce match_res %u32vec3_null", |
| "ClusteredReduce match_res %v2bool_false", |
| "ClusteredReduce match_res %v4float_null", |
| "ClusteredReduce match_res %struct_null", |
| "ClusteredReduce match_res %v4int_null"), |
| Values("ClusterSize must be an unsigned integer scalar"))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GroupNonUniformBooleanArithmeticClusterSizeNotConstant, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr", |
| "OpGroupNonUniformLogicalXor"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("ClusteredReduce match_res %u32_undef"), |
| Values("ClusterSize must be a constant instruction"))); |
| |
| // Subgroup scope is not actual parameter, but used for test expectations, |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuadAllKHR, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformQuadAllKHR"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true"), Values(""))); |
| |
| // Subgroup scope is not actual parameter, but used for test expectations, |
| INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuadAnyKHR, GroupNonUniform, |
| Combine(Values("OpGroupNonUniformQuadAnyKHR"), |
| Values("%bool"), Values(spv::Scope::Subgroup), |
| Values("%true"), Values(""))); |
| |
| TEST_F(ValidateGroupNonUniform, VulkanGroupNonUniformBallotBitCountOperation) { |
| std::string test = R"( |
| OpCapability Shader |
| OpCapability GroupNonUniform |
| OpCapability GroupNonUniformBallot |
| OpCapability GroupNonUniformClustered |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %u32 = OpTypeInt 32 0 |
| %u32vec4 = OpTypeVector %u32 4 |
| %u32_0 = OpConstant %u32 0 |
| %u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0 |
| %subgroup = OpConstant %u32 3 |
| %main = OpFunction %void None %func |
| %main_entry = OpLabel |
| %result = OpGroupNonUniformBallotBitCount %u32 %subgroup ClusteredReduce %u32vec4_null |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CompileSuccessfully(test, SPV_ENV_VULKAN_1_1); |
| ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| AnyVUID("VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685")); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| HasSubstr( |
| "In Vulkan: The OpGroupNonUniformBallotBitCount group operation must " |
| "be only: Reduce, InclusiveScan, or ExclusiveScan.")); |
| } |
| |
| TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p4) { |
| const std::string text = R"( |
| OpCapability Shader |
| OpCapability GroupNonUniformBallot |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %var |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| OpDecorate %struct Block |
| OpMemberDecorate %struct 0 Offset 0 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %int_0 = OpConstant %int 0 |
| %subgroup = OpConstant %int 3 |
| %struct = OpTypeStruct %int |
| %ptr_struct = OpTypePointer StorageBuffer %struct |
| %ptr_int = OpTypePointer StorageBuffer %int |
| %var = OpVariable %ptr_struct StorageBuffer |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| %gep = OpAccessChain %ptr_int %var %int_0 |
| %ld = OpLoad %int %gep |
| %broadcast = OpGroupNonUniformBroadcast %int %subgroup %int_0 %ld |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, |
| ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| HasSubstr("Before SPIR-V 1.5, Id must be a constant instruction")); |
| } |
| |
| TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p5) { |
| const std::string text = R"( |
| OpCapability Shader |
| OpCapability GroupNonUniformBallot |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %var |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| OpDecorate %struct Block |
| OpMemberDecorate %struct 0 Offset 0 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %int_0 = OpConstant %int 0 |
| %subgroup = OpConstant %int 3 |
| %struct = OpTypeStruct %int |
| %ptr_struct = OpTypePointer StorageBuffer %struct |
| %ptr_int = OpTypePointer StorageBuffer %int |
| %var = OpVariable %ptr_struct StorageBuffer |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| %gep = OpAccessChain %ptr_int %var %int_0 |
| %ld = OpLoad %int %gep |
| %broadcast = OpGroupNonUniformBroadcast %int %subgroup %int_0 %ld |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_5); |
| EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); |
| } |
| |
| TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p4) { |
| const std::string text = R"( |
| OpCapability Shader |
| OpCapability GroupNonUniformQuad |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %var |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| OpDecorate %struct Block |
| OpMemberDecorate %struct 0 Offset 0 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %int_0 = OpConstant %int 0 |
| %subgroup = OpConstant %int 3 |
| %struct = OpTypeStruct %int |
| %ptr_struct = OpTypePointer StorageBuffer %struct |
| %ptr_int = OpTypePointer StorageBuffer %int |
| %var = OpVariable %ptr_struct StorageBuffer |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| %gep = OpAccessChain %ptr_int %var %int_0 |
| %ld = OpLoad %int %gep |
| %broadcast = OpGroupNonUniformQuadBroadcast %int %subgroup %int_0 %ld |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); |
| EXPECT_EQ(SPV_ERROR_INVALID_DATA, |
| ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); |
| EXPECT_THAT( |
| getDiagnosticString(), |
| HasSubstr("Before SPIR-V 1.5, Index must be a constant instruction")); |
| } |
| |
| TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p5) { |
| const std::string text = R"( |
| OpCapability Shader |
| OpCapability GroupNonUniformQuad |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %var |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| OpDecorate %struct Block |
| OpMemberDecorate %struct 0 Offset 0 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %int_0 = OpConstant %int 0 |
| %subgroup = OpConstant %int 3 |
| %struct = OpTypeStruct %int |
| %ptr_struct = OpTypePointer StorageBuffer %struct |
| %ptr_int = OpTypePointer StorageBuffer %int |
| %var = OpVariable %ptr_struct StorageBuffer |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| %gep = OpAccessChain %ptr_int %var %int_0 |
| %ld = OpLoad %int %gep |
| %broadcast = OpGroupNonUniformQuadBroadcast %int %subgroup %int_0 %ld |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_5); |
| EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); |
| } |
| |
| } // namespace |
| } // namespace val |
| } // namespace spvtools |