-
Notifications
You must be signed in to change notification settings - Fork 462
Allow SV_PrimitiveID in ray tracing hit stages #11423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 60 commits
f1c8645
9a617f4
70debcd
85865f8
9425abd
b85c65b
240a14a
9d2552d
a61125a
d95badf
b5275bc
9da9ce2
7b64847
8d2b981
213e0f7
cfeda0b
49e16ab
1225131
9fa9f48
ad3c6fa
cf1ac42
7466afd
33f4896
21f415a
e8ab0d6
de1f740
701c4d4
bd32d06
2c5092b
0035f14
ccc10a4
742e7a9
e12ab61
16a2d99
92b53ac
4f4b6c9
c18e089
5190000
34b60d4
2b3d705
0de9b7e
5e6c3eb
e398ceb
0fc1868
60bd954
ffbf01a
8f222ec
403c538
9c96cb0
403863d
87b80de
fbc972a
479bc64
968a0e6
f0e623f
16800db
e185f30
5d33c5c
dcd0acd
bd7a400
894214b
f9f998c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| #include "slang-ir-clone.h" | ||
| #include "slang-ir-inst-pass-base.h" | ||
| #include "slang-ir-insts.h" | ||
| #include "slang-ir-legalize-varying-params.h" | ||
| #include "slang-ir-single-return.h" | ||
| #include "slang-ir-specialize-function-call.h" | ||
| #include "slang-ir-util.h" | ||
|
|
@@ -2999,6 +3000,71 @@ void handleSingleParam( | |
| builder->addDependsOnDecoration(func, globalParam); | ||
| } | ||
|
|
||
| struct DirectSPIRVPrimitiveIDEmitterContext | ||
| { | ||
| IRFunc* func = nullptr; | ||
| IRType* canonicalValueType = nullptr; | ||
| IRGlobalParam* globalParam = nullptr; | ||
| }; | ||
|
|
||
| static IRType* getPrimitiveIDValueTypeForDirectSPIRV(IRType* type) | ||
| { | ||
| if (auto borrowInParamType = as<IRBorrowInParamType>(type)) | ||
| return borrowInParamType->getValueType(); | ||
| if (auto ptrType = as<IRPtrTypeBase>(type)) | ||
| return ptrType->getValueType(); | ||
| return type; | ||
| } | ||
|
|
||
| static IRInst* emitDirectSPIRVPrimitiveIDValue( | ||
| IRModule* module, | ||
| IRBuilder& builder, | ||
| IRType* type, | ||
| IRStructField* field, | ||
| IRVarLayout* layout, | ||
| void* userData) | ||
| { | ||
| SLANG_RELEASE_ASSERT(layout); | ||
|
|
||
| auto semanticDecor = field ? field->getKey()->findDecoration<IRSemanticDecoration>() : nullptr; | ||
| auto systemValueAttr = layout->findSystemValueSemanticAttr(); | ||
| SLANG_RELEASE_ASSERT( | ||
| (systemValueAttr && | ||
| systemValueAttr->getName().caseInsensitiveEquals(toSlice("sv_primitiveid"))) || | ||
| (semanticDecor && | ||
| semanticDecor->getSemanticName().caseInsensitiveEquals(toSlice("sv_primitiveid")))); | ||
|
|
||
| auto context = static_cast<DirectSPIRVPrimitiveIDEmitterContext*>(userData); | ||
| auto valueType = getPrimitiveIDValueTypeForDirectSPIRV(type); | ||
| if (context->globalParam) | ||
| { | ||
| auto value = builder.emitLoad(context->globalParam); | ||
| if (isTypeEqual(context->canonicalValueType, valueType)) | ||
| return value; | ||
| return builder.emitCast(valueType, value); | ||
| } | ||
|
|
||
| auto globalParam = addGlobalParam( | ||
| module, | ||
| builder.getPtrType( | ||
| valueType, | ||
| AccessQualifier::Immutable, | ||
| AddressSpace::BuiltinInput, | ||
| builder.getDefaultBufferLayoutType())); | ||
|
|
||
| IRVarLayout::Builder varLayoutBuilder(&builder, layout->getTypeLayout()); | ||
| varLayoutBuilder.cloneEverythingButOffsetsFrom(layout); | ||
| if (!systemValueAttr && semanticDecor) | ||
| varLayoutBuilder.setSystemValueSemantic(semanticDecor->getSemanticName(), 0); | ||
| builder.addLayoutDecoration(globalParam, varLayoutBuilder.build()); | ||
| moveValueBefore(globalParam, context->func); | ||
| builder.addDependsOnDecoration(context->func, globalParam); | ||
|
|
||
| context->canonicalValueType = valueType; | ||
| context->globalParam = globalParam; | ||
| return builder.emitLoad(globalParam); | ||
| } | ||
|
|
||
| static void consolidateParameters(GLSLLegalizationContext* context, List<IRParam*>& params) | ||
| { | ||
| auto builder = context->getBuilder(); | ||
|
|
@@ -3077,7 +3143,12 @@ static void consolidateParameters(GLSLLegalizationContext* context, List<IRParam | |
| } | ||
|
|
||
| // Consolidate ray tracing parameters for an entry point function | ||
| void consolidateRayTracingParameters(GLSLLegalizationContext* context, IRFunc* func) | ||
| void consolidateRayTracingParameters( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, I am not sure why we need so many special handling of primitive ID across different places in this file. What makes PrimitiveID so special compared to other builtins, e.g. InstanceID? Why don't we need the special case for InstanceID, DispatchId etc.? The changes seems more like fixes to paper issues rather than principled way to implement the new feature. We should have some legalization/canonicalization step to turn all uses of primitiveID into a canonical form, so no special handling is needed throughout different places.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Agent] Addressed in cfeda0b. The GLSL/glslang path now canonicalizes ray-tracing hit-stage Validation: |
||
| GLSLLegalizationContext* context, | ||
| IRFunc* func, | ||
| bool legalizePrimitiveIDBeforeConsolidation, | ||
| bool legalizePrimitiveIDStructBeforeConsolidation, | ||
| RayTracingPrimitiveIDValueEmitter const* primitiveIDStructValueEmitter) | ||
| { | ||
| auto builder = context->getBuilder(); | ||
| auto firstBlock = func->getFirstBlock(); | ||
|
|
@@ -3088,18 +3159,73 @@ void consolidateRayTracingParameters(GLSLLegalizationContext* context, IRFunc* f | |
| List<IRParam*> outParams; | ||
| List<IRParam*> params; | ||
|
|
||
| for (auto param = firstBlock->getFirstParam(); param; param = param->getNextParam()) | ||
| // When requested for SPIR-V via GLSL, canonicalize hit-stage SV_PrimitiveID before | ||
| // ray-tracing parameter consolidation rewrites entry-point parameters. This changes | ||
| // a Slang entry point parameter: | ||
| // | ||
| // void main_chit(int primitiveID : SV_PrimitiveID) { use(primitiveID); } | ||
| // | ||
| // into GLSL-style body code that reads the builtin: | ||
| // | ||
| // int primitiveID = int(gl_PrimitiveID); | ||
| // use(primitiveID); | ||
| // | ||
| // and removes the original parameter before consolidation sees payload/attributes. | ||
| for (auto param = firstBlock->getFirstParam(); param;) | ||
| { | ||
| auto nextParam = param->getNextParam(); | ||
| auto paramLayout = findVarLayout(param); | ||
| if (!isVaryingParameter(paramLayout)) | ||
| { | ||
| param = nextParam; | ||
| continue; | ||
| } | ||
|
|
||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not make unnecessary change.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Agent] Addressed in Validation: I left this thread unresolved for reviewer confirmation. |
||
| builder->setInsertBefore(firstBlock->getFirstOrdinaryInst()); | ||
|
|
||
| if (legalizePrimitiveIDBeforeConsolidation) | ||
| { | ||
| bool paramRemoved = false; | ||
| if (tryLegalizeRayTracingPrimitiveIDParam( | ||
| builder->getModule(), | ||
| *builder, | ||
| param, | ||
| ¶mRemoved)) | ||
| { | ||
| if (paramRemoved) | ||
| { | ||
| param = nextParam; | ||
| continue; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (legalizePrimitiveIDStructBeforeConsolidation) | ||
| { | ||
| bool paramRemoved = false; | ||
| if (tryLegalizeRayTracingPrimitiveIDStructParam( | ||
| builder->getModule(), | ||
| *builder, | ||
| param, | ||
| ¶mRemoved, | ||
| primitiveIDStructValueEmitter)) | ||
| { | ||
| if (paramRemoved) | ||
| { | ||
| param = nextParam; | ||
| continue; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (as<IROutParamType>(param->getDataType()) || | ||
| as<IRBorrowInOutParamType>(param->getDataType())) | ||
| { | ||
| outParams.add(param); | ||
| } | ||
| params.add(param); | ||
|
|
||
| param = nextParam; | ||
| } | ||
|
|
||
| // We don't need consolidation here. | ||
|
|
@@ -4820,6 +4946,7 @@ void legalizeEntryPointForGLSL( | |
| SLANG_ASSERT(entryPointDecor); | ||
|
|
||
| auto stage = entryPointDecor->getProfile().getStage(); | ||
| const bool isViaGLSL = !codeGenContext->getTargetProgram()->shouldEmitSPIRVDirectly(); | ||
|
|
||
| auto layoutDecoration = func->findDecoration<IRLayoutDecoration>(); | ||
| SLANG_ASSERT(layoutDecoration); | ||
|
|
@@ -4918,8 +5045,27 @@ void legalizeEntryPointForGLSL( | |
| case Stage::Intersection: | ||
| case Stage::Miss: | ||
| case Stage::RayGeneration: | ||
| consolidateRayTracingParameters(&context, func); | ||
| break; | ||
| { | ||
| DirectSPIRVPrimitiveIDEmitterContext directSPIRVPrimitiveIDEmitterContext; | ||
| directSPIRVPrimitiveIDEmitterContext.func = func; | ||
|
|
||
| RayTracingPrimitiveIDValueEmitter directSPIRVPrimitiveIDEmitter; | ||
| RayTracingPrimitiveIDValueEmitter const* primitiveIDStructValueEmitter = nullptr; | ||
| if (isRayTracingHitStage(stage) && !isViaGLSL) | ||
| { | ||
| directSPIRVPrimitiveIDEmitter.func = emitDirectSPIRVPrimitiveIDValue; | ||
| directSPIRVPrimitiveIDEmitter.userData = &directSPIRVPrimitiveIDEmitterContext; | ||
| primitiveIDStructValueEmitter = &directSPIRVPrimitiveIDEmitter; | ||
| } | ||
|
|
||
| consolidateRayTracingParameters( | ||
| &context, | ||
| func, | ||
| isRayTracingHitStage(stage) && isViaGLSL, | ||
| isRayTracingHitStage(stage), | ||
| primitiveIDStructValueEmitter); | ||
| break; | ||
| } | ||
| default: | ||
| break; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.