Updates for final Vulkan ray tracing extensions (#2466)
* Fix traceRay/executeCallable to have id instead of constant.
Update to final (non-provisional) SPIR-V capabilities
(includes review feedback)
- Change visibilty of findLinkerObjects.
See merge request GLSL/glslang!78
* Add support for OpConvertUToAccelerationStructureKHR.
GLSL : https://gitlab.khronos.org/GLSL/GLSL/-/merge_requests/60
SPV : https://gitlab.khronos.org/spirv/spirv-extensions/-/merge_requests/182
See merge request GLSL/glslang!77
* Add volatile qualifier to certain builtins for ray tracing.
See merge request GLSL/glslang!81
* make gl_RayTmaxEXT volatile in intersection shader
Vulkan Issue #2268
* Add testing for layouts on SBT
vulkan/vulkan#2230
- no layout specified should be same as std430
- explicitly test std140, std430, scalar layouts
See merge request GLSL/glslang!86
* Support for new opcodes OpIgnoreIntersectionKHR and OpTerminateRayKHR
vulkan/vulkan#2374
Add support for ignoreIntersectionEXT and terminateRayEXT as block
terminator statements.
See merge request GLSL/glslang!87
* Fix code-generation issues with global ray query variables
See merge request GLSL/glslang!88
* update dependencies for spirv-headers and tools
And update mesh shader results
* Fix indeterminate argument ordering
Authored-by: David Neto <dneto@google.com>
Co-authored-by: Ashwin Lele (NVIDIA Corporation) <alele@nvidia.com>
Co-authored-by: Neslisah <Neslisah.Torosdagli@amd.com>
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index e0b5a19..18ef64f 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -190,6 +190,7 @@
bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
void makeFunctions(const glslang::TIntermSequence&);
void makeGlobalInitializers(const glslang::TIntermSequence&);
+ void collectRayTracingLinkerObjects();
void visitFunctions(const glslang::TIntermSequence&);
void handleFunctionEntry(const glslang::TIntermAggregate* node);
void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
@@ -273,6 +274,9 @@
// requiring local translation to and from SPIR-V type on every access.
// Maps <builtin-variable-id -> AST-required-type-id>
std::unordered_map<spv::Id, spv::Id> forceType;
+
+ // Used later for generating OpTraceKHR/OpExecuteCallableKHR
+ std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[2];
};
//
@@ -1232,7 +1236,7 @@
spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
{
if (type.getBasicType() == glslang::EbtRayQuery)
- return spv::StorageClassFunction;
+ return spv::StorageClassPrivate;
if (type.getQualifier().isPipeInput())
return spv::StorageClassInput;
if (type.getQualifier().isPipeOutput())
@@ -1501,7 +1505,7 @@
}
if (glslangIntermediate->getLayoutPrimitiveCulling()) {
- builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
+ builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR);
}
unsigned int mode;
@@ -1668,7 +1672,7 @@
{
auto& extensions = glslangIntermediate->getRequestedExtensions();
if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
- builder.addCapability(spv::CapabilityRayTracingProvisionalKHR);
+ builder.addCapability(spv::CapabilityRayTracingKHR);
builder.addExtension("SPV_KHR_ray_tracing");
}
else {
@@ -2118,8 +2122,9 @@
// these require changing a 64-bit scaler -> a vector of 32-bit components
if (glslangType.isVector())
break;
- std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4),
- builder.makeUintType(64));
+ spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4);
+ spv::Id uint64_type = builder.makeUintType(64);
+ std::pair<spv::Id, spv::Id> ret(ivec4_type, uint64_type);
return ret;
}
// There are no SPIR-V builtins defined for these and map onto original non-transposed
@@ -2490,6 +2495,10 @@
// anything else gets there, so visit out of order, doing them all now.
makeGlobalInitializers(node->getAsAggregate()->getSequence());
+ //Pre process linker objects for ray tracing stages
+ if (glslangIntermediate->isRayTracingStage())
+ collectRayTracingLinkerObjects();
+
// Initializers are done, don't want to visit again, but functions and link objects need to be processed,
// so do them manually.
visitFunctions(node->getAsAggregate()->getSequence());
@@ -2799,10 +2808,12 @@
binOp = node->getOp();
break;
- case glslang::EOpIgnoreIntersection:
- case glslang::EOpTerminateRay:
- case glslang::EOpTrace:
- case glslang::EOpExecuteCallable:
+ case glslang::EOpIgnoreIntersectionNV:
+ case glslang::EOpTerminateRayNV:
+ case glslang::EOpTraceNV:
+ case glslang::EOpTraceKHR:
+ case glslang::EOpExecuteCallableNV:
+ case glslang::EOpExecuteCallableKHR:
case glslang::EOpWritePackedPrimitiveIndices4x8NV:
noReturnValue = true;
break;
@@ -2811,7 +2822,7 @@
case glslang::EOpRayQueryGenerateIntersection:
case glslang::EOpRayQueryConfirmIntersection:
builder.addExtension("SPV_KHR_ray_query");
- builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+ builder.addCapability(spv::CapabilityRayQueryKHR);
noReturnValue = true;
break;
case glslang::EOpRayQueryProceed:
@@ -2834,7 +2845,7 @@
case glslang::EOpRayQueryGetIntersectionObjectToWorld:
case glslang::EOpRayQueryGetIntersectionWorldToObject:
builder.addExtension("SPV_KHR_ray_query");
- builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+ builder.addCapability(spv::CapabilityRayQueryKHR);
break;
case glslang::EOpCooperativeMatrixLoad:
case glslang::EOpCooperativeMatrixStore:
@@ -3087,11 +3098,18 @@
)) {
bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
- }
- else {
+ } else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) ||
+ (arg == 1 && glslangOp == glslang::EOpExecuteCallableKHR)) {
+ const int opdNum = glslangOp == glslang::EOpTraceKHR ? 10 : 1;
+ const int set = glslangOp == glslang::EOpTraceKHR ? 0 : 1;
+ const int location = glslangOperands[opdNum]->getAsConstantUnion()->getConstArray()[0].getUConst();
+ auto itNode = locationToSymbol[set].find(location);
+ visitSymbol(itNode->second);
+ spv::Id symId = getSymbolId(itNode->second);
+ operands.push_back(symId);
+ } else {
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
- }
-
+ }
}
}
@@ -3494,11 +3512,11 @@
switch (node->getFlowOp()) {
case glslang::EOpKill:
- builder.makeDiscard();
+ builder.makeStatementTerminator(spv::OpKill, "post-discard");
break;
case glslang::EOpTerminateInvocation:
builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
- builder.makeTerminateInvocation();
+ builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation");
break;
case glslang::EOpBreak:
if (breakForLoop.top())
@@ -3535,6 +3553,12 @@
builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
break;
+ case glslang::EOpTerminateRayKHR:
+ builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR");
+ break;
+ case glslang::EOpIgnoreIntersectionKHR:
+ builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR");
+ break;
#endif
default:
@@ -4629,7 +4653,39 @@
}
}
}
+// Walk over all linker objects to create a map for payload and callable data linker objects
+// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR
+// This is done here since it is possible that these linker objects are not be referenced in the AST
+void TGlslangToSpvTraverser::collectRayTracingLinkerObjects()
+{
+ glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects();
+ for (auto& objSeq : linkerObjects->getSequence()) {
+ auto objNode = objSeq->getAsSymbolNode();
+ if (objNode != nullptr) {
+ if (objNode->getQualifier().hasLocation()) {
+ unsigned int location = objNode->getQualifier().layoutLocation;
+ auto st = objNode->getQualifier().storage;
+ int set;
+ switch (st)
+ {
+ case glslang::EvqPayload:
+ case glslang::EvqPayloadIn:
+ set = 0;
+ break;
+ case glslang::EvqCallableData:
+ case glslang::EvqCallableDataIn:
+ set = 1;
+ break;
+ default:
+ set = -1;
+ }
+ if (set != -1)
+ locationToSymbol[set].insert(std::make_pair(location, objNode));
+ }
+ }
+ }
+}
// Process all the functions, while skipping initializers.
void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
{
@@ -6254,6 +6310,11 @@
case glslang::EOpConstructReference:
unaryOp = spv::OpBitcast;
break;
+
+ case glslang::EOpConvUint64ToAccStruct:
+ case glslang::EOpConvUvec2ToAccStruct:
+ unaryOp = spv::OpConvertUToAccelerationStructureKHR;
+ break;
#endif
case glslang::EOpCopyObject:
@@ -7840,10 +7901,16 @@
typeId = builder.makeBoolType();
opCode = spv::OpReportIntersectionKHR;
break;
- case glslang::EOpTrace:
+ case glslang::EOpTraceNV:
+ builder.createNoResultOp(spv::OpTraceNV, operands);
+ return 0;
+ case glslang::EOpTraceKHR:
builder.createNoResultOp(spv::OpTraceRayKHR, operands);
return 0;
- case glslang::EOpExecuteCallable:
+ case glslang::EOpExecuteCallableNV:
+ builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
+ return 0;
+ case glslang::EOpExecuteCallableKHR:
builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
return 0;
@@ -8131,11 +8198,11 @@
spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
return builder.setPrecision(id, precision);
}
- case glslang::EOpIgnoreIntersection:
- builder.createNoResultOp(spv::OpIgnoreIntersectionKHR);
+ case glslang::EOpIgnoreIntersectionNV:
+ builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
return 0;
- case glslang::EOpTerminateRay:
- builder.createNoResultOp(spv::OpTerminateRayKHR);
+ case glslang::EOpTerminateRayNV:
+ builder.createNoResultOp(spv::OpTerminateRayNV);
return 0;
case glslang::EOpRayQueryInitialize:
builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
@@ -8263,7 +8330,8 @@
}
#ifndef GLSLANG_WEB
- if (symbol->getType().isImage()) {
+ // Subgroup builtins which have input storage class are volatile for ray tracing stages.
+ if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) {
std::vector<spv::Decoration> memory;
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
glslangIntermediate->usingVulkanMemoryModel());