Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPIR-V SV_InstanceId support in pixel shader #4368

34 changes: 31 additions & 3 deletions source/slang/slang-ir-glsl-legalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,36 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
declarator,
&systemValueInfoStorage);

{

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"))
&& ((stage == Stage::Fragment) || (stage == Stage::Vertex && inVarLayout->usesResourceKind(LayoutResourceKind::VaryingOutput))))
{
ShortList<IRInst*> newOperands;
auto opCount = inVarLayout->getOperandCount();
newOperands.reserveOverflowBuffer(opCount);
for (UInt i = 0; i < opCount; ++i)
{
auto op = inVarLayout->getOperand(i);
if (op == systemSemantic)
continue;
newOperands.add(op);
}

auto newVarLayout = builder->emitIntrinsicInst(
inVarLayout->getFullType(),
inVarLayout->getOp(),
newOperands.getCount(),
newOperands.getArrayView().getBuffer());

newVarLayout->sourceLoc = inVarLayout->sourceLoc;

inVarLayout->replaceUsesWith(newVarLayout);
}
}

IRType* type = inType;
IRType* peeledRequiredType = nullptr;

Expand Down Expand Up @@ -2570,9 +2600,7 @@ static void legalizeMeshOutputParam(
//

// First, collect the subset of outputs being used
const bool isSPIRV = codeGenContext->getTargetFormat() == CodeGenTarget::SPIRV
|| codeGenContext->getTargetFormat() == CodeGenTarget::SPIRVAssembly;
if(!isSPIRV)
if(!isSPIRV(codeGenContext->getTargetFormat()))
{
auto isMeshOutputBuiltin = [](IRInst* g)
{
Expand Down
7 changes: 7 additions & 0 deletions source/slang/slang-ir-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,13 @@ void verifyComputeDerivativeGroupModifiers(
bool linearAttr,
IRNumThreadsDecoration* numThreadsDecor);


inline bool isSPIRV(CodeGenTarget codeGenTarget)
{
return codeGenTarget == CodeGenTarget::SPIRV
|| codeGenTarget == CodeGenTarget::SPIRVAssembly;
}

}

#endif
15 changes: 15 additions & 0 deletions source/slang/slang-parameter-binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "slang-lookup.h"
#include "slang-compiler.h"
#include "slang-type-layout.h"
#include "slang-ir-util.h"

#include "../compiler-core/slang-artifact-desc-util.h"

Expand Down Expand Up @@ -1640,6 +1641,20 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
type,
kEntryPointParameterDirection_Output);
}
else if (isSPIRV(context->getTargetRequest()->getTarget())
&& (
(state.directionMask & kEntryPointParameterDirection_Input && state.stage == Stage::Fragment)
|| (state.directionMask & kEntryPointParameterDirection_Output && state.stage == Stage::Vertex)
)
&& sn == "sv_instanceid"
)
{
// This fragment-shader-input/vertex-shader-output is effectively not a system semantic for SPIR-V,
typeLayout = getSimpleVaryingParameterTypeLayout(
context->layoutContext,
type,
state.directionMask);
}
else
{
// For a system-value parameter (that didn't match the
Expand Down
38 changes: 38 additions & 0 deletions tests/bugs/gh-3087-multi-entry-point.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//TEST:SIMPLE(filecheck=CHECK): -target spirv -fvk-use-entrypoint-name -emit-spirv-directly

// 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: BuiltIn InstanceIndex
// CHECK-NOT: BuiltIn InstanceIndex

// We require 1 `Flat` for the fragment input `uint`
// SPIRV: Flat
// SPIRV-NOT: Flat

struct VIn
{
uint instanceID : SV_InstanceID;
}

struct VSOutput
{
uint instanceID : SV_InstanceID;
float4 color : COLOR;
};

[shader("vertex")]
VSOutput vmain(VIn vin) {
VSOutput t;
t.instanceID = vin.instanceID;
t.color = float4(0, 0, 0, 0);
return t;
}

[shader("pixel")]
float4 pmain(VSOutput input) : SV_TARGET
{
return float4(float(input.instanceID), input.color.xyz);
}
28 changes: 28 additions & 0 deletions tests/bugs/gh-3087.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//TEST:SIMPLE(filecheck=HLSL): -entry main -target hlsl
//TEST:SIMPLE(filecheck=GLSL): -entry main -target glsl
//TEST:SIMPLE(filecheck=SPIRV): -entry main -target spirv

// HLSL-DAG: main
// HLSL-DAG: SV_InstanceID

// GLSL-DAG: main
// GLSL-DAG: gl_InstanceIndex

// SPIRV: OpEntryPoint
// SPIRV-NOT: BuiltIn InstanceIndex
// We require 1 `Flat` for the fragment input `uint`
// SPIRV: Flat
// SPIRV-NOT: Flat


struct PSInput
{
uint vInstance : SV_InstanceID;
float4 color : COLOR;
};

[shader("pixel")]
float4 main(PSInput input) : SV_TARGET
{
return input.color + float(input.vInstance).xxxx;
}
Loading