Skip to content

Commit 19b1e50

Browse files
committed
Map SV_InstanceID to gl_InstanceIndex-gl_BaseInstance
1 parent f7b9745 commit 19b1e50

10 files changed

+204
-21
lines changed

source/slang/glsl.meta.slang

+21-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,27 @@ public property uint3 gl_WorkGroupSize
136136
// TODO: define overload for tessellation control stage.
137137
public in int gl_InvocationID : SV_GSInstanceID;
138138

139-
public in int gl_InstanceIndex : SV_InstanceID;
139+
internal in int __sv_InstanceIndex : SV_InstanceID;
140+
141+
// SPIRV InstanceIndex builtin for vertex shader
142+
public property int gl_InstanceIndex
143+
{
144+
[require(vertex)]
145+
get
146+
{
147+
__target_switch
148+
{
149+
default:
150+
return __sv_InstanceIndex;
151+
case glsl:
152+
__intrinsic_asm "gl_InstanceIndex";
153+
case spirv:
154+
return spirv_asm {
155+
result:$$int = OpLoad builtin(InstanceIndex:int);
156+
};
157+
}
158+
}
159+
}
140160
public in bool gl_FrontFacing : SV_IsFrontFace;
141161

142162
// TODO: define overload for geometry stage.

source/slang/slang-emit-c-like.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,20 @@ IRNumThreadsDecoration* CLikeSourceEmitter::getComputeThreadGroupSize(
345345
return decor;
346346
}
347347

348+
String CLikeSourceEmitter::getTargetBuiltinVarName(IRInst* inst, IRTargetBuiltinVarName builtinName)
349+
{
350+
switch (builtinName)
351+
{
352+
case IRTargetBuiltinVarName::SpvInstanceIndex:
353+
return "gl_InstanceIndex";
354+
case IRTargetBuiltinVarName::SpvBaseInstance:
355+
return "gl_BaseInstance";
356+
}
357+
if (auto linkage = inst->findDecoration<IRLinkageDecoration>())
358+
return linkage->getMangledName();
359+
return generateName(inst);
360+
}
361+
348362
List<IRWitnessTableEntry*> CLikeSourceEmitter::getSortedWitnessTableEntries(
349363
IRWitnessTable* witnessTable)
350364
{
@@ -1208,6 +1222,11 @@ String CLikeSourceEmitter::generateName(IRInst* inst)
12081222
return externCppDecoration->getName();
12091223
}
12101224

1225+
if (auto builtinTargetVarDecoration = inst->findDecoration<IRTargetBuiltinVarDecoration>())
1226+
{
1227+
return getTargetBuiltinVarName(inst, builtinTargetVarDecoration->getBuiltinVarName());
1228+
}
1229+
12111230
// If we have a name hint on the instruction, then we will try to use that
12121231
// to provide the basis for the actual name in the output code.
12131232
if (auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>())

source/slang/slang-emit-c-like.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ class CLikeSourceEmitter : public SourceEmitterBase
243243
Linkage* getLinkage() { return m_codeGenContext->getLinkage(); }
244244
ComponentType* getProgram() { return m_codeGenContext->getProgram(); }
245245
TargetProgram* getTargetProgram() { return m_codeGenContext->getTargetProgram(); }
246-
247246
//
248247
// Types
249248
//
@@ -519,6 +518,7 @@ class CLikeSourceEmitter : public SourceEmitterBase
519518
protected:
520519
virtual void emitGlobalParamDefaultVal(IRGlobalParam* inst) { SLANG_UNUSED(inst); }
521520
virtual void emitPostDeclarationAttributesForType(IRInst* type) { SLANG_UNUSED(type); }
521+
virtual String getTargetBuiltinVarName(IRInst* inst, IRTargetBuiltinVarName builtinName);
522522
virtual bool doesTargetSupportPtrTypes() { return false; }
523523
virtual bool isResourceTypeBindless(IRType* type)
524524
{

source/slang/slang-emit-glsl.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,12 @@ bool GLSLSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* v
17911791
}
17921792
}
17931793

1794+
if (varDecl->findDecoration<IRTargetBuiltinVarDecoration>())
1795+
{
1796+
// By default, we don't need to emit a definition for target builtin variables.
1797+
return true;
1798+
}
1799+
17941800
// Do the default thing
17951801
return false;
17961802
}

source/slang/slang-emit-spirv.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -5215,6 +5215,16 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
52155215
{
52165216
IRBuilder builder(m_irModule);
52175217
builder.setInsertBefore(inst);
5218+
if (auto builtinVarDecor = inst->findDecoration<IRTargetBuiltinVarDecoration>())
5219+
{
5220+
switch (builtinVarDecor->getBuiltinVarName())
5221+
{
5222+
case IRTargetBuiltinVarName::SpvInstanceIndex:
5223+
return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInInstanceIndex, inst);
5224+
case IRTargetBuiltinVarName::SpvBaseInstance:
5225+
return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaseInstance, inst);
5226+
}
5227+
}
52185228
if (auto layout = getVarLayout(inst))
52195229
{
52205230
if (auto systemValueAttr = layout->findAttr<IRSystemValueSemanticAttr>())

source/slang/slang-ir-glsl-legalize.cpp

+71-2
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ struct GLSLSystemValueInfo
236236

237237
// The kind of the system value that requires special treatment.
238238
GLSLSystemValueKind kind = GLSLSystemValueKind::General;
239+
240+
// The target builtin name.
241+
IRTargetBuiltinVarName targetVarName = IRTargetBuiltinVarName::Unknown;
239242
};
240243

241244
static void leafAddressesImpl(List<IRInst*>& ret, const ScalarizedVal& v)
@@ -283,6 +286,7 @@ struct GLSLLegalizationContext
283286
DiagnosticSink* sink;
284287
Stage stage;
285288
IRFunc* entryPointFunc;
289+
Dictionary<IRTargetBuiltinVarName, IRInst*> builtinVarMap;
286290

287291
/// This dictionary stores all bindings of 'VaryingIn/VaryingOut'. We assume 'space' is 0.
288292
Dictionary<LayoutResourceKind, UIntSet> usedBindingIndex;
@@ -414,7 +418,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
414418
char const* outerArrayName = nullptr;
415419
int arrayIndex = -1;
416420
GLSLSystemValueKind systemValueKind = GLSLSystemValueKind::General;
417-
421+
IRTargetBuiltinVarName targetVarName = IRTargetBuiltinVarName::Unknown;
418422
auto semanticInst = varLayout->findSystemValueSemanticAttr();
419423
if (!semanticInst)
420424
return nullptr;
@@ -621,6 +625,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
621625

622626
requiredType = builder->getBasicType(BaseType::Int);
623627
name = "gl_InstanceIndex";
628+
targetVarName = IRTargetBuiltinVarName::HlslInstanceID;
624629
}
625630
else if (semanticName == "sv_isfrontface")
626631
{
@@ -869,6 +874,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
869874
name = "gl_BaseInstance";
870875
}
871876

877+
inStorage->targetVarName = targetVarName;
872878
if (name)
873879
{
874880
inStorage->name = name;
@@ -976,6 +982,12 @@ void createVarLayoutForLegalizedGlobalParam(
976982
default:
977983
break;
978984
}
985+
986+
if (systemValueInfo->targetVarName != IRTargetBuiltinVarName::Unknown)
987+
{
988+
builder->addTargetBuiltinVarDecoration(globalParam, systemValueInfo->targetVarName);
989+
context->builtinVarMap[systemValueInfo->targetVarName] = globalParam;
990+
}
979991
}
980992
}
981993

@@ -1262,7 +1274,7 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
12621274
// Validate the system value, convert to a regular parameter if this is not a valid system
12631275
// value for a given target.
12641276
if (systemSemantic && isSPIRV(codeGenContext->getTargetFormat()) &&
1265-
systemSemantic->getName().caseInsensitiveEquals(UnownedStringSlice("sv_instanceid")) &&
1277+
systemValueInfo->targetVarName == IRTargetBuiltinVarName::HlslInstanceID &&
12661278
((stage == Stage::Fragment) ||
12671279
(stage == Stage::Vertex &&
12681280
inVarLayout->usesResourceKind(LayoutResourceKind::VaryingOutput))))
@@ -1287,6 +1299,7 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
12871299
newVarLayout->sourceLoc = inVarLayout->sourceLoc;
12881300

12891301
inVarLayout->replaceUsesWith(newVarLayout);
1302+
systemValueInfo->targetVarName = IRTargetBuiltinVarName::Unknown;
12901303
}
12911304
}
12921305

@@ -3746,6 +3759,57 @@ ScalarizedVal legalizeEntryPointReturnValueForGLSL(
37463759
return result;
37473760
}
37483761

3762+
void legalizeTargetBuiltinVar(GLSLLegalizationContext& context)
3763+
{
3764+
List<KeyValuePair<IRTargetBuiltinVarName, IRInst*>> workItems;
3765+
for (auto [builtinVarName, varInst] : context.builtinVarMap)
3766+
{
3767+
if (builtinVarName == IRTargetBuiltinVarName::HlslInstanceID)
3768+
{
3769+
workItems.add(KeyValuePair(builtinVarName, varInst));
3770+
}
3771+
}
3772+
3773+
auto getOrCreateBuiltinVar = [&](IRTargetBuiltinVarName name, IRType* type)
3774+
{
3775+
if (auto var = context.builtinVarMap.tryGetValue(name))
3776+
return *var;
3777+
IRBuilder builder(context.entryPointFunc);
3778+
builder.setInsertBefore(context.entryPointFunc);
3779+
IRInst* var = builder.createGlobalParam(type);
3780+
builder.addTargetBuiltinVarDecoration(var, name);
3781+
return var;
3782+
};
3783+
for (auto [builtinVarName, varInst] : workItems)
3784+
{
3785+
// Repalce SV_InstanceID with gl_InstanceIndex - gl_BaseInstance.
3786+
if (builtinVarName == IRTargetBuiltinVarName::HlslInstanceID)
3787+
{
3788+
auto instanceIndex = getOrCreateBuiltinVar(
3789+
IRTargetBuiltinVarName::SpvInstanceIndex,
3790+
varInst->getDataType());
3791+
auto baseInstance = getOrCreateBuiltinVar(
3792+
IRTargetBuiltinVarName::SpvBaseInstance,
3793+
varInst->getDataType());
3794+
traverseUses(
3795+
varInst,
3796+
[&](IRUse* use)
3797+
{
3798+
auto user = use->getUser();
3799+
if (user->getOp() == kIROp_Load)
3800+
{
3801+
IRBuilder builder(use->getUser());
3802+
builder.setInsertBefore(use->getUser());
3803+
auto sub = builder.emitSub(
3804+
tryGetPointedToType(&builder, varInst->getDataType()),
3805+
builder.emitLoad(instanceIndex),
3806+
builder.emitLoad(baseInstance));
3807+
user->replaceUsesWith(sub);
3808+
}
3809+
});
3810+
}
3811+
}
3812+
}
37493813

37503814
void legalizeEntryPointForGLSL(
37513815
Session* session,
@@ -3937,6 +4001,11 @@ void legalizeEntryPointForGLSL(
39374001
value.globalParam->setFullType(sizedArrayType);
39384002
}
39394003
}
4004+
4005+
// Some system value vars can't be mapped 1:1 to a GLSL/Vulkan builtin,
4006+
// for example, SV_InstanceID should map to gl_InstanceIndex - gl_BaseInstance,
4007+
// we will replace these builtins with additional compute logic here.
4008+
legalizeTargetBuiltinVar(context);
39404009
}
39414010

39424011
void decorateModuleWithSPIRVVersion(IRModule* module, SemanticVersion spirvVersion)

source/slang/slang-ir-inst-defs.h

+3
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,9 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
926926
INST(ExportDecoration, export, 1, 0)
927927
INST_RANGE(LinkageDecoration, ImportDecoration, ExportDecoration)
928928

929+
/// Mark a global variable as a target builtin variable.
930+
INST(TargetBuiltinVarDecoration, TargetBuiltinVar, 1, 0)
931+
929932
/// Marks an inst as coming from an `extern` symbol defined in the user code.
930933
INST(UserExternDecoration, UserExtern, 0, 0)
931934

source/slang/slang-ir-insts.h

+32
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ enum class IRInterpolationMode
193193
PerVertex,
194194
};
195195

196+
enum class IRTargetBuiltinVarName
197+
{
198+
Unknown,
199+
HlslInstanceID,
200+
SpvInstanceIndex,
201+
SpvBaseInstance,
202+
};
203+
196204
struct IRInterpolationModeDecoration : IRDecoration
197205
{
198206
enum
@@ -705,6 +713,18 @@ struct IRLinkageDecoration : IRDecoration
705713
UnownedStringSlice getMangledName() { return getMangledNameOperand()->getStringSlice(); }
706714
};
707715

716+
// Mark a global variable as a target buitlin variable.
717+
struct IRTargetBuiltinVarDecoration : IRDecoration
718+
{
719+
IR_LEAF_ISA(TargetBuiltinVarDecoration)
720+
721+
IRIntLit* getBuiltinVarOperand() { return cast<IRIntLit>(getOperand(0)); }
722+
IRTargetBuiltinVarName getBuiltinVarName()
723+
{
724+
return IRTargetBuiltinVarName(getBuiltinVarOperand()->getValue());
725+
}
726+
};
727+
708728
struct IRUserExternDecoration : IRDecoration
709729
{
710730
enum
@@ -4658,6 +4678,18 @@ struct IRBuilder
46584678
// void addLayoutDecoration(IRInst* value, Layout* layout);
46594679
IRLayoutDecoration* addLayoutDecoration(IRInst* value, IRLayout* layout);
46604680

4681+
IRDecoration* addTargetBuiltinVarDecoration(
4682+
IRInst* value,
4683+
IRTargetBuiltinVarName builtinVarName)
4684+
{
4685+
IRInst* operands[] = {getIntValue((IRIntegerValue)builtinVarName)};
4686+
return addDecoration(
4687+
value,
4688+
kIROp_TargetBuiltinVarDecoration,
4689+
operands,
4690+
SLANG_COUNT_OF(operands));
4691+
}
4692+
46614693
// IRLayout* getLayout(Layout* astLayout);
46624694

46634695
IRTypeSizeAttr* getTypeSizeAttr(LayoutResourceKind kind, LayoutSize size);

source/slang/slang-ir-spirv-legalize.cpp

+27-17
Original file line numberDiff line numberDiff line change
@@ -422,20 +422,10 @@ struct SPIRVLegalizationContext : public SourceEmitterBase
422422
}
423423

424424
AddressSpace addressSpace = AddressSpace::ThreadLocal;
425-
// Figure out storage class based on var layout.
426-
if (auto layout = getVarLayout(inst))
427-
{
428-
auto cls = getGlobalParamAddressSpace(layout);
429-
if (cls != AddressSpace::Generic)
430-
addressSpace = cls;
431-
else if (auto systemValueAttr = layout->findAttr<IRSystemValueSemanticAttr>())
432-
{
433-
String semanticName = systemValueAttr->getName();
434-
semanticName = semanticName.toLower();
435-
if (semanticName == "sv_pointsize")
436-
addressSpace = AddressSpace::BuiltinInput;
437-
}
438-
}
425+
// Figure out storage class based on builtin info or var layout.
426+
auto cls = getGlobalParamAddressSpace(inst);
427+
if (cls != AddressSpace::Generic)
428+
addressSpace = cls;
439429

440430
// Don't do any processing for specialization constants.
441431
if (addressSpace == AddressSpace::SpecializationConstant)
@@ -635,8 +625,18 @@ struct SPIRVLegalizationContext : public SourceEmitterBase
635625
return addressSpace;
636626
}
637627

638-
AddressSpace getGlobalParamAddressSpace(IRVarLayout* varLayout)
628+
AddressSpace getGlobalParamAddressSpace(IRInst* varInst)
639629
{
630+
auto builtinDecor = varInst->findDecoration<IRTargetBuiltinVarDecoration>();
631+
switch (builtinDecor->getBuiltinVarName())
632+
{
633+
case IRTargetBuiltinVarName::SpvInstanceIndex:
634+
case IRTargetBuiltinVarName::SpvBaseInstance:
635+
return AddressSpace::BuiltinInput;
636+
}
637+
638+
auto varLayout = getVarLayout(varInst);
639+
640640
auto typeLayout = varLayout->getTypeLayout()->unwrapArray();
641641
if (auto parameterGroupTypeLayout = as<IRParameterGroupTypeLayout>(typeLayout))
642642
{
@@ -663,15 +663,25 @@ struct SPIRVLegalizationContext : public SourceEmitterBase
663663
"resolve a storage class address space.");
664664
}
665665
}
666+
auto systemValueAttr = varLayout->findSystemValueSemanticAttr();
667+
668+
if (systemValueAttr)
669+
{
670+
// TODO: is this needed?
671+
String semanticName = systemValueAttr->getName();
672+
semanticName = semanticName.toLower();
673+
if (semanticName == "sv_pointsize")
674+
result = AddressSpace::BuiltinInput;
675+
}
666676

667677
switch (result)
668678
{
669679
case AddressSpace::Input:
670-
if (varLayout->findSystemValueSemanticAttr())
680+
if (systemValueAttr)
671681
result = AddressSpace::BuiltinInput;
672682
break;
673683
case AddressSpace::Output:
674-
if (varLayout->findSystemValueSemanticAttr())
684+
if (systemValueAttr)
675685
result = AddressSpace::BuiltinOutput;
676686
break;
677687
}

0 commit comments

Comments
 (0)