diff options
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 21 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 55 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/get-attribute-at-vertex-struct.slang | 38 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/get-attribute-at-vertex.slang | 25 |
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; } |
