diff options
| author | davli-nv <davli@nvidia.com> | 2025-08-20 17:30:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-21 00:30:44 +0000 |
| commit | 05f0f5603561daed2c134e13bc64649362759968 (patch) | |
| tree | ff1ea0eb835dd636a459603ea0285290d504b9b7 | |
| parent | cbd73dde3dd2da790bb663385a229ce22965c43c (diff) | |
Implement SV_VulkanSamplePosition (#8236)
-Adds semantic SV_VulkanSamplePosition that emits corresponding
gl_SamplePosition and SpvBuiltinSamplePosition
-Adds gl_SamplePosition property to glsl.meta.slang
-Adds SPIRV and GLSL tests for the semantic and property
-Plan is to later implement SV_SamplePosition that follows HLSL range of
-0.5 to +0.5,
and emits GetRenderTargetSamplePosition(SV_SampleIndex) which needs more
complicated IR manipulation for HLSL and Metal
Fixes #7906
---------
Co-authored-by: ArielG-NV <159081215+ArielG-NV@users.noreply.github.com>
| -rw-r--r-- | docs/user-guide/a2-01-spirv-target-specific.md | 3 | ||||
| -rw-r--r-- | docs/user-guide/a2-02-metal-target-specific.md | 1 | ||||
| -rw-r--r-- | docs/user-guide/a2-03-wgsl-target-specific.md | 1 | ||||
| -rw-r--r-- | source/slang/glsl.meta.slang | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir-legalize-varying-params.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-parameter-binding.cpp | 5 | ||||
| -rw-r--r-- | tests/spirv/sv-vulkan-sample-position.slang | 21 |
9 files changed, 44 insertions, 3 deletions
diff --git a/docs/user-guide/a2-01-spirv-target-specific.md b/docs/user-guide/a2-01-spirv-target-specific.md index 0f64a5e1b..899fb39fd 100644 --- a/docs/user-guide/a2-01-spirv-target-specific.md +++ b/docs/user-guide/a2-01-spirv-target-specific.md @@ -95,9 +95,10 @@ The system-value semantics are translated to the following SPIR-V code. | `SV_ViewID` | `BuiltIn ViewIndex` | | `SV_ViewportArrayIndex` | `BuiltIn ViewportIndex` | | `SV_VulkanInstanceID` | `BuiltIn InstanceIndex` | +| `SV_VulkanSamplePosition` | `BuiltIn SamplePosition` | | `SV_VulkanVertexID` | `BuiltIn VertexIndex` | -*Note* that `SV_DrawIndex`, `SV_FragInvocationCount`, `SV_FragSize`, `SV_PointSize` and `SV_PointCoord` are Slang-specific semantics that are not defined in HLSL. +*Note* that `SV_DrawIndex`, `SV_FragInvocationCount`, `SV_FragSize`, `SV_PointSize`, `SV_PointCoord` and `SV_VulkanSamplePosition` are Slang-specific semantics that are not defined in HLSL. Also *Note* that `SV_InstanceID`/`SV_VertexID` counts all instances/vertices in a draw call, unlike how `InstanceIndex`/`VertexIndex` is relative to `BaseInstance`/`BaseVertex`. See [Using SV_InstanceID/SV_VertexID with SPIR-V target](#using-sv_instanceid-and-sv_vertexid-with-spir-v-target) diff --git a/docs/user-guide/a2-02-metal-target-specific.md b/docs/user-guide/a2-02-metal-target-specific.md index 5d3e336db..62af51a0e 100644 --- a/docs/user-guide/a2-02-metal-target-specific.md +++ b/docs/user-guide/a2-02-metal-target-specific.md @@ -47,6 +47,7 @@ The system-value semantics are translated to the following Metal attributes: | `SV_StartVertexLocation` | `[[base_vertex]]` | | `SV_StartInstanceLocation` | `[[base_instance]]` | | `SV_VulkanInstanceID` | `[[instance_id]]` | +| `SV_VulkanSamplePosition` | `(Not supported)` | | `SV_VulkanVertexID` | `[[vertex_id]]` | Custom semantics are mapped to user attributes: diff --git a/docs/user-guide/a2-03-wgsl-target-specific.md b/docs/user-guide/a2-03-wgsl-target-specific.md index 35aecd291..a16ca946e 100644 --- a/docs/user-guide/a2-03-wgsl-target-specific.md +++ b/docs/user-guide/a2-03-wgsl-target-specific.md @@ -53,6 +53,7 @@ The system-value semantics are translated to the following WGSL code. | SV_ViewID | *Not supported* | | SV_ViewportArrayIndex | *Not supported* | | SV_VulkanInstanceID | `@builtin(instance_index)` | +| SV_VulkanSamplePosition | *Not supported* | | SV_VulkanVertexID | `@builtin(vertex_index)` | diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang index 5a78a9960..9112c1d2a 100644 --- a/source/slang/glsl.meta.slang +++ b/source/slang/glsl.meta.slang @@ -219,6 +219,8 @@ public in int gl_BaseInstance : SV_StartInstanceLocation; public in int gl_FragInvocationCountEXT : SV_FragInvocationCount; public in int2 gl_FragSizeEXT : SV_FragSize; +public in float2 gl_SamplePosition : SV_VulkanSamplePosition; + // Override operator* behavior to compute algebric product of matrices and vectors. diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index aa4c3bec8..6b42896d0 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -6182,6 +6182,11 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex requireSPIRVCapability(SpvCapabilitySampleRateShading); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInSampleId, inst); } + else if (semanticName == "sv_vulkansampleposition") + { + requireSPIRVCapability(SpvCapabilitySampleRateShading); + return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInSamplePosition, inst); + } else if (semanticName == "sv_stencilref") { requireSPIRVCapability(SpvCapabilityStencilExportEXT); diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index d1a534c66..65b997195 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -756,6 +756,14 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo( requiredType = builder->getBasicType(BaseType::Int); name = "gl_SampleID"; } + else if (semanticName == "sv_vulkansampleposition") + { + context->requireGLSLVersion(ProfileVersion::GLSL_400); + requiredType = builder->getVectorType( + builder->getBasicType(BaseType::Float), + builder->getIntValue(builder->getIntType(), 2)); + name = "gl_SamplePosition"; + } else if (semanticName == "sv_stencilref") { // uint in hlsl, int in glsl diff --git a/source/slang/slang-ir-legalize-varying-params.h b/source/slang/slang-ir-legalize-varying-params.h index 4f23b1e6d..14a5c5d97 100644 --- a/source/slang/slang-ir-legalize-varying-params.h +++ b/source/slang/slang-ir-legalize-varying-params.h @@ -75,6 +75,7 @@ void depointerizeInputParams(IRFunc* entryPoint); M(QuadLaneIndex, SV_QuadLaneIndex) \ M(VulkanVertexID, SV_VulkanVertexID) \ M(VulkanInstanceID, SV_VulkanInstanceID) \ + M(VulkanSamplePosition, SV_VulkanSamplePosition) \ M(Barycentrics, SV_Barycentrics) \ /* end */ diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index 89e633857..4b91056fc 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -1821,11 +1821,12 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter( // We need to compute whether an entry point consumes // any sample-rate inputs, and along with explicitly // `sample`-qualified parameters, we also need to - // detect use of `SV_SampleIndex` as an input. + // detect use of `SV_SampleIndex` and + // `SV_VulkanSamplePosition` as an input. // if (state.directionMask & kEntryPointParameterDirection_Input) { - if (sn == "sv_sampleindex") + if (sn == "sv_sampleindex" || sn == "sv_vulkansampleposition") { state.isSampleRate = true; } diff --git a/tests/spirv/sv-vulkan-sample-position.slang b/tests/spirv/sv-vulkan-sample-position.slang new file mode 100644 index 000000000..853ae03ac --- /dev/null +++ b/tests/spirv/sv-vulkan-sample-position.slang @@ -0,0 +1,21 @@ +//TEST:SIMPLE(filecheck=CHECK-SPIRV): -target spirv -stage fragment -entry main +//TEST:SIMPLE(filecheck=CHECK-GLSL): -target glsl -stage fragment -entry main + +// Test for SV_VulkanSamplePosition support + +// CHECK-SPIRV: OpCapability SampleRateShading +// CHECK-SPIRV-DAG: OpDecorate {{.*}} BuiltIn SamplePosition +// CHECK-GLSL-DAG: gl_SamplePosition + +import glsl; + +struct FragmentInput +{ + float2 samplePosition : SV_VulkanSamplePosition; +} + +[shader("fragment")] +float4 main(FragmentInput input) : SV_Target +{ + return float4(input.samplePosition.x, gl_SamplePosition.y, 0.0, 1.0); +}
\ No newline at end of file |
