Skip to content

Commit 4670c93

Browse files
committed
Map SV_InstanceID to gl_InstanceIndex-gl_BaseInstance
1 parent 519e866 commit 4670c93

12 files changed

+231
-41
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-compiler.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "slang-check-impl.h"
1717
#include "slang-check.h"
1818

19+
#include <chrono>
20+
1921
// Artifact
2022
#include "../compiler-core/slang-artifact-associated.h"
2123
#include "../compiler-core/slang-artifact-container-util.h"
@@ -1835,6 +1837,26 @@ SlangResult CodeGenContext::_emitEntryPoints(ComPtr<IArtifact>& outArtifact)
18351837
return SLANG_FAIL;
18361838
}
18371839

1840+
// Helper class for recording compile time.
1841+
struct CompileTimerRAII
1842+
{
1843+
std::chrono::high_resolution_clock::time_point startTime;
1844+
Session* session;
1845+
CompileTimerRAII(Session* inSession)
1846+
{
1847+
startTime = std::chrono::high_resolution_clock::now();
1848+
session = inSession;
1849+
}
1850+
~CompileTimerRAII()
1851+
{
1852+
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(
1853+
std::chrono::high_resolution_clock::now() - startTime)
1854+
.count() /
1855+
1e6;
1856+
session->addTotalCompileTime(elapsedTime);
1857+
}
1858+
};
1859+
18381860
// Do emit logic for a zero or more entry points
18391861
SlangResult CodeGenContext::emitEntryPoints(ComPtr<IArtifact>& outArtifact)
18401862
{

source/slang/slang-compiler.h

-20
Original file line numberDiff line numberDiff line change
@@ -3755,26 +3755,6 @@ SLANG_FORCE_INLINE SlangSourceLanguage asExternal(SourceLanguage sourceLanguage)
37553755
return (SlangSourceLanguage)sourceLanguage;
37563756
}
37573757

3758-
// Helper class for recording compile time.
3759-
struct CompileTimerRAII
3760-
{
3761-
std::chrono::high_resolution_clock::time_point startTime;
3762-
Session* session;
3763-
CompileTimerRAII(Session* inSession)
3764-
{
3765-
startTime = std::chrono::high_resolution_clock::now();
3766-
session = inSession;
3767-
}
3768-
~CompileTimerRAII()
3769-
{
3770-
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(
3771-
std::chrono::high_resolution_clock::now() - startTime)
3772-
.count() /
3773-
1e6;
3774-
session->addTotalCompileTime(elapsedTime);
3775-
}
3776-
};
3777-
37783758
// helpers for error/warning reporting
37793759
enum class DiagnosticCategory
37803760
{

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

+74-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,60 @@ 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& kv : workItems)
3784+
{
3785+
auto builtinVarName = kv.key;
3786+
auto varInst = kv.value;
3787+
3788+
// Repalce SV_InstanceID with gl_InstanceIndex - gl_BaseInstance.
3789+
if (builtinVarName == IRTargetBuiltinVarName::HlslInstanceID)
3790+
{
3791+
auto instanceIndex = getOrCreateBuiltinVar(
3792+
IRTargetBuiltinVarName::SpvInstanceIndex,
3793+
varInst->getDataType());
3794+
auto baseInstance = getOrCreateBuiltinVar(
3795+
IRTargetBuiltinVarName::SpvBaseInstance,
3796+
varInst->getDataType());
3797+
traverseUses(
3798+
varInst,
3799+
[&](IRUse* use)
3800+
{
3801+
auto user = use->getUser();
3802+
if (user->getOp() == kIROp_Load)
3803+
{
3804+
IRBuilder builder(use->getUser());
3805+
builder.setInsertBefore(use->getUser());
3806+
auto sub = builder.emitSub(
3807+
tryGetPointedToType(&builder, varInst->getDataType()),
3808+
builder.emitLoad(instanceIndex),
3809+
builder.emitLoad(baseInstance));
3810+
user->replaceUsesWith(sub);
3811+
}
3812+
});
3813+
}
3814+
}
3815+
}
37493816

37503817
void legalizeEntryPointForGLSL(
37513818
Session* session,
@@ -3937,6 +4004,11 @@ void legalizeEntryPointForGLSL(
39374004
value.globalParam->setFullType(sizedArrayType);
39384005
}
39394006
}
4007+
4008+
// Some system value vars can't be mapped 1:1 to a GLSL/Vulkan builtin,
4009+
// for example, SV_InstanceID should map to gl_InstanceIndex - gl_BaseInstance,
4010+
// we will replace these builtins with additional compute logic here.
4011+
legalizeTargetBuiltinVar(context);
39404012
}
39414013

39424014
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);

0 commit comments

Comments
 (0)