Skip to content

Commit e53f3a3

Browse files
committed
Map SV_InstanceID to gl_InstanceIndex-gl_BaseInstance
1 parent 86669cb commit e53f3a3

15 files changed

+258
-52
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-artifact-output-util.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "../core/slang-string-util.h"
77
#include "../core/slang-type-text-util.h"
88

9+
#include <chrono>
10+
911
// Artifact
1012
#include "../compiler-core/slang-artifact-desc-util.h"
1113
#include "../compiler-core/slang-artifact-util.h"

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -4344,8 +4344,11 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
43444344
continue;
43454345
}
43464346
}
4347-
paramsSet.add(spvGlobalInst);
43484347
referencedBuiltinIRVars.add(globalInst);
4348+
// Don't add duplicate vars to the interface list.
4349+
bool paramAdded = paramsSet.add(spvGlobalInst);
4350+
if (!paramAdded)
4351+
continue;
43494352

43504353
// Don't add a global param to the interface if it is a
43514354
// specialization constant.
@@ -5215,6 +5218,17 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
52155218
{
52165219
IRBuilder builder(m_irModule);
52175220
builder.setInsertBefore(inst);
5221+
if (auto builtinVarDecor = inst->findDecoration<IRTargetBuiltinVarDecoration>())
5222+
{
5223+
switch (builtinVarDecor->getBuiltinVarName())
5224+
{
5225+
case IRTargetBuiltinVarName::SpvInstanceIndex:
5226+
return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInInstanceIndex, inst);
5227+
case IRTargetBuiltinVarName::SpvBaseInstance:
5228+
requireSPIRVCapability(SpvCapabilityDrawParameters);
5229+
return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaseInstance, inst);
5230+
}
5231+
}
52185232
if (auto layout = getVarLayout(inst))
52195233
{
52205234
if (auto systemValueAttr = layout->findAttr<IRSystemValueSemanticAttr>())

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

+77-3
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,9 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
621625

622626
requiredType = builder->getBasicType(BaseType::Int);
623627
name = "gl_InstanceIndex";
628+
targetVarName = IRTargetBuiltinVarName::HlslInstanceID;
629+
context->requireSPIRVVersion(SemanticVersion(1, 3));
630+
context->requireGLSLExtension(toSlice("GL_ARB_shader_draw_parameters"));
624631
}
625632
else if (semanticName == "sv_isfrontface")
626633
{
@@ -869,6 +876,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
869876
name = "gl_BaseInstance";
870877
}
871878

879+
inStorage->targetVarName = targetVarName;
872880
if (name)
873881
{
874882
inStorage->name = name;
@@ -976,6 +984,12 @@ void createVarLayoutForLegalizedGlobalParam(
976984
default:
977985
break;
978986
}
987+
988+
if (systemValueInfo->targetVarName != IRTargetBuiltinVarName::Unknown)
989+
{
990+
builder->addTargetBuiltinVarDecoration(globalParam, systemValueInfo->targetVarName);
991+
context->builtinVarMap[systemValueInfo->targetVarName] = globalParam;
992+
}
979993
}
980994
}
981995

@@ -1261,8 +1275,8 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
12611275
auto systemSemantic = inVarLayout->findAttr<IRSystemValueSemanticAttr>();
12621276
// Validate the system value, convert to a regular parameter if this is not a valid system
12631277
// value for a given target.
1264-
if (systemSemantic && isSPIRV(codeGenContext->getTargetFormat()) &&
1265-
systemSemantic->getName().caseInsensitiveEquals(UnownedStringSlice("sv_instanceid")) &&
1278+
if (systemSemantic && systemValueInfo && isSPIRV(codeGenContext->getTargetFormat()) &&
1279+
systemValueInfo->targetVarName == IRTargetBuiltinVarName::HlslInstanceID &&
12661280
((stage == Stage::Fragment) ||
12671281
(stage == Stage::Vertex &&
12681282
inVarLayout->usesResourceKind(LayoutResourceKind::VaryingOutput))))
@@ -1287,6 +1301,7 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
12871301
newVarLayout->sourceLoc = inVarLayout->sourceLoc;
12881302

12891303
inVarLayout->replaceUsesWith(newVarLayout);
1304+
systemValueInfo->targetVarName = IRTargetBuiltinVarName::Unknown;
12901305
}
12911306
}
12921307

@@ -3746,6 +3761,60 @@ ScalarizedVal legalizeEntryPointReturnValueForGLSL(
37463761
return result;
37473762
}
37483763

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

37503819
void legalizeEntryPointForGLSL(
37513820
Session* session,
@@ -3937,6 +4006,11 @@ void legalizeEntryPointForGLSL(
39374006
value.globalParam->setFullType(sizedArrayType);
39384007
}
39394008
}
4009+
4010+
// Some system value vars can't be mapped 1:1 to a GLSL/Vulkan builtin,
4011+
// for example, SV_InstanceID should map to gl_InstanceIndex - gl_BaseInstance,
4012+
// we will replace these builtins with additional compute logic here.
4013+
legalizeTargetBuiltinVar(context);
39404014
}
39414015

39424016
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

0 commit comments

Comments
 (0)