summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-spirv.cpp21
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp55
-rw-r--r--tests/pipeline/rasterization/get-attribute-at-vertex-struct.slang38
-rw-r--r--tests/pipeline/rasterization/get-attribute-at-vertex.slang25
4 files changed, 108 insertions, 31 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index a5a77e148..0a755cd6d 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -6211,11 +6211,24 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
requireSPIRVCapability(SpvCapabilityFragmentBarycentricKHR);
ensureExtensionDeclaration(
UnownedStringSlice("SPV_KHR_fragment_shader_barycentric"));
- return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaryCoordKHR, inst);
- // TODO: There is also the `gl_BaryCoordNoPerspNV` builtin, which
- // we ought to use if the `noperspective` modifier has been
- // applied to this varying input.
+ auto interpolationModeDecor =
+ inst->findDecoration<IRInterpolationModeDecoration>();
+ if (interpolationModeDecor &&
+ interpolationModeDecor->getMode() == IRInterpolationMode::NoPerspective)
+ {
+ return getBuiltinGlobalVar(
+ inst->getFullType(),
+ SpvBuiltInBaryCoordNoPerspKHR,
+ inst);
+ }
+ else
+ {
+ return getBuiltinGlobalVar(
+ inst->getFullType(),
+ SpvBuiltInBaryCoordKHR,
+ inst);
+ }
}
else if (semanticName == "sv_cullprimitive")
{
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index dce85efd3..d1a534c66 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -391,6 +391,20 @@ GLSLSystemValueInfo* getMeshOutputIndicesSystemValueInfo(
SLANG_UNREACHABLE("Unhandled mesh output indices type");
}
+// Hold the in-stack linked list that represents the access chain
+// to the current global varying parameter being created.
+// e.g. if the user code has:
+// struct Params { in float member; }
+// void main(in Params inParams);
+// Then the `outerParamInfo` when we get to `createSimpleGLSLVarying` for `member`
+// will be: {IRStructField member} -> {IRParam inParams} -> {IRFunc main}.
+//
+struct OuterParamInfoLink
+{
+ IRInst* outerParam;
+ OuterParamInfoLink* next;
+};
+
GLSLSystemValueInfo* getGLSLSystemValueInfo(
GLSLLegalizationContext* context,
CodeGenContext* codeGenContext,
@@ -399,7 +413,8 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
Stage stage,
IRType* type,
GlobalVaryingDeclarator* declarator,
- GLSLSystemValueInfo* inStorage)
+ GLSLSystemValueInfo* inStorage,
+ OuterParamInfoLink* outerParamInfo)
{
SLANG_UNUSED(codeGenContext);
@@ -864,11 +879,26 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
context->requireGLSLVersion(ProfileVersion::GLSL_450);
context->requireGLSLExtension(
UnownedStringSlice::fromLiteral("GL_EXT_fragment_shader_barycentric"));
+
name = "gl_BaryCoordEXT";
- // TODO: There is also the `gl_BaryCoordNoPerspNV` builtin, which
- // we ought to use if the `noperspective` modifier has been
- // applied to this varying input.
+ // Search for nointerpolation keyword to use no-perspective variant of BaryCoord
+ for (auto paramInfo = outerParamInfo; paramInfo; paramInfo = paramInfo->next)
+ {
+ auto outerParam = paramInfo->outerParam;
+ auto decorParent = outerParam;
+ if (auto field = as<IRStructField>(decorParent))
+ decorParent = field->getKey();
+ auto interpolation = decorParent->findDecoration<IRInterpolationModeDecoration>();
+ if (!interpolation || interpolation->getMode() != IRInterpolationMode::NoPerspective)
+ continue;
+ name = "gl_BaryCoordNoPerspEXT";
+ break;
+ }
+
+ requiredType = builder->getVectorType(
+ builder->getBasicType(BaseType::Float),
+ builder->getIntValue(builder->getIntType(), 3));
}
else if (semanticName == "sv_cullprimitive")
{
@@ -938,20 +968,6 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
return nullptr;
}
-// Hold the in-stack linked list that represents the access chain
-// to the current global varying parameter being created.
-// e.g. if the user code has:
-// struct Params { in float member; }
-// void main(in Params inParams);
-// Then the `outerParamInfo` when we get to `createSimpleGLSLVarying` for `member`
-// will be: {IRStructField member} -> {IRParam inParams} -> {IRFunc main}.
-//
-struct OuterParamInfoLink
-{
- IRInst* outerParam;
- OuterParamInfoLink* next;
-};
-
void createVarLayoutForLegalizedGlobalParam(
GLSLLegalizationContext* context,
IRInst* globalParam,
@@ -1318,7 +1334,8 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
stage,
inType,
declarator,
- &systemValueInfoStorage);
+ &systemValueInfoStorage,
+ outerParamInfo);
{
diff --git a/tests/pipeline/rasterization/get-attribute-at-vertex-struct.slang b/tests/pipeline/rasterization/get-attribute-at-vertex-struct.slang
new file mode 100644
index 000000000..a63be1718
--- /dev/null
+++ b/tests/pipeline/rasterization/get-attribute-at-vertex-struct.slang
@@ -0,0 +1,38 @@
+// get-attribute-at-vertex-struct.slang
+
+// Test GetAttributeAtVertex and SV_Barycentrics on struct members
+
+//TEST:SIMPLE(filecheck=CHECK-SPIRV):-target spirv -entry main -stage fragment -profile glsl_450+GL_EXT_fragment_shader_barycentric
+//TEST:SIMPLE(filecheck=CHECK-GLSL):-target glsl -entry main -stage fragment -profile glsl_450+GL_EXT_fragment_shader_barycentric
+
+// CHECK-SPIRV: OpCapability FragmentBarycentricKHR
+// CHECK-SPIRV: OpExtension "SPV_KHR_fragment_shader_barycentric"
+
+// CHECK-SPIRV: OpEntryPoint Fragment %main "main"
+// CHECK-SPIRV: OpDecorate %{{.*}} BuiltIn BaryCoordKHR
+// CHECK-SPIRV: OpDecorate %{{.*}} BuiltIn BaryCoordNoPerspKHR
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_0
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_1
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_2
+
+// CHECK-GLSL: #extension GL_EXT_fragment_shader_barycentric : require
+// CHECK-GLSL-DAG: gl_BaryCoordEXT
+// CHECK-GLSL-DAG: gl_BaryCoordNoPerspEXT
+
+struct Input
+{
+ pervertex float4 color : COLOR;
+ float3 bary : SV_Barycentrics;
+ noperspective float3 baryNoPerspective : SV_Barycentrics;
+}
+
+[shader("fragment")]
+void main(
+ Input input,
+ out float4 result : SV_Target)
+{
+ result = input.bary.x * GetAttributeAtVertex(input.color, 0)
+ + input.bary.y * GetAttributeAtVertex(input.color, 1)
+ + input.bary.z * GetAttributeAtVertex(input.color, 2)
+ + input.baryNoPerspective.x * 0.1f;
+} \ No newline at end of file
diff --git a/tests/pipeline/rasterization/get-attribute-at-vertex.slang b/tests/pipeline/rasterization/get-attribute-at-vertex.slang
index c334200fb..342796b90 100644
--- a/tests/pipeline/rasterization/get-attribute-at-vertex.slang
+++ b/tests/pipeline/rasterization/get-attribute-at-vertex.slang
@@ -2,23 +2,32 @@
// Basic test for `GetAttributeAtVertex` function
-//TEST:SIMPLE(filecheck=CHECK):-emit-spirv-directly -target spirv -entry main -stage fragment -profile glsl_450+GL_EXT_fragment_shader_barycentric
+//TEST:SIMPLE(filecheck=CHECK-SPIRV):-target spirv -entry main -stage fragment -profile glsl_450+GL_EXT_fragment_shader_barycentric
+//TEST:SIMPLE(filecheck=CHECK-GLSL):-target glsl -entry main -stage fragment -profile glsl_450+GL_EXT_fragment_shader_barycentric
-// CHECK: OpCapability FragmentBarycentricKHR
-// CHECK: OpExtension "SPV_KHR_fragment_shader_barycentric"
+// CHECK-SPIRV: OpCapability FragmentBarycentricKHR
+// CHECK-SPIRV: OpExtension "SPV_KHR_fragment_shader_barycentric"
-// CHECK: OpEntryPoint Fragment %main "main"
-// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_0
-// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_1
-// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_2
+// CHECK-SPIRV: OpEntryPoint Fragment %main "main"
+// CHECK-SPIRV: OpDecorate %{{.*}} BuiltIn BaryCoordKHR
+// CHECK-SPIRV: OpDecorate %{{.*}} BuiltIn BaryCoordNoPerspKHR
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_0
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_1
+// CHECK-SPIRV: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_2
+
+// CHECK-GLSL: #extension GL_EXT_fragment_shader_barycentric : require
+// CHECK-GLSL-DAG: gl_BaryCoordEXT
+// CHECK-GLSL-DAG: gl_BaryCoordNoPerspEXT
[shader("fragment")]
void main(
pervertex float4 color : COLOR,
float3 bary : SV_Barycentrics,
+ noperspective float3 baryNoPerspective : SV_Barycentrics,
out float4 result : SV_Target)
{
result = bary.x * GetAttributeAtVertex(color, 0)
+ bary.y * GetAttributeAtVertex(color, 1)
- + bary.z * GetAttributeAtVertex(color, 2);
+ + bary.z * GetAttributeAtVertex(color, 2)
+ + baryNoPerspective.x * 0.1f;
}