@@ -3108,7 +3108,6 @@ SpirvInstruction *SpirvEmitter::processCall(const CallExpr *callExpr) {
3108
3108
// This looks for cases where the copy can be elided. To generate valid
3109
3109
// SPIR-V, the argument must be a memory declaration.
3110
3110
//
3111
- //
3112
3111
3113
3112
// If argInfo is nullptr and argInst is a rvalue, we do not have a proper
3114
3113
// pointer to pass to the function. we need a temporary variable in that
@@ -3118,7 +3117,32 @@ SpirvInstruction *SpirvEmitter::processCall(const CallExpr *callExpr) {
3118
3117
// create a temporary variable for it because the function definition
3119
3118
// expects are point-to-pointer argument for resources, which will be
3120
3119
// resolved by legalization.
3121
- if ((argInfo || (argInst && argInst->getopcode() == spv::Op::OpVariable)) &&
3120
+
3121
+ // Workaround for Nabla STL `NBL_REF_ARG(T)` macro
3122
+ bool preliminaryInOutCanBeReference = false;
3123
+ if (argInst) {
3124
+ // new behaviour
3125
+ preliminaryInOutCanBeReference =
3126
+ argInst->getopcode() == spv::Op::OpVariable;
3127
+ // old behaviour, but gated behind `vk::ext_reference`
3128
+ if (param->hasAttr<VKReferenceExtAttr>()) {
3129
+ if (argInst->isRValue()) {
3130
+ emitError("argument for a parameter with vk::ext_reference attribute "
3131
+ "must be a reference",
3132
+ arg->getExprLoc());
3133
+ return nullptr;
3134
+ }
3135
+ if (!canActAsOutParmVar(param)) {
3136
+ emitError("argument for a non SPIR-V intrinsic parameter with vk::ext_reference attribute "
3137
+ "must be a applied to `inout`",
3138
+ arg->getExprLoc());
3139
+ return nullptr;
3140
+ }
3141
+ preliminaryInOutCanBeReference = true;
3142
+ }
3143
+ }
3144
+
3145
+ if ((argInfo || preliminaryInOutCanBeReference) &&
3122
3146
canActAsOutParmVar(param) && !isArgGlobalVarWithResourceType &&
3123
3147
paramTypeMatchesArgType(paramType, arg->getType())) {
3124
3148
// Based on SPIR-V spec, function parameter must be always Function
0 commit comments