Skip to content

Commit b951948

Browse files
SPV_KHR_quad_control (KhronosGroup#5547)
* SPV_KHR_quad_control 1. Add two new execute modes: RequireFullQuadsKHR and QuadDerivativesKHR 2. Add two opCodes: OpGroupNonUniformQuadAllKHR and OpGroupNonUniformQuadAnyKHR 3. Add one Capability: QuadControlKHR * update DEPS * Fixes * Build fixes * Formatting fixes * Test fixes * formatting --------- Co-authored-by: Alan Baker <[email protected]>
1 parent 69197ba commit b951948

File tree

8 files changed

+232
-8
lines changed

8 files changed

+232
-8
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ vars = {
1313
'protobuf_revision': 'v21.12',
1414

1515
're2_revision': '264e71e88e1c8a4b5ec326e70e9cf1d476f58a58',
16-
'spirv_headers_revision': 'ae6a8b39717523d96683bc0d20b541944e28072f',
16+
'spirv_headers_revision': '5aa1dd8a11182ea9a6a0eabd6a9edc639d5dbecd',
1717
}
1818

1919
deps = {

source/opcode.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,8 @@ bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode) {
534534
case spv::Op::OpGroupNonUniformQuadBroadcast:
535535
case spv::Op::OpGroupNonUniformQuadSwap:
536536
case spv::Op::OpGroupNonUniformRotateKHR:
537+
case spv::Op::OpGroupNonUniformQuadAllKHR:
538+
case spv::Op::OpGroupNonUniformQuadAnyKHR:
537539
return true;
538540
default:
539541
return false;

source/val/validate_mode_setting.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,17 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
557557
"model.";
558558
}
559559
break;
560+
case spv::ExecutionMode::QuadDerivativesKHR:
561+
if (!std::all_of(models->begin(), models->end(),
562+
[](const spv::ExecutionModel& model) {
563+
return (model == spv::ExecutionModel::Fragment ||
564+
model == spv::ExecutionModel::GLCompute);
565+
})) {
566+
return _.diag(SPV_ERROR_INVALID_DATA, inst)
567+
<< "Execution mode can only be used with the Fragment or "
568+
"GLCompute execution model.";
569+
}
570+
break;
560571
case spv::ExecutionMode::PixelCenterInteger:
561572
case spv::ExecutionMode::OriginUpperLeft:
562573
case spv::ExecutionMode::OriginLowerLeft:
@@ -581,6 +592,7 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
581592
case spv::ExecutionMode::StencilRefUnchangedBackAMD:
582593
case spv::ExecutionMode::StencilRefGreaterBackAMD:
583594
case spv::ExecutionMode::StencilRefLessBackAMD:
595+
case spv::ExecutionMode::RequireFullQuadsKHR:
584596
if (!std::all_of(models->begin(), models->end(),
585597
[](const spv::ExecutionModel& model) {
586598
return model == spv::ExecutionModel::Fragment;

source/val/validate_non_uniform.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,9 +422,14 @@ spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) {
422422
const spv::Op opcode = inst->opcode();
423423

424424
if (spvOpcodeIsNonUniformGroupOperation(opcode)) {
425-
const uint32_t execution_scope = inst->GetOperandAs<uint32_t>(2);
426-
if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
427-
return error;
425+
// OpGroupNonUniformQuadAllKHR and OpGroupNonUniformQuadAnyKHR don't have
426+
// scope paramter
427+
if ((opcode != spv::Op::OpGroupNonUniformQuadAllKHR) &&
428+
(opcode != spv::Op::OpGroupNonUniformQuadAnyKHR)) {
429+
const uint32_t execution_scope = inst->GetOperandAs<uint32_t>(2);
430+
if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
431+
return error;
432+
}
428433
}
429434
}
430435

source/val/validate_scopes.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
9797
// Vulkan 1.1 specific rules
9898
if (_.context()->target_env != SPV_ENV_VULKAN_1_0) {
9999
// Scope for Non Uniform Group Operations must be limited to Subgroup
100-
if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
101-
value != spv::Scope::Subgroup) {
100+
if ((spvOpcodeIsNonUniformGroupOperation(opcode) &&
101+
(opcode != spv::Op::OpGroupNonUniformQuadAllKHR) &&
102+
(opcode != spv::Op::OpGroupNonUniformQuadAnyKHR)) &&
103+
(value != spv::Scope::Subgroup)) {
102104
return _.diag(SPV_ERROR_INVALID_DATA, inst)
103105
<< _.VkErrorID(4642) << spvOpcodeString(opcode)
104106
<< ": in Vulkan environment Execution scope is limited to "
@@ -178,6 +180,8 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
178180
// Scope for execution must be limited to Workgroup or Subgroup for
179181
// non-uniform operations
180182
if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
183+
opcode != spv::Op::OpGroupNonUniformQuadAllKHR &&
184+
opcode != spv::Op::OpGroupNonUniformQuadAnyKHR &&
181185
value != spv::Scope::Subgroup && value != spv::Scope::Workgroup) {
182186
return _.diag(SPV_ERROR_INVALID_DATA, inst)
183187
<< spvOpcodeString(opcode)

test/val/val_modes_test.cpp

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,184 @@ OpFunctionEnd
18741874
"with the FPFastMathDefault execution mode"));
18751875
}
18761876

1877+
TEST_F(ValidateMode, FragmentShaderRequireFullQuadsKHR) {
1878+
const std::string spirv = R"(
1879+
OpCapability Shader
1880+
OpCapability GroupNonUniform
1881+
OpCapability GroupNonUniformVote
1882+
OpCapability GroupNonUniformBallot
1883+
OpCapability QuadControlKHR
1884+
OpExtension "SPV_KHR_quad_control"
1885+
%1 = OpExtInstImport "GLSL.std.450"
1886+
OpMemoryModel Logical GLSL450
1887+
OpEntryPoint GLCompute %4 "main"
1888+
OpExecutionMode %4 OriginUpperLeft
1889+
OpExecutionMode %4 RequireFullQuadsKHR
1890+
OpDecorate %17 Location 0
1891+
OpDecorate %31 BuiltIn HelperInvocation
1892+
OpDecorate %40 Location 0
1893+
OpDecorate %44 DescriptorSet 0
1894+
OpDecorate %44 Binding 0
1895+
%2 = OpTypeVoid
1896+
%3 = OpTypeFunction %2
1897+
%6 = OpTypeInt 32 0
1898+
%7 = OpTypeVector %6 4
1899+
%8 = OpTypePointer Function %7
1900+
%10 = OpTypeBool
1901+
%11 = OpConstantTrue %10
1902+
%12 = OpConstant %6 7
1903+
%14 = OpTypeFloat 32
1904+
%15 = OpTypeVector %14 4
1905+
%16 = OpTypePointer Output %15
1906+
%17 = OpVariable %16 Output
1907+
%18 = OpConstant %14 1
1908+
%19 = OpConstant %14 0
1909+
%20 = OpConstantComposite %15 %18 %19 %19 %18
1910+
%23 = OpConstant %6 4
1911+
%27 = OpConstant %6 1
1912+
%28 = OpTypePointer Output %14
1913+
%30 = OpTypePointer Input %10
1914+
%31 = OpVariable %30 Input
1915+
%36 = OpConstant %6 2
1916+
%38 = OpTypeVector %14 2
1917+
%39 = OpTypePointer Input %38
1918+
%40 = OpVariable %39 Input
1919+
%41 = OpTypeImage %14 2D 0 0 0 1 Unknown
1920+
%42 = OpTypeSampledImage %41
1921+
%43 = OpTypePointer UniformConstant %42
1922+
%44 = OpVariable %43 UniformConstant
1923+
%4 = OpFunction %2 None %3
1924+
%5 = OpLabel
1925+
%9 = OpVariable %8 Function
1926+
%13 = OpGroupNonUniformBallot %7 %12 %11
1927+
OpStore %9 %13
1928+
OpStore %17 %20
1929+
%21 = OpLoad %7 %9
1930+
%22 = OpGroupNonUniformBallotBitCount %6 %12 Reduce %21
1931+
%24 = OpIEqual %10 %22 %23
1932+
OpSelectionMerge %26 None
1933+
OpBranchConditional %24 %25 %26
1934+
%25 = OpLabel
1935+
%29 = OpAccessChain %28 %17 %27
1936+
OpStore %29 %18
1937+
OpBranch %26
1938+
%26 = OpLabel
1939+
%32 = OpLoad %10 %31
1940+
%33 = OpGroupNonUniformAny %10 %12 %32
1941+
OpSelectionMerge %35 None
1942+
OpBranchConditional %33 %34 %35
1943+
%34 = OpLabel
1944+
%37 = OpAccessChain %28 %17 %36
1945+
OpStore %37 %18
1946+
OpBranch %35
1947+
%35 = OpLabel
1948+
OpReturn
1949+
OpFunctionEnd
1950+
)";
1951+
1952+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1953+
EXPECT_THAT(SPV_ERROR_INVALID_DATA,
1954+
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1955+
EXPECT_THAT(
1956+
getDiagnosticString(),
1957+
HasSubstr(
1958+
"Execution mode can only be used with the Fragment execution model"));
1959+
}
1960+
1961+
TEST_F(ValidateMode, FragmentShaderQuadDerivativesKHR) {
1962+
const std::string spirv = R"(
1963+
OpCapability Shader
1964+
OpCapability GroupNonUniform
1965+
OpCapability GroupNonUniformVote
1966+
OpCapability QuadControlKHR
1967+
OpExtension "SPV_KHR_quad_control"
1968+
%1 = OpExtInstImport "GLSL.std.450"
1969+
OpMemoryModel Logical GLSL450
1970+
OpEntryPoint GLCompute %4 "main"
1971+
OpExecutionMode %4 OriginUpperLeft
1972+
OpExecutionMode %4 QuadDerivativesKHR
1973+
OpDecorate %12 BuiltIn FragCoord
1974+
OpDecorate %41 Location 0
1975+
OpDecorate %45 DescriptorSet 0
1976+
OpDecorate %45 Binding 0
1977+
OpDecorate %49 Location 0
1978+
%2 = OpTypeVoid
1979+
%3 = OpTypeFunction %2
1980+
%6 = OpTypeBool
1981+
%7 = OpTypePointer Function %6
1982+
%9 = OpTypeFloat 32
1983+
%10 = OpTypeVector %9 4
1984+
%11 = OpTypePointer Input %10
1985+
%12 = OpVariable %11 Input
1986+
%13 = OpTypeInt 32 0
1987+
%14 = OpConstant %13 1
1988+
%15 = OpTypePointer Input %9
1989+
%18 = OpConstant %9 8.5
1990+
%21 = OpConstant %9 0.100000001
1991+
%25 = OpConstant %13 0
1992+
%28 = OpConstant %9 3.5
1993+
%30 = OpConstant %9 6
1994+
%36 = OpConstant %13 7
1995+
%40 = OpTypePointer Output %10
1996+
%41 = OpVariable %40 Output
1997+
%42 = OpTypeImage %9 2D 0 0 0 1 Unknown
1998+
%43 = OpTypeSampledImage %42
1999+
%44 = OpTypePointer UniformConstant %43
2000+
%45 = OpVariable %44 UniformConstant
2001+
%47 = OpTypeVector %9 2
2002+
%48 = OpTypePointer Input %47
2003+
%49 = OpVariable %48 Input
2004+
%53 = OpConstant %9 0.899999976
2005+
%54 = OpConstant %9 0.200000003
2006+
%55 = OpConstant %9 1
2007+
%56 = OpConstantComposite %10 %53 %54 %54 %55
2008+
%4 = OpFunction %2 None %3
2009+
%5 = OpLabel
2010+
%8 = OpVariable %7 Function
2011+
%16 = OpAccessChain %15 %12 %14
2012+
%17 = OpLoad %9 %16
2013+
%19 = OpFSub %9 %17 %18
2014+
%20 = OpExtInst %9 %1 FAbs %19
2015+
%22 = OpFOrdLessThan %6 %20 %21
2016+
OpSelectionMerge %24 None
2017+
OpBranchConditional %22 %23 %24
2018+
%23 = OpLabel
2019+
%26 = OpAccessChain %15 %12 %25
2020+
%27 = OpLoad %9 %26
2021+
%29 = OpFSub %9 %27 %28
2022+
%31 = OpFMod %9 %29 %30
2023+
%33 = OpFOrdLessThan %6 %31 %21
2024+
OpBranch %24
2025+
%24 = OpLabel
2026+
%34 = OpPhi %6 %22 %5 %33 %23
2027+
OpStore %8 %34
2028+
%35 = OpLoad %6 %8
2029+
%37 = OpGroupNonUniformAny %6 %36 %35
2030+
OpSelectionMerge %39 None
2031+
OpBranchConditional %37 %38 %52
2032+
%38 = OpLabel
2033+
%46 = OpLoad %43 %45
2034+
%50 = OpLoad %47 %49
2035+
%51 = OpImageSampleImplicitLod %10 %46 %50
2036+
OpStore %41 %51
2037+
OpBranch %39
2038+
%52 = OpLabel
2039+
OpStore %41 %56
2040+
OpBranch %39
2041+
%39 = OpLabel
2042+
OpReturn
2043+
OpFunctionEnd
2044+
)";
2045+
2046+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2047+
EXPECT_THAT(SPV_ERROR_INVALID_DATA,
2048+
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2049+
EXPECT_THAT(
2050+
getDiagnosticString(),
2051+
HasSubstr(
2052+
"Execution mode can only be used with the Fragment execution model"));
2053+
}
2054+
18772055
} // namespace
18782056
} // namespace val
18792057
} // namespace spvtools

test/val/val_non_uniform_test.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ OpCapability GroupNonUniformArithmetic
4545
OpCapability GroupNonUniformClustered
4646
OpCapability GroupNonUniformQuad
4747
OpCapability GroupNonUniformPartitionedNV
48+
OpCapability QuadControlKHR
4849
OpExtension "SPV_NV_shader_subgroup_partitioned"
50+
OpExtension "SPV_KHR_quad_control"
4951
)";
5052

5153
ss << capabilities_and_extensions;
@@ -178,7 +180,10 @@ TEST_P(GroupNonUniform, Vulkan1p1) {
178180
std::ostringstream sstr;
179181
sstr << "%result = " << opcode << " ";
180182
sstr << type << " ";
181-
sstr << ConvertScope(execution_scope) << " ";
183+
if (opcode != "OpGroupNonUniformQuadAllKHR" &&
184+
opcode != "OpGroupNonUniformQuadAnyKHR") {
185+
sstr << ConvertScope(execution_scope) << " ";
186+
}
182187
sstr << args << "\n";
183188

184189
CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1);
@@ -218,7 +223,10 @@ TEST_P(GroupNonUniform, Spirv1p3) {
218223
std::ostringstream sstr;
219224
sstr << "%result = " << opcode << " ";
220225
sstr << type << " ";
221-
sstr << ConvertScope(execution_scope) << " ";
226+
if (opcode != "OpGroupNonUniformQuadAllKHR" &&
227+
opcode != "OpGroupNonUniformQuadAnyKHR") {
228+
sstr << ConvertScope(execution_scope) << " ";
229+
}
222230
sstr << args << "\n";
223231

224232
CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3);
@@ -869,6 +877,18 @@ INSTANTIATE_TEST_SUITE_P(
869877
Values("ClusteredReduce match_res %u32_undef"),
870878
Values("ClusterSize must be a constant instruction")));
871879

880+
// Subgroup scope is not actual parameter, but used for test expectations,
881+
INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuadAllKHR, GroupNonUniform,
882+
Combine(Values("OpGroupNonUniformQuadAllKHR"),
883+
Values("%bool"), Values(spv::Scope::Subgroup),
884+
Values("%true"), Values("")));
885+
886+
// Subgroup scope is not actual parameter, but used for test expectations,
887+
INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuadAnyKHR, GroupNonUniform,
888+
Combine(Values("OpGroupNonUniformQuadAnyKHR"),
889+
Values("%bool"), Values(spv::Scope::Subgroup),
890+
Values("%true"), Values("")));
891+
872892
TEST_F(ValidateGroupNonUniform, VulkanGroupNonUniformBallotBitCountOperation) {
873893
std::string test = R"(
874894
OpCapability Shader

tools/sva/src/spirv.data.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4376,6 +4376,9 @@ export default {
43764376
"ShaderClockKHR": {
43774377
"value": 5055
43784378
},
4379+
"QuadControlKHR": {
4380+
"value": 5087
4381+
},
43794382
"FragmentFullyCoveredEXT": {
43804383
"value": 5265
43814384
},

0 commit comments

Comments
 (0)