summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-05-18 10:09:28 -0400
committerGitHub <noreply@github.com>2022-05-18 10:09:28 -0400
commit1148564b9cdbbc8fec4fbecf65b0af60aa6af344 (patch)
treefc5ca7629aed7e60797163c33deb56a4137249b4
parentd9fd0ff3f0fc7b775de1e05570f01798fbc8baa3 (diff)
Support for `[[vk::spirv_instruction(op)]]` (#2242)
* #include an absolute path didn't work - because paths were taken to always be relative. * Add extension required by SPIRVOpDecoration into part of emit (could be a prior pass). * Add [[vk::spirv_instruction]] attribute * Add documentation for [[vk::spirv_instruction]. * Update 08-attributes.md * Update 08-attributes.md
-rw-r--r--docs/language-reference/08-attributes.md26
-rw-r--r--source/slang/core.meta.slang3
-rw-r--r--source/slang/slang-ast-modifier.h5
-rw-r--r--source/slang/slang-check-modifier.cpp3
-rw-r--r--source/slang/slang-emit-glsl.cpp2
-rw-r--r--source/slang/slang-ir-glsl-liveness.cpp10
-rw-r--r--source/slang/slang-lower-to-ir.cpp6
-rw-r--r--tests/spirv/spirv-instruction.slang17
-rw-r--r--tests/spirv/spirv-instruction.slang.expected.txt4
9 files changed, 70 insertions, 6 deletions
diff --git a/docs/language-reference/08-attributes.md b/docs/language-reference/08-attributes.md
index 4098303cf..76a739315 100644
--- a/docs/language-reference/08-attributes.md
+++ b/docs/language-reference/08-attributes.md
@@ -2,3 +2,29 @@ Attributes
==========
> Note: This section is not yet complete.
+
+## [[vk::spirv_instruction]]
+
+** SPIR-V only **
+
+This attribute is only available for Vulkan SPIR-V output via GLSLANG. In the future it could be supported via the `direct-spirv` option. The attribute will be ignored for any other target. This attribute requires the `GL_EXT_spirv_intrinsics` GLSL extension.
+
+The attibute allows access to SPIR-V intrinsics, by supplying a function declaration with the appropriate signature for the SPIR-V op and no body. The intrinsic takes a single parameter which is the integer value for the SPIR-V op.
+
+In the example below the add function, uses the mechanism to directly use the SPIR-V integer add 'op' which is 128 in this case.
+
+```HLSL
+// 128 is OpIAdd in SPIR-V
+[[vk::spirv_instruction(128)]]
+uint add(uint a, uint b);
+
+RWStructuredBuffer<uint> resultBuffer;
+
+[numthreads(4,1,1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint threadId = dispatchThreadID.x;
+ resultBuffer[threadId] = add(threadId, threadId);
+}
+```
+
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 9a09196c5..476e88e3f 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -2059,6 +2059,9 @@ attribute_syntax [vk_location(locaiton : int)] : GLSLLocationAttribute;
__attributeTarget(VarDeclBase)
attribute_syntax [vk_index(index : int)] : GLSLIndexAttribute;
+__attributeTarget(FuncDecl)
+attribute_syntax [vk_spirv_instruction(op : int)] : SPIRVInstructionOpAttribute;
+
// Statement Attributes
__attributeTarget(LoopStmt)
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
index a8185e06e..4522b7148 100644
--- a/source/slang/slang-ast-modifier.h
+++ b/source/slang/slang-ast-modifier.h
@@ -671,6 +671,11 @@ class GLSLIndexAttribute : public GLSLSimpleIntegerLayoutAttribute
SLANG_AST_CLASS(GLSLIndexAttribute)
};
+// [[vk_spirv_instruction]]
+class SPIRVInstructionOpAttribute : public Attribute
+{
+ SLANG_AST_CLASS(SPIRVInstructionOpAttribute)
+};
// TODO: for attributes that take arguments, the syntax node
// classes should provide accessors for the values of those arguments.
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index 320b980e9..1d9e30c95 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -398,7 +398,8 @@ namespace Slang
getSink()->diagnose(attr, Diagnostics::expectedSingleStringArg, attr->keywordName);
}
}
- else if (as<OutputControlPointsAttribute>(attr))
+ else if (as<OutputControlPointsAttribute>(attr) ||
+ as<SPIRVInstructionOpAttribute>(attr))
{
// Let it go thru iff single integral attribute
if (!hasIntArgs(attr, 1))
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index d9c81f14b..c1bbf813b 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -1881,6 +1881,8 @@ void GLSLSourceEmitter::emitFuncDecorationImpl(IRDecoration* decoration)
{
if (decoration->getOp() == kIROp_SPIRVOpDecoration)
{
+ m_glslExtensionTracker->requireExtension(UnownedStringSlice::fromLiteral("GL_EXT_spirv_intrinsics"));
+
m_writer->emit("spirv_instruction(id = ");
emitSimpleValue(decoration->getOperand(0));
m_writer->emit(")\n");
diff --git a/source/slang/slang-ir-glsl-liveness.cpp b/source/slang/slang-ir-glsl-liveness.cpp
index 3cfde0246..d5448a788 100644
--- a/source/slang/slang-ir-glsl-liveness.cpp
+++ b/source/slang/slang-ir-glsl-liveness.cpp
@@ -60,7 +60,6 @@ struct GLSLLivenessContext
Entry m_entries[Index(Kind::CountOf)]; /// Entry for each kind of function
- IRStringLit* m_extensionStringLiteral = nullptr; ///< The string literal holding the SPIR-V extension needed
IRInst* m_zeroIntLiteral = nullptr; ///< Zero value literal
IRType* m_spirvIntLiteralType = nullptr; ///< Int type that emits as `spirv_literal`
@@ -92,9 +91,8 @@ void GLSLLivenessContext::_addDecorations(Kind kind, IRFunc* func)
//
// m_builder.addTargetDecoration();
- // We need the spirv extension
- m_builder.addDecoration(func, kIROp_RequireGLSLExtensionDecoration, m_extensionStringLiteral);
-
+ // We don't need to explictly add the "GL_EXT_spirv_intrinsics"
+ // as it will be added on the GLSL emit, with the SPIRVOpDecoration is hit
const auto& entry = m_entries[Index(kind)];
if (entry.m_nameHintLiteral)
{
@@ -207,8 +205,10 @@ void GLSLLivenessContext::processModule()
// Zero value literal
m_zeroIntLiteral = m_builder.getIntValue(m_builder.getIntType(), 0);
+ // We don't need to explicitly add this decoration because it will be added as needed on GLSL emit
+ // m_extensionStringLiteral = m_builder.getStringValue(UnownedStringSlice::fromLiteral("GL_EXT_spirv_intrinsics"));
+
// Set up some values that will be needed on instructions
- m_extensionStringLiteral = m_builder.getStringValue(UnownedStringSlice::fromLiteral("GL_EXT_spirv_intrinsics"));
// The op values are from the SPIR-V spec
// https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#OpLifetimeStart
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 585b02a02..4ff43b697 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -7517,6 +7517,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
getBuilder()->addDecoration(irFunc, kIROp_OutputControlPointsDecoration, intLit);
}
+ if (auto attr = decl->findModifier<SPIRVInstructionOpAttribute>())
+ {
+ IRIntLit* intLit = _getIntLitFromAttribute(getBuilder(), attr);
+ getBuilder()->addDecoration(irFunc, kIROp_SPIRVOpDecoration, intLit);
+ }
+
if(decl->findModifier<UnsafeForceInlineEarlyAttribute>())
{
getBuilder()->addDecoration(irFunc, kIROp_UnsafeForceInlineEarlyDecoration);
diff --git a/tests/spirv/spirv-instruction.slang b/tests/spirv/spirv-instruction.slang
new file mode 100644
index 000000000..1f85479f9
--- /dev/null
+++ b/tests/spirv/spirv-instruction.slang
@@ -0,0 +1,17 @@
+// spirv-instruction.slang
+//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
+
+// Test using a spirv op. 128 is SpvOpIAdd
+
+[[vk::spirv_instruction(128)]]
+uint add(uint a, uint b);
+
+//TEST_INPUT:set resultBuffer = out ubuffer(data=[0 0 0 0], stride=4)
+RWStructuredBuffer<uint> resultBuffer;
+
+[numthreads(4,1,1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint threadId = dispatchThreadID.x;
+ resultBuffer[threadId] = add(threadId, threadId);
+}
diff --git a/tests/spirv/spirv-instruction.slang.expected.txt b/tests/spirv/spirv-instruction.slang.expected.txt
new file mode 100644
index 000000000..e1e8ccec4
--- /dev/null
+++ b/tests/spirv/spirv-instruction.slang.expected.txt
@@ -0,0 +1,4 @@
+0
+2
+4
+6