Non-Semantic can be looked at as just a special case of an extended instruction set
The addition of the SPV_KHR_non_semantic_info extension adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module. This uses the OpExtInstImport and OpExtInst instructions.
This was added so tools such as the Vulkan Validation Layers, RenderDoc, etc could inject SPIR-V instructions to aid in tooling without worrying about the implementation compiler crashing from an unknown instruction.
The following will be using the Debug Printf non-semantic instruction as an example.
Taking a GLSL shader of
#version 450
#extension GL_EXT_debug_printf : enable
void main() {
float myfloat = 2.0;
debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat);
}
the output SPIR-V disassembly roughly looks like
OpExtension "SPV_KHR_non_semantic_info"
%13 = OpExtInstImport "NonSemantic.DebugPrintf"
%2 = OpTypeVoid
%10 = OpString "Here are two float values %f, %f"
OpSourceExtension "GL_EXT_debug_printf"
%14 = %2 OpExtInst %13 %1 %10 %11 %12
Breaking this down:
- First need to make sure the
SPV_KHR_non_semantic_info
is enabled - Need to import the name of the non-semantic extension being added with
OpExtInstImport
- Use
OpExtInst
- Set the
Set
field to the imported non-semantic extension - Set the
Instruction
to the non-semantic extension specific instruction being added- For
DebugPrintf
it is listed as being instruction1
in the extension spec
- For
- Set the
Some non-semantic extensions have multiple revisions. Some extensions will append the version on the end of the string, for example:
OpExtInstImport "NonSemantic.ClspvReflection.1" // revision 1
OpExtInstImport "NonSemantic.ClspvReflection.2" // revision 2
The details of versioning and the string to detect can be found per extension in the SPIRV-Registry
For those parsing the grammar, you may notice for non-semantic instruction there are no references to ValueEnum
or BitEnum
. So instead of having something such as
{ "kind" : "SomeEnumName", "name" : "'Value'" },
everything will be an IdRef
that points to an OpConstant
or OpString
instead
{ "kind" : "IdRef", "name" : "'Value'" },
More information can be found in OpExtInstImport, but this is done so if someone introduced a new non-semantic instruction, things will not break from under an old parser.
Set of instructions to get a non-semantic extension added
- Add to the SPIRV-Registry repo
- Add to the SPIRV-Headers repo
- Add a grammar file at
include/spirv/unified1/extinst.nonsemantic.<INSERT_NAME>.grammar.json
- Add line to bottom of the generator script
mk_extinst('NonSemantic<INSERT_NAME>', 'extinst.nonsemantic.<INSERT_NAME>.grammar.json')
- Run script (as described in the README) to generate the C header file.
- Example PR
- Add a grammar file at