Unverified Commit 74e8f05b by Jesse Hall Committed by GitHub

Implement GL_EXT_terminate_invocation (#2454)

* Implement GL_EXT_terminate_invocation. * terminateInvocation: declare the SPV extension * Update test results for spirv-tools and bison version bumps Co-authored-by: 's avatarJohn Kessenich <cepheus@frii.com>
parent 383eaf32
...@@ -49,4 +49,6 @@ static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_s ...@@ -49,4 +49,6 @@ static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_s
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate"; static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate";
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H
...@@ -3458,6 +3458,10 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T ...@@ -3458,6 +3458,10 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
case glslang::EOpKill: case glslang::EOpKill:
builder.makeDiscard(); builder.makeDiscard();
break; break;
case glslang::EOpTerminateInvocation:
builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
builder.makeTerminateInvocation();
break;
case glslang::EOpBreak: case glslang::EOpBreak:
if (breakForLoop.top()) if (breakForLoop.top())
builder.createLoopExit(); builder.createLoopExit();
......
...@@ -1454,6 +1454,13 @@ void Builder::makeDiscard() ...@@ -1454,6 +1454,13 @@ void Builder::makeDiscard()
} }
// Comments in header // Comments in header
void Builder::makeTerminateInvocation()
{
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpTerminateInvocation)));
createAndSetNoPredecessorBlock("post-terminate-invocation");
}
// Comments in header
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer) Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
{ {
Id pointerType = makePointer(storageClass, type); Id pointerType = makePointer(storageClass, type);
......
...@@ -357,8 +357,9 @@ public: ...@@ -357,8 +357,9 @@ public:
// Generate all the code needed to finish up a function. // Generate all the code needed to finish up a function.
void leaveFunction(); void leaveFunction();
// Create a discard. // Create a discard or terminate-invocation.
void makeDiscard(); void makeDiscard();
void makeTerminateInvocation();
// Create a global or function local or IO variable. // Create a global or function local or IO variable.
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr, Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
......
...@@ -1336,6 +1336,8 @@ const char* OpcodeString(int op) ...@@ -1336,6 +1336,8 @@ const char* OpcodeString(int op)
case 365: return "OpGroupNonUniformQuadBroadcast"; case 365: return "OpGroupNonUniformQuadBroadcast";
case 366: return "OpGroupNonUniformQuadSwap"; case 366: return "OpGroupNonUniformQuadSwap";
case OpTerminateInvocation: return "OpTerminateInvocation";
case 4421: return "OpSubgroupBallotKHR"; case 4421: return "OpSubgroupBallotKHR";
case 4422: return "OpSubgroupFirstInvocationKHR"; case 4422: return "OpSubgroupFirstInvocationKHR";
case 4428: return "OpSubgroupAllKHR"; case 4428: return "OpSubgroupAllKHR";
...@@ -1504,6 +1506,7 @@ void Parameterize() ...@@ -1504,6 +1506,7 @@ void Parameterize()
InstructionDesc[OpBranchConditional].setResultAndType(false, false); InstructionDesc[OpBranchConditional].setResultAndType(false, false);
InstructionDesc[OpSwitch].setResultAndType(false, false); InstructionDesc[OpSwitch].setResultAndType(false, false);
InstructionDesc[OpKill].setResultAndType(false, false); InstructionDesc[OpKill].setResultAndType(false, false);
InstructionDesc[OpTerminateInvocation].setResultAndType(false, false);
InstructionDesc[OpReturn].setResultAndType(false, false); InstructionDesc[OpReturn].setResultAndType(false, false);
InstructionDesc[OpReturnValue].setResultAndType(false, false); InstructionDesc[OpReturnValue].setResultAndType(false, false);
InstructionDesc[OpUnreachable].setResultAndType(false, false); InstructionDesc[OpUnreachable].setResultAndType(false, false);
......
...@@ -1849,6 +1849,7 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { ...@@ -1849,6 +1849,7 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpBranchConditional: *hasResult = false; *hasResultType = false; break; case OpBranchConditional: *hasResult = false; *hasResultType = false; break;
case OpSwitch: *hasResult = false; *hasResultType = false; break; case OpSwitch: *hasResult = false; *hasResultType = false; break;
case OpKill: *hasResult = false; *hasResultType = false; break; case OpKill: *hasResult = false; *hasResultType = false; break;
case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break;
case OpReturn: *hasResult = false; *hasResultType = false; break; case OpReturn: *hasResult = false; *hasResultType = false; break;
case OpReturnValue: *hasResult = false; *hasResultType = false; break; case OpReturnValue: *hasResult = false; *hasResultType = false; break;
case OpUnreachable: *hasResult = false; *hasResultType = false; break; case OpUnreachable: *hasResult = false; *hasResultType = false; break;
......
...@@ -263,6 +263,7 @@ public: ...@@ -263,6 +263,7 @@ public:
case OpBranchConditional: case OpBranchConditional:
case OpSwitch: case OpSwitch:
case OpKill: case OpKill:
case OpTerminateInvocation:
case OpReturn: case OpReturn:
case OpReturnValue: case OpReturnValue:
case OpUnreachable: case OpUnreachable:
......
cppDeepNest.frag cppDeepNest.frag
ERROR: 0:66: '#if/#ifdef/#ifndef' : maximum nesting depth exceeded ERROR: 0:66: '#if/#ifdef/#ifndef' : maximum nesting depth exceeded
ERROR: 0:66: '' : missing #endif ERROR: 0:66: '' : missing #endif
ERROR: 0:66: '' : syntax error, unexpected $end ERROR: 0:66: '' : syntax error, unexpected end of file
ERROR: 3 compilation errors. No code generated. ERROR: 3 compilation errors. No code generated.
......
...@@ -12,7 +12,7 @@ ERROR: 0:88: '' : float literal needs a decimal point or exponent ...@@ -12,7 +12,7 @@ ERROR: 0:88: '' : float literal needs a decimal point or exponent
ERROR: 0:98: '' : numeric literal too big ERROR: 0:98: '' : numeric literal too big
ERROR: 0:101: '' : numeric literal too big ERROR: 0:101: '' : numeric literal too big
ERROR: 0:104: '#' : preprocessor directive cannot be preceded by another token ERROR: 0:104: '#' : preprocessor directive cannot be preceded by another token
ERROR: 0:104: '' : syntax error, unexpected $end, expecting COMMA or SEMICOLON ERROR: 0:104: '' : syntax error, unexpected end of file, expecting COMMA or SEMICOLON
ERROR: 14 compilation errors. No code generated. ERROR: 14 compilation errors. No code generated.
......
spv.terminate.frag
// Module Version 10000
// Generated by (magic number): 8000a
// Id's are bound by 7
Capability Shader
Extension "SPV_KHR_terminate_invocation"
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main"
ExecutionMode 4 OriginUpperLeft
Source GLSL 400
SourceExtension "GL_EXT_terminate_invocation"
Name 4 "main"
2: TypeVoid
3: TypeFunction 2
4(main): 2 Function None 3
5: Label
TerminateInvocation
FunctionEnd
terminate.frag
ERROR: 0:3: 'terminateInvocation' : undeclared identifier
ERROR: 0:9: '' : syntax error, unexpected TERMINATE_INVOCATION, expecting COMMA or SEMICOLON
ERROR: 2 compilation errors. No code generated.
Shader version: 400
Requested GL_EXT_terminate_invocation
ERROR: node is still EOpNull!
0:3 Function Definition: foo( ( global void)
0:3 Function Parameters:
0:3 Sequence
0:3 'terminateInvocation' ( temp float)
0:? Linker Objects
Linked fragment stage:
Shader version: 400
Requested GL_EXT_terminate_invocation
ERROR: node is still EOpNull!
0:? Linker Objects
terminate.vert
ERROR: 0:3: 'terminateInvocation' : undeclared identifier
ERROR: 0:9: 'terminateInvocation' : not supported in this stage: vertex
ERROR: 2 compilation errors. No code generated.
Shader version: 400
Requested GL_EXT_terminate_invocation
ERROR: node is still EOpNull!
0:3 Function Definition: foo( ( global void)
0:3 Function Parameters:
0:3 Sequence
0:3 'terminateInvocation' ( temp float)
0:7 Function Definition: main( ( global void)
0:7 Function Parameters:
0:9 Sequence
0:9 Branch: TerminateInvocation
0:? Linker Objects
0:? 'gl_VertexID' ( gl_VertexId int VertexId)
0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId)
Linked vertex stage:
Shader version: 400
Requested GL_EXT_terminate_invocation
ERROR: node is still EOpNull!
0:7 Function Definition: main( ( global void)
0:7 Function Parameters:
0:9 Sequence
0:9 Branch: TerminateInvocation
0:? Linker Objects
0:? 'gl_VertexID' ( gl_VertexId int VertexId)
0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId)
#version 400
#extension GL_EXT_terminate_invocation : enable
void main()
{
terminateInvocation;
}
#version 400
void foo() { terminateInvocation; } // ERROR: identifier undeclared
#extension GL_EXT_terminate_invocation : enable
void main()
{
int terminateInvocation; // syntax ERROR
}
#version 400
void foo() { terminateInvocation; } // ERROR: identifier undeclared
#extension GL_EXT_terminate_invocation : enable
void main()
{
terminateInvocation; // ERROR: wrong stage
}
...@@ -628,13 +628,14 @@ enum TOperator { ...@@ -628,13 +628,14 @@ enum TOperator {
// Branch // Branch
// //
EOpKill, // Fragment only EOpKill, // Fragment only
EOpTerminateInvocation, // Fragment only
EOpDemote, // Fragment only
EOpReturn, EOpReturn,
EOpBreak, EOpBreak,
EOpContinue, EOpContinue,
EOpCase, EOpCase,
EOpDefault, EOpDefault,
EOpDemote, // Fragment only
// //
// Constructors // Constructors
......
...@@ -365,6 +365,7 @@ void TScanContext::fillInKeywordMap() ...@@ -365,6 +365,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["if"] = IF; (*KeywordMap)["if"] = IF;
(*KeywordMap)["else"] = ELSE; (*KeywordMap)["else"] = ELSE;
(*KeywordMap)["discard"] = DISCARD; (*KeywordMap)["discard"] = DISCARD;
(*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION;
(*KeywordMap)["return"] = RETURN; (*KeywordMap)["return"] = RETURN;
(*KeywordMap)["void"] = VOID; (*KeywordMap)["void"] = VOID;
(*KeywordMap)["bool"] = BOOL; (*KeywordMap)["bool"] = BOOL;
...@@ -936,6 +937,11 @@ int TScanContext::tokenizeIdentifier() ...@@ -936,6 +937,11 @@ int TScanContext::tokenizeIdentifier()
case CASE: case CASE:
return keyword; return keyword;
case TERMINATE_INVOCATION:
if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation))
return identifierOrType();
return keyword;
case BUFFER: case BUFFER:
afterBuffer = true; afterBuffer = true;
if ((parseContext.isEsProfile() && parseContext.version < 310) || if ((parseContext.isEsProfile() && parseContext.version < 310) ||
......
...@@ -329,6 +329,7 @@ void TParseVersions::initializeExtensionBehavior() ...@@ -329,6 +329,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable; extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable; extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable;
// OVR extensions // OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable; extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
...@@ -411,7 +412,7 @@ void TParseVersions::getPreamble(std::string& preamble) ...@@ -411,7 +412,7 @@ void TParseVersions::getPreamble(std::string& preamble)
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n"; preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
} }
} else { } else { // !isEsProfile()
preamble = preamble =
"#define GL_FRAGMENT_PRECISION_HIGH 1\n" "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
"#define GL_ARB_texture_rectangle 1\n" "#define GL_ARB_texture_rectangle 1\n"
...@@ -563,6 +564,11 @@ void TParseVersions::getPreamble(std::string& preamble) ...@@ -563,6 +564,11 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_GOOGLE_include_directive 1\n" "#define GL_GOOGLE_include_directive 1\n"
"#define GL_KHR_blend_equation_advanced 1\n" "#define GL_KHR_blend_equation_advanced 1\n"
; ;
// other general extensions
preamble +=
"#define GL_EXT_terminate_invocation 1\n"
;
#endif #endif
// #define VULKAN XXXX // #define VULKAN XXXX
......
...@@ -299,6 +299,7 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad ...@@ -299,6 +299,7 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float"; const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
......
...@@ -293,6 +293,7 @@ GLSLANG_WEB_EXCLUDE_OFF ...@@ -293,6 +293,7 @@ GLSLANG_WEB_EXCLUDE_OFF
%token <lex> CENTROID IN OUT INOUT %token <lex> CENTROID IN OUT INOUT
%token <lex> STRUCT VOID WHILE %token <lex> STRUCT VOID WHILE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> TERMINATE_INVOCATION
%token <lex> UNIFORM SHARED BUFFER %token <lex> UNIFORM SHARED BUFFER
%token <lex> FLAT SMOOTH LAYOUT %token <lex> FLAT SMOOTH LAYOUT
...@@ -3927,6 +3928,10 @@ jump_statement ...@@ -3927,6 +3928,10 @@ jump_statement
parseContext.requireStage($1.loc, EShLangFragment, "discard"); parseContext.requireStage($1.loc, EShLangFragment, "discard");
$$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc);
} }
| TERMINATE_INVOCATION SEMICOLON {
parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation");
$$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc);
}
; ;
// Grammar Note: No 'goto'. Gotos are not supported. // Grammar Note: No 'goto'. Gotos are not supported.
......
...@@ -293,6 +293,7 @@ extern int yylex(YYSTYPE*, TParseContext&); ...@@ -293,6 +293,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> CENTROID IN OUT INOUT %token <lex> CENTROID IN OUT INOUT
%token <lex> STRUCT VOID WHILE %token <lex> STRUCT VOID WHILE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> TERMINATE_INVOCATION
%token <lex> UNIFORM SHARED BUFFER %token <lex> UNIFORM SHARED BUFFER
%token <lex> FLAT SMOOTH LAYOUT %token <lex> FLAT SMOOTH LAYOUT
...@@ -3927,6 +3928,10 @@ jump_statement ...@@ -3927,6 +3928,10 @@ jump_statement
parseContext.requireStage($1.loc, EShLangFragment, "discard"); parseContext.requireStage($1.loc, EShLangFragment, "discard");
$$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc);
} }
| TERMINATE_INVOCATION SEMICOLON {
parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation");
$$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc);
}
; ;
// Grammar Note: No 'goto'. Gotos are not supported. // Grammar Note: No 'goto'. Gotos are not supported.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -1409,14 +1409,15 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node) ...@@ -1409,14 +1409,15 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
OutputTreeText(out, node, depth); OutputTreeText(out, node, depth);
switch (node->getFlowOp()) { switch (node->getFlowOp()) {
case EOpKill: out.debug << "Branch: Kill"; break; case EOpKill: out.debug << "Branch: Kill"; break;
case EOpBreak: out.debug << "Branch: Break"; break; case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break;
case EOpContinue: out.debug << "Branch: Continue"; break; case EOpBreak: out.debug << "Branch: Break"; break;
case EOpReturn: out.debug << "Branch: Return"; break; case EOpContinue: out.debug << "Branch: Continue"; break;
case EOpCase: out.debug << "case: "; break; case EOpReturn: out.debug << "Branch: Return"; break;
case EOpDemote: out.debug << "Demote"; break; case EOpCase: out.debug << "case: "; break;
case EOpDefault: out.debug << "default: "; break; case EOpDemote: out.debug << "Demote"; break;
default: out.debug << "Branch: Unknown Branch"; break; case EOpDefault: out.debug << "default: "; break;
default: out.debug << "Branch: Unknown Branch"; break;
} }
if (node->getExpression()) { if (node->getExpression()) {
......
...@@ -278,6 +278,8 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -278,6 +278,8 @@ INSTANTIATE_TEST_SUITE_P(
"glsl.es320.subgroupShuffleRelative.comp", "glsl.es320.subgroupShuffleRelative.comp",
"glsl.es320.subgroupQuad.comp", "glsl.es320.subgroupQuad.comp",
"glsl.es320.subgroupVote.comp", "glsl.es320.subgroupVote.comp",
"terminate.frag",
"terminate.vert",
})), })),
FileNameAsCustomTestSuffix FileNameAsCustomTestSuffix
); );
......
...@@ -436,6 +436,7 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -436,6 +436,7 @@ INSTANTIATE_TEST_SUITE_P(
"spv.specConstant.int16.comp", "spv.specConstant.int16.comp",
"spv.specConstant.int8.comp", "spv.specConstant.int8.comp",
"spv.storageBuffer.vert", "spv.storageBuffer.vert",
"spv.terminate.frag",
"spv.precise.tese", "spv.precise.tese",
"spv.precise.tesc", "spv.precise.tesc",
"spv.volatileAtomic.comp", "spv.volatileAtomic.comp",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment