From e53f3a3fad757c870e3f39bd608b718164c213cd Mon Sep 17 00:00:00 2001 From: Yong He <yonghe@outlook.com> Date: Wed, 26 Feb 2025 12:43:12 -0800 Subject: [PATCH 1/2] Map `SV_InstanceID` to `gl_InstanceIndex-gl_BaseInstance` --- source/slang/glsl.meta.slang | 22 ++++- source/slang/slang-artifact-output-util.cpp | 2 + source/slang/slang-compiler.cpp | 22 +++++ source/slang/slang-compiler.h | 20 ----- source/slang/slang-emit-c-like.cpp | 19 +++++ source/slang/slang-emit-c-like.h | 2 +- source/slang/slang-emit-glsl.cpp | 6 ++ source/slang/slang-emit-spirv.cpp | 16 +++- source/slang/slang-ir-glsl-legalize.cpp | 80 ++++++++++++++++++- source/slang/slang-ir-inst-defs.h | 3 + source/slang/slang-ir-insts.h | 32 ++++++++ source/slang/slang-ir-spirv-legalize.cpp | 52 +++++++----- tests/bugs/gh-3087-multi-entry-point.slang | 18 +++-- .../system-values-draw-parameters.slang | 2 +- tests/spirv/sv_instance.slang | 14 ++++ 15 files changed, 258 insertions(+), 52 deletions(-) create mode 100644 tests/spirv/sv_instance.slang diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang index 6f0ca1bf34..eed6cc6908 100644 --- a/source/slang/glsl.meta.slang +++ b/source/slang/glsl.meta.slang @@ -136,7 +136,27 @@ public property uint3 gl_WorkGroupSize // TODO: define overload for tessellation control stage. public in int gl_InvocationID : SV_GSInstanceID; -public in int gl_InstanceIndex : SV_InstanceID; +internal in int __sv_InstanceIndex : SV_InstanceID; + +// SPIRV InstanceIndex builtin for vertex shader +public property int gl_InstanceIndex +{ + [require(vertex)] + get + { + __target_switch + { + default: + return __sv_InstanceIndex; + case glsl: + __intrinsic_asm "gl_InstanceIndex"; + case spirv: + return spirv_asm { + result:$$int = OpLoad builtin(InstanceIndex:int); + }; + } + } +} public in bool gl_FrontFacing : SV_IsFrontFace; // TODO: define overload for geometry stage. diff --git a/source/slang/slang-artifact-output-util.cpp b/source/slang/slang-artifact-output-util.cpp index 2d9dae1cf0..0e297955f5 100644 --- a/source/slang/slang-artifact-output-util.cpp +++ b/source/slang/slang-artifact-output-util.cpp @@ -6,6 +6,8 @@ #include "../core/slang-string-util.h" #include "../core/slang-type-text-util.h" +#include <chrono> + // Artifact #include "../compiler-core/slang-artifact-desc-util.h" #include "../compiler-core/slang-artifact-util.h" diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 04ebb753c1..58cc55e713 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -16,6 +16,8 @@ #include "slang-check-impl.h" #include "slang-check.h" +#include <chrono> + // Artifact #include "../compiler-core/slang-artifact-associated.h" #include "../compiler-core/slang-artifact-container-util.h" @@ -1835,6 +1837,26 @@ SlangResult CodeGenContext::_emitEntryPoints(ComPtr<IArtifact>& outArtifact) return SLANG_FAIL; } +// Helper class for recording compile time. +struct CompileTimerRAII +{ + std::chrono::high_resolution_clock::time_point startTime; + Session* session; + CompileTimerRAII(Session* inSession) + { + startTime = std::chrono::high_resolution_clock::now(); + session = inSession; + } + ~CompileTimerRAII() + { + double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::high_resolution_clock::now() - startTime) + .count() / + 1e6; + session->addTotalCompileTime(elapsedTime); + } +}; + // Do emit logic for a zero or more entry points SlangResult CodeGenContext::emitEntryPoints(ComPtr<IArtifact>& outArtifact) { diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 056c1fc835..db7f018ec6 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -3755,26 +3755,6 @@ SLANG_FORCE_INLINE SlangSourceLanguage asExternal(SourceLanguage sourceLanguage) return (SlangSourceLanguage)sourceLanguage; } -// Helper class for recording compile time. -struct CompileTimerRAII -{ - std::chrono::high_resolution_clock::time_point startTime; - Session* session; - CompileTimerRAII(Session* inSession) - { - startTime = std::chrono::high_resolution_clock::now(); - session = inSession; - } - ~CompileTimerRAII() - { - double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::high_resolution_clock::now() - startTime) - .count() / - 1e6; - session->addTotalCompileTime(elapsedTime); - } -}; - // helpers for error/warning reporting enum class DiagnosticCategory { diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index db2c0150f7..946e9c429f 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -345,6 +345,20 @@ IRNumThreadsDecoration* CLikeSourceEmitter::getComputeThreadGroupSize( return decor; } +String CLikeSourceEmitter::getTargetBuiltinVarName(IRInst* inst, IRTargetBuiltinVarName builtinName) +{ + switch (builtinName) + { + case IRTargetBuiltinVarName::SpvInstanceIndex: + return "gl_InstanceIndex"; + case IRTargetBuiltinVarName::SpvBaseInstance: + return "gl_BaseInstance"; + } + if (auto linkage = inst->findDecoration<IRLinkageDecoration>()) + return linkage->getMangledName(); + return generateName(inst); +} + List<IRWitnessTableEntry*> CLikeSourceEmitter::getSortedWitnessTableEntries( IRWitnessTable* witnessTable) { @@ -1208,6 +1222,11 @@ String CLikeSourceEmitter::generateName(IRInst* inst) return externCppDecoration->getName(); } + if (auto builtinTargetVarDecoration = inst->findDecoration<IRTargetBuiltinVarDecoration>()) + { + return getTargetBuiltinVarName(inst, builtinTargetVarDecoration->getBuiltinVarName()); + } + // If we have a name hint on the instruction, then we will try to use that // to provide the basis for the actual name in the output code. if (auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>()) diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index e83b6e5861..6fe7f5d34d 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -243,7 +243,6 @@ class CLikeSourceEmitter : public SourceEmitterBase Linkage* getLinkage() { return m_codeGenContext->getLinkage(); } ComponentType* getProgram() { return m_codeGenContext->getProgram(); } TargetProgram* getTargetProgram() { return m_codeGenContext->getTargetProgram(); } - // // Types // @@ -519,6 +518,7 @@ class CLikeSourceEmitter : public SourceEmitterBase protected: virtual void emitGlobalParamDefaultVal(IRGlobalParam* inst) { SLANG_UNUSED(inst); } virtual void emitPostDeclarationAttributesForType(IRInst* type) { SLANG_UNUSED(type); } + virtual String getTargetBuiltinVarName(IRInst* inst, IRTargetBuiltinVarName builtinName); virtual bool doesTargetSupportPtrTypes() { return false; } virtual bool isResourceTypeBindless(IRType* type) { diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 25dab3fb35..776c539b48 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -1791,6 +1791,12 @@ bool GLSLSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* v } } + if (varDecl->findDecoration<IRTargetBuiltinVarDecoration>()) + { + // By default, we don't need to emit a definition for target builtin variables. + return true; + } + // Do the default thing return false; } diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index ef015df7f9..f210b97686 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -4344,8 +4344,11 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex continue; } } - paramsSet.add(spvGlobalInst); referencedBuiltinIRVars.add(globalInst); + // Don't add duplicate vars to the interface list. + bool paramAdded = paramsSet.add(spvGlobalInst); + if (!paramAdded) + continue; // Don't add a global param to the interface if it is a // specialization constant. @@ -5215,6 +5218,17 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex { IRBuilder builder(m_irModule); builder.setInsertBefore(inst); + if (auto builtinVarDecor = inst->findDecoration<IRTargetBuiltinVarDecoration>()) + { + switch (builtinVarDecor->getBuiltinVarName()) + { + case IRTargetBuiltinVarName::SpvInstanceIndex: + return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInInstanceIndex, inst); + case IRTargetBuiltinVarName::SpvBaseInstance: + requireSPIRVCapability(SpvCapabilityDrawParameters); + return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaseInstance, inst); + } + } if (auto layout = getVarLayout(inst)) { if (auto systemValueAttr = layout->findAttr<IRSystemValueSemanticAttr>()) diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index 11d5399cf8..1123e1f2ad 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -236,6 +236,9 @@ struct GLSLSystemValueInfo // The kind of the system value that requires special treatment. GLSLSystemValueKind kind = GLSLSystemValueKind::General; + + // The target builtin name. + IRTargetBuiltinVarName targetVarName = IRTargetBuiltinVarName::Unknown; }; static void leafAddressesImpl(List<IRInst*>& ret, const ScalarizedVal& v) @@ -283,6 +286,7 @@ struct GLSLLegalizationContext DiagnosticSink* sink; Stage stage; IRFunc* entryPointFunc; + Dictionary<IRTargetBuiltinVarName, IRInst*> builtinVarMap; /// This dictionary stores all bindings of 'VaryingIn/VaryingOut'. We assume 'space' is 0. Dictionary<LayoutResourceKind, UIntSet> usedBindingIndex; @@ -414,7 +418,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo( char const* outerArrayName = nullptr; int arrayIndex = -1; GLSLSystemValueKind systemValueKind = GLSLSystemValueKind::General; - + IRTargetBuiltinVarName targetVarName = IRTargetBuiltinVarName::Unknown; auto semanticInst = varLayout->findSystemValueSemanticAttr(); if (!semanticInst) return nullptr; @@ -621,6 +625,9 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo( requiredType = builder->getBasicType(BaseType::Int); name = "gl_InstanceIndex"; + targetVarName = IRTargetBuiltinVarName::HlslInstanceID; + context->requireSPIRVVersion(SemanticVersion(1, 3)); + context->requireGLSLExtension(toSlice("GL_ARB_shader_draw_parameters")); } else if (semanticName == "sv_isfrontface") { @@ -869,6 +876,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo( name = "gl_BaseInstance"; } + inStorage->targetVarName = targetVarName; if (name) { inStorage->name = name; @@ -976,6 +984,12 @@ void createVarLayoutForLegalizedGlobalParam( default: break; } + + if (systemValueInfo->targetVarName != IRTargetBuiltinVarName::Unknown) + { + builder->addTargetBuiltinVarDecoration(globalParam, systemValueInfo->targetVarName); + context->builtinVarMap[systemValueInfo->targetVarName] = globalParam; + } } } @@ -1261,8 +1275,8 @@ ScalarizedVal createSimpleGLSLGlobalVarying( auto systemSemantic = inVarLayout->findAttr<IRSystemValueSemanticAttr>(); // Validate the system value, convert to a regular parameter if this is not a valid system // value for a given target. - if (systemSemantic && isSPIRV(codeGenContext->getTargetFormat()) && - systemSemantic->getName().caseInsensitiveEquals(UnownedStringSlice("sv_instanceid")) && + if (systemSemantic && systemValueInfo && isSPIRV(codeGenContext->getTargetFormat()) && + systemValueInfo->targetVarName == IRTargetBuiltinVarName::HlslInstanceID && ((stage == Stage::Fragment) || (stage == Stage::Vertex && inVarLayout->usesResourceKind(LayoutResourceKind::VaryingOutput)))) @@ -1287,6 +1301,7 @@ ScalarizedVal createSimpleGLSLGlobalVarying( newVarLayout->sourceLoc = inVarLayout->sourceLoc; inVarLayout->replaceUsesWith(newVarLayout); + systemValueInfo->targetVarName = IRTargetBuiltinVarName::Unknown; } } @@ -3746,6 +3761,60 @@ ScalarizedVal legalizeEntryPointReturnValueForGLSL( return result; } +void legalizeTargetBuiltinVar(GLSLLegalizationContext& context) +{ + List<KeyValuePair<IRTargetBuiltinVarName, IRInst*>> workItems; + for (auto [builtinVarName, varInst] : context.builtinVarMap) + { + if (builtinVarName == IRTargetBuiltinVarName::HlslInstanceID) + { + workItems.add(KeyValuePair(builtinVarName, varInst)); + } + } + + auto getOrCreateBuiltinVar = [&](IRTargetBuiltinVarName name, IRType* type) + { + if (auto var = context.builtinVarMap.tryGetValue(name)) + return *var; + IRBuilder builder(context.entryPointFunc); + builder.setInsertBefore(context.entryPointFunc); + IRInst* var = builder.createGlobalParam(type); + builder.addTargetBuiltinVarDecoration(var, name); + return var; + }; + for (auto& kv : workItems) + { + auto builtinVarName = kv.key; + auto varInst = kv.value; + + // Repalce SV_InstanceID with gl_InstanceIndex - gl_BaseInstance. + if (builtinVarName == IRTargetBuiltinVarName::HlslInstanceID) + { + auto instanceIndex = getOrCreateBuiltinVar( + IRTargetBuiltinVarName::SpvInstanceIndex, + varInst->getDataType()); + auto baseInstance = getOrCreateBuiltinVar( + IRTargetBuiltinVarName::SpvBaseInstance, + varInst->getDataType()); + traverseUses( + varInst, + [&](IRUse* use) + { + auto user = use->getUser(); + if (user->getOp() == kIROp_Load) + { + IRBuilder builder(use->getUser()); + builder.setInsertBefore(use->getUser()); + auto sub = builder.emitSub( + tryGetPointedToType(&builder, varInst->getDataType()), + builder.emitLoad(instanceIndex), + builder.emitLoad(baseInstance)); + user->replaceUsesWith(sub); + } + }); + } + } +} void legalizeEntryPointForGLSL( Session* session, @@ -3937,6 +4006,11 @@ void legalizeEntryPointForGLSL( value.globalParam->setFullType(sizedArrayType); } } + + // Some system value vars can't be mapped 1:1 to a GLSL/Vulkan builtin, + // for example, SV_InstanceID should map to gl_InstanceIndex - gl_BaseInstance, + // we will replace these builtins with additional compute logic here. + legalizeTargetBuiltinVar(context); } void decorateModuleWithSPIRVVersion(IRModule* module, SemanticVersion spirvVersion) diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 9ffaeeeb9d..3e2872cb7a 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -926,6 +926,9 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace) INST(ExportDecoration, export, 1, 0) INST_RANGE(LinkageDecoration, ImportDecoration, ExportDecoration) + /// Mark a global variable as a target builtin variable. + INST(TargetBuiltinVarDecoration, TargetBuiltinVar, 1, 0) + /// Marks an inst as coming from an `extern` symbol defined in the user code. INST(UserExternDecoration, UserExtern, 0, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 7c975cfcdf..4efb7d6715 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -193,6 +193,14 @@ enum class IRInterpolationMode PerVertex, }; +enum class IRTargetBuiltinVarName +{ + Unknown, + HlslInstanceID, + SpvInstanceIndex, + SpvBaseInstance, +}; + struct IRInterpolationModeDecoration : IRDecoration { enum @@ -705,6 +713,18 @@ struct IRLinkageDecoration : IRDecoration UnownedStringSlice getMangledName() { return getMangledNameOperand()->getStringSlice(); } }; +// Mark a global variable as a target buitlin variable. +struct IRTargetBuiltinVarDecoration : IRDecoration +{ + IR_LEAF_ISA(TargetBuiltinVarDecoration) + + IRIntLit* getBuiltinVarOperand() { return cast<IRIntLit>(getOperand(0)); } + IRTargetBuiltinVarName getBuiltinVarName() + { + return IRTargetBuiltinVarName(getBuiltinVarOperand()->getValue()); + } +}; + struct IRUserExternDecoration : IRDecoration { enum @@ -4658,6 +4678,18 @@ struct IRBuilder // void addLayoutDecoration(IRInst* value, Layout* layout); IRLayoutDecoration* addLayoutDecoration(IRInst* value, IRLayout* layout); + IRDecoration* addTargetBuiltinVarDecoration( + IRInst* value, + IRTargetBuiltinVarName builtinVarName) + { + IRInst* operands[] = {getIntValue((IRIntegerValue)builtinVarName)}; + return addDecoration( + value, + kIROp_TargetBuiltinVarDecoration, + operands, + SLANG_COUNT_OF(operands)); + } + // IRLayout* getLayout(Layout* astLayout); IRTypeSizeAttr* getTypeSizeAttr(LayoutResourceKind kind, LayoutSize size); diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index c672180b70..b19af364e0 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -422,20 +422,10 @@ struct SPIRVLegalizationContext : public SourceEmitterBase } AddressSpace addressSpace = AddressSpace::ThreadLocal; - // Figure out storage class based on var layout. - if (auto layout = getVarLayout(inst)) - { - auto cls = getGlobalParamAddressSpace(layout); - if (cls != AddressSpace::Generic) - addressSpace = cls; - else if (auto systemValueAttr = layout->findAttr<IRSystemValueSemanticAttr>()) - { - String semanticName = systemValueAttr->getName(); - semanticName = semanticName.toLower(); - if (semanticName == "sv_pointsize") - addressSpace = AddressSpace::BuiltinInput; - } - } + // Figure out storage class based on builtin info or var layout. + auto cls = getGlobalParamAddressSpace(inst); + if (cls != AddressSpace::Generic) + addressSpace = cls; // Don't do any processing for specialization constants. if (addressSpace == AddressSpace::SpecializationConstant) @@ -635,8 +625,22 @@ struct SPIRVLegalizationContext : public SourceEmitterBase return addressSpace; } - AddressSpace getGlobalParamAddressSpace(IRVarLayout* varLayout) + AddressSpace getGlobalParamAddressSpace(IRInst* varInst) { + if (auto builtinDecor = varInst->findDecoration<IRTargetBuiltinVarDecoration>()) + { + switch (builtinDecor->getBuiltinVarName()) + { + case IRTargetBuiltinVarName::SpvInstanceIndex: + case IRTargetBuiltinVarName::SpvBaseInstance: + return AddressSpace::BuiltinInput; + } + } + + auto varLayout = getVarLayout(varInst); + if (!varLayout) + return AddressSpace::Generic; + auto typeLayout = varLayout->getTypeLayout()->unwrapArray(); if (auto parameterGroupTypeLayout = as<IRParameterGroupTypeLayout>(typeLayout)) { @@ -663,15 +667,25 @@ struct SPIRVLegalizationContext : public SourceEmitterBase "resolve a storage class address space."); } } + auto systemValueAttr = varLayout->findSystemValueSemanticAttr(); + + if (systemValueAttr) + { + // TODO: is this needed? + String semanticName = systemValueAttr->getName(); + semanticName = semanticName.toLower(); + if (semanticName == "sv_pointsize") + result = AddressSpace::BuiltinInput; + } switch (result) { case AddressSpace::Input: - if (varLayout->findSystemValueSemanticAttr()) + if (systemValueAttr) result = AddressSpace::BuiltinInput; break; case AddressSpace::Output: - if (varLayout->findSystemValueSemanticAttr()) + if (systemValueAttr) result = AddressSpace::BuiltinOutput; break; } @@ -781,9 +795,9 @@ struct SPIRVLegalizationContext : public SourceEmitterBase { addressSpace = AddressSpace::GroupShared; } - else if (const auto varLayout = getVarLayout(inst)) + else { - auto cls = getGlobalParamAddressSpace(varLayout); + auto cls = getGlobalParamAddressSpace(inst); if (cls != AddressSpace::Generic) addressSpace = cls; } diff --git a/tests/bugs/gh-3087-multi-entry-point.slang b/tests/bugs/gh-3087-multi-entry-point.slang index d3aa574c7c..edfda08afe 100644 --- a/tests/bugs/gh-3087-multi-entry-point.slang +++ b/tests/bugs/gh-3087-multi-entry-point.slang @@ -3,14 +3,20 @@ // CHECK-DAG: OpEntryPoint Vertex // CHECK-DAG: OpEntryPoint Fragment -// we should only have 1 'BuiltIn InstanceIndex' since the `Output` and `Input` semantic -// for `InstanceIndex` should be converted to a non-builtin -// CHECK-DAG: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex -// CHECK-NOT: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex - // We require 1 `Flat` for the fragment input `uint` // CHECK-DAG: OpDecorate %{{[1-9][0-9]*}} Flat -// CHECK-NOT: OpDecorate %{{[1-9][0-9]*}} Flat + +// CHECK-DAG: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex + +// The vertex shader should be using the builtin InstanceIndex var. +// CHECK: %vmain = OpFunction +// CHECK: InstanceIndex +// CHECK: OpFunctionEnd + +// The fragment shader should not be using the builtin InstanceIndex var. +// CHECK: %pmain = OpFunction +// CHECK-NOT: InstanceIndex +// CHECK: OpFunctionEnd struct VIn { diff --git a/tests/hlsl-intrinsic/system-values-draw-parameters.slang b/tests/hlsl-intrinsic/system-values-draw-parameters.slang index e453669398..009efffa1f 100644 --- a/tests/hlsl-intrinsic/system-values-draw-parameters.slang +++ b/tests/hlsl-intrinsic/system-values-draw-parameters.slang @@ -32,7 +32,7 @@ VSOutput main(VSInput input, // CHECK_HLSL: SV_StartVertexLocation // CHECK_METAL: base_vertex - // CHECK_SPIRV: BuiltIn BaseInstance + // CHECK_SPIRV: BuiltIn InstanceIndex // CHECK_GLSL: gl_BaseInstance // CHECK_HLSL: SV_StartInstanceLocation // CHECK_METAL: base_instance diff --git a/tests/spirv/sv_instance.slang b/tests/spirv/sv_instance.slang new file mode 100644 index 0000000000..e71c6c7faf --- /dev/null +++ b/tests/spirv/sv_instance.slang @@ -0,0 +1,14 @@ +//TEST:SIMPLE(filecheck=GLSL): -target glsl -entry vertMain -stage vertex +//TEST:SIMPLE(filecheck=CHECK): -target spirv + +// CHECK-DAG: %[[REG1:[0-9a-zA-Z_]+]] = OpLoad %int %gl_BaseInstance +// CHECK-DAG: %[[REG2:[0-9a-zA-Z_]+]] = OpLoad %int %gl_InstanceIndex +// CHECK-DAG: OpISub %int %[[REG2]] %[[REG1]] + +// GLSL: gl_InstanceIndex - gl_BaseInstance + +[shader("vertex")] +float4 vertMain(int i : SV_InstanceID) : SV_Position +{ + return i; +} \ No newline at end of file From 04da85c1e69cb68021437a3ec8385686dfd7f49e Mon Sep 17 00:00:00 2001 From: Yong He <yonghe@outlook.com> Date: Thu, 27 Feb 2025 15:38:03 -0800 Subject: [PATCH 2/2] Fix ci. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cf72fdee1..ffc64ee35c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: -expected-failure-list tests/expected-failure-record-replay-tests.txt fi - name: Run Slang examples - if: steps.filter.outputs.should-run == 'true' && matrix.platform != 'wasm' + if: steps.filter.outputs.should-run == 'true' && matrix.platform != 'wasm' && matrix.full-gpu-tests run: | .github/workflows/ci-examples.sh \ --bin-dir "$bin_dir" \