Skip to content

Commit c89bffb

Browse files
committed
Implement SampleCmpBias and SampleCmpGrad
these are new for HLSL shader model 6.8 fixes #8929
1 parent 8b2faea commit c89bffb

File tree

4 files changed

+345
-1
lines changed

4 files changed

+345
-1
lines changed

docs/user-guide/a3-02-reference-capability-atoms.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,10 @@ Compound Capabilities
13241324
`texture_querylod`
13251325
> Capabilities required to query texture LOD info
13261326
1327+
`texture_shadowgrad`
1328+
> Capabilities required for shadow texture sampling with bias and gradients.
1329+
> New in HLSL SM6.8 but existed in older GLSL and SPIRV targets.
1330+
13271331
`texture_shadowlod`
13281332
> Capabilities required to query shadow texture lod info
13291333

source/slang/hlsl.meta.slang

Lines changed: 281 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
10621062
///
10631063
/// For HLSL/D3D targets, the texture element type must be a scalar or vector of float or half types.
10641064
///
1065-
///@see `SampleBias`, `SampleLevel`, `SampleLevelZero`, `SampleGrad`, `SampleCmp`, `SampleCmpLevelZero`, `SampleCmpLevel`.
1065+
///@see `SampleBias`, `SampleLevel`, `SampleLevelZero`, `SampleGrad`, `SampleCmp`, `SampleCmpLevelZero`, `SampleCmpLevel`, `SampleCmpBias`, `SampleCmpGrad`.
10661066
[__readNone]
10671067
[ForceInline]
10681068
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)]
@@ -1584,6 +1584,143 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
15841584
}
15851585
}
15861586

1587+
[__readNone]
1588+
[ForceInline]
1589+
[require(hlsl_spirv, texture_shadowgrad)]
1590+
float SampleCmpGrad(vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY)
1591+
{
1592+
__target_switch
1593+
{
1594+
case hlsl:
1595+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1596+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1597+
, "HLSL supports only float and half type textures");
1598+
return __getTexture().SampleCmpGrad(__getComparisonSampler(), location, compareValue, gradX, gradY);
1599+
case spirv:
1600+
return spirv_asm
1601+
{
1602+
result:$$float = OpImageSampleDrefExplicitLod $this $location $compareValue Grad $gradX $gradY;
1603+
};
1604+
}
1605+
}
1606+
1607+
[__readNone]
1608+
[ForceInline]
1609+
[require(hlsl_spirv, texture_shadowgrad)]
1610+
float SampleCmpGrad(vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset)
1611+
{
1612+
__target_switch
1613+
{
1614+
case hlsl:
1615+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1616+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1617+
, "HLSL supports only float and half type textures");
1618+
return __getTexture().SampleCmpGrad(__getComparisonSampler(), location, compareValue, gradX, gradY, offset);
1619+
case spirv:
1620+
return spirv_asm
1621+
{
1622+
result:$$float = OpImageSampleDrefExplicitLod $this $location $compareValue Grad|ConstOffset $gradX $gradY $offset;
1623+
};
1624+
}
1625+
}
1626+
1627+
[__readNone]
1628+
[ForceInline]
1629+
[require(hlsl_spirv, texture_shadowgrad)]
1630+
float SampleCmpGrad(vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
1631+
{
1632+
__target_switch
1633+
{
1634+
case hlsl:
1635+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1636+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1637+
, "HLSL supports only float and half type textures");
1638+
return __getTexture().SampleCmpGrad(__getComparisonSampler(), location, compareValue, gradX, gradY, offset, status);
1639+
case spirv:
1640+
return spirv_asm
1641+
{
1642+
OpCapability SparseResidency;
1643+
%sparseResultType = OpTypeStruct $$uint $$float;
1644+
1645+
%sparseResult:%sparseResultType = OpImageSparseSampleDrefExplicitLod $this $location $compareValue Grad|ConstOffset $gradX $gradY $offset;
1646+
1647+
%residentCode:$$uint = OpCompositeExtract %sparseResult 0;
1648+
OpStore &status %residentCode;
1649+
result:$$float = OpCompositeExtract %sparseResult 1;
1650+
};
1651+
}
1652+
}
1653+
1654+
[__readNone]
1655+
[ForceInline]
1656+
[require(hlsl_spirv, texture_shadowgrad)]
1657+
float SampleCmpBias(vector<float, Shape.dimensions+isArray> location, float compareValue, float bias)
1658+
{
1659+
__requireComputeDerivative();
1660+
__target_switch
1661+
{
1662+
case hlsl:
1663+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1664+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1665+
, "HLSL supports only float and half type textures");
1666+
return __getTexture().SampleCmpBias(__getComparisonSampler(), location, compareValue, bias);
1667+
case spirv:
1668+
return spirv_asm
1669+
{
1670+
result:$$float = OpImageSampleDrefImplicitLod $this $location $compareValue Bias $bias;
1671+
};
1672+
}
1673+
}
1674+
1675+
[__readNone]
1676+
[ForceInline]
1677+
[require(hlsl_spirv, texture_shadowgrad)]
1678+
float SampleCmpBias(vector<float, Shape.dimensions+isArray> location, float compareValue, float bias, constexpr vector<int, Shape.planeDimensions> offset)
1679+
{
1680+
__requireComputeDerivative();
1681+
__target_switch
1682+
{
1683+
case hlsl:
1684+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1685+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1686+
, "HLSL supports only float and half type textures");
1687+
return __getTexture().SampleCmpBias(__getComparisonSampler(), location, compareValue, bias, offset);
1688+
case spirv:
1689+
return spirv_asm
1690+
{
1691+
result:$$float = OpImageSampleDrefImplicitLod $this $location $compareValue Bias|ConstOffset $bias $offset;
1692+
};
1693+
}
1694+
}
1695+
1696+
[__readNone]
1697+
[ForceInline]
1698+
[require(hlsl_spirv, texture_shadowgrad)]
1699+
float SampleCmpBias(vector<float, Shape.dimensions+isArray> location, float compareValue, float bias, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
1700+
{
1701+
__requireComputeDerivative();
1702+
__target_switch
1703+
{
1704+
case hlsl:
1705+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
1706+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
1707+
, "HLSL supports only float and half type textures");
1708+
return __getTexture().SampleCmpBias(__getComparisonSampler(), location, compareValue, bias, offset, status);
1709+
case spirv:
1710+
return spirv_asm
1711+
{
1712+
OpCapability SparseResidency;
1713+
%sparseResultType = OpTypeStruct $$uint $$float;
1714+
1715+
%sparseResult:%sparseResultType = OpImageSparseSampleDrefImplicitLod $this $location $compareValue Bias|ConstOffset $bias $offset;
1716+
1717+
%residentCode:$$uint = OpCompositeExtract %sparseResult 0;
1718+
OpStore &status %residentCode;
1719+
result:$$float = OpCompositeExtract %sparseResult 1;
1720+
};
1721+
}
1722+
}
1723+
15871724
[__readNone]
15881725
[ForceInline]
15891726
[require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)]
@@ -2783,6 +2920,149 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
27832920
}
27842921
}
27852922

2923+
[__readNone]
2924+
[ForceInline]
2925+
[require(hlsl_spirv, texture_shadowgrad)]
2926+
float SampleCmpGrad(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY)
2927+
{
2928+
__target_switch
2929+
{
2930+
case hlsl:
2931+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
2932+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
2933+
, "HLSL supports only float and half type textures");
2934+
__intrinsic_asm ".SampleCmpGrad";
2935+
case spirv:
2936+
return spirv_asm
2937+
{
2938+
%sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
2939+
result:$$float = OpImageSampleDrefExplicitLod %sampledImage $location $compareValue Grad $gradX $gradY;
2940+
};
2941+
}
2942+
}
2943+
2944+
[__readNone]
2945+
[ForceInline]
2946+
[require(hlsl_spirv, texture_shadowgrad)]
2947+
float SampleCmpGrad(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset)
2948+
{
2949+
__target_switch
2950+
{
2951+
case hlsl:
2952+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
2953+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
2954+
, "HLSL supports only float and half type textures");
2955+
__intrinsic_asm ".SampleCmpGrad";
2956+
case spirv:
2957+
return spirv_asm
2958+
{
2959+
%sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
2960+
result:$$float = OpImageSampleDrefExplicitLod %sampledImage $location $compareValue Grad|ConstOffset $gradX $gradY $offset;
2961+
};
2962+
}
2963+
}
2964+
2965+
[__readNone]
2966+
[ForceInline]
2967+
[require(hlsl_spirv, texture_shadowgrad)]
2968+
float SampleCmpGrad(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
2969+
{
2970+
__target_switch
2971+
{
2972+
case hlsl:
2973+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
2974+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
2975+
, "HLSL supports only float and half type textures");
2976+
__intrinsic_asm ".SampleCmpGrad";
2977+
case spirv:
2978+
return spirv_asm
2979+
{
2980+
OpCapability SparseResidency;
2981+
%sparseResultType = OpTypeStruct $$uint $$float;
2982+
%sampledImage:__sampledImageType(this) = OpSampledImage $this $s;
2983+
2984+
%sparseResult:%sparseResultType = OpImageSparseSampleDrefExplicitLod %sampledImage $location $compareValue Grad|ConstOffset $gradX $gradY $offset;
2985+
2986+
%residentCode:$$uint = OpCompositeExtract %sparseResult 0;
2987+
OpStore &status %residentCode;
2988+
result:$$float = OpCompositeExtract %sparseResult 1;
2989+
};
2990+
}
2991+
}
2992+
2993+
[__readNone]
2994+
[ForceInline]
2995+
[require(hlsl_spirv, texture_shadowgrad)]
2996+
float SampleCmpBias(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float bias)
2997+
{
2998+
__requireComputeDerivative();
2999+
__target_switch
3000+
{
3001+
case hlsl:
3002+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
3003+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
3004+
, "HLSL supports only float and half type textures");
3005+
__intrinsic_asm ".SampleCmpBias";
3006+
case spirv:
3007+
return spirv_asm
3008+
{
3009+
%sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
3010+
result:$$float = OpImageSampleDrefImplicitLod %sampledImage $location $compareValue Bias $bias;
3011+
};
3012+
}
3013+
}
3014+
3015+
[__readNone]
3016+
[ForceInline]
3017+
[require(hlsl_spirv, texture_shadowgrad)]
3018+
float SampleCmpBias(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float bias, constexpr vector<int, Shape.planeDimensions> offset)
3019+
{
3020+
__requireComputeDerivative();
3021+
__target_switch
3022+
{
3023+
case hlsl:
3024+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
3025+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
3026+
, "HLSL supports only float and half type textures");
3027+
__intrinsic_asm ".SampleCmpBias";
3028+
case spirv:
3029+
return spirv_asm
3030+
{
3031+
%sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
3032+
result:$$float = OpImageSampleDrefImplicitLod %sampledImage $location $compareValue Bias|ConstOffset $bias $offset;
3033+
};
3034+
}
3035+
}
3036+
3037+
[__readNone]
3038+
[ForceInline]
3039+
[require(hlsl_spirv, texture_shadowgrad)]
3040+
float SampleCmpBias(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float bias, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
3041+
{
3042+
__requireComputeDerivative();
3043+
__target_switch
3044+
{
3045+
case hlsl:
3046+
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
3047+
|| T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4>
3048+
, "HLSL supports only float and half type textures");
3049+
__intrinsic_asm ".SampleCmpBias";
3050+
case spirv:
3051+
return spirv_asm
3052+
{
3053+
OpCapability SparseResidency;
3054+
%sparseResultType = OpTypeStruct $$uint $$float;
3055+
%sampledImage:__sampledImageType(this) = OpSampledImage $this $s;
3056+
3057+
%sparseResult:%sparseResultType = OpImageSparseSampleDrefImplicitLod %sampledImage $location $compareValue Bias|ConstOffset $bias $offset;
3058+
3059+
%residentCode:$$uint = OpCompositeExtract %sparseResult 0;
3060+
OpStore &status %residentCode;
3061+
result:$$float = OpCompositeExtract %sparseResult 1;
3062+
};
3063+
}
3064+
}
3065+
27863066
[__readNone]
27873067
[ForceInline]
27883068
[require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0)]

source/slang/slang-capabilities.capdef

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,10 @@ alias texture_querylevels = texture_sm_4_1 | GL_ARB_texture_query_levels;
21042104
/// [Compound]
21052105
alias texture_shadowlod = texture_sm_4_1 | GL_EXT_texture_shadow_lod
21062106
| texture_sm_4_1;
2107+
/// Capabilities required for shadow texture sampling with bias and gradients.
2108+
/// New in HLSL SM6.8 but existed in older GLSL and SPIRV targets.
2109+
/// [Compound]
2110+
alias texture_shadowgrad = sm_6_8_version | GL_EXT_texture_shadow_lod;
21072111

21082112
/// (GLSL/SPIRV) Capabilities required to use GLSL-tier-1 float-atomic operations
21092113
/// [Compound]
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Test shader for SampleCmpGrad and SampleCmpBias functions
2+
//TEST:SIMPLE(filecheck=CHECK_HLSL): -stage fragment -entry fragmentMain -target hlsl
3+
//TEST:SIMPLE(filecheck=CHECK_DXIL): -target dxil-assembly -entry fragmentMain -stage fragment -profile ps_6_8
4+
//TEST:SIMPLE(filecheck=CHECK_SPIRV): -stage fragment -entry fragmentMain -target spirv
5+
6+
//CHECK_HLSL: SampleCmpGrad
7+
//CHECK_HLSL: SampleCmpBias
8+
9+
//CHECK_SPIRV: OpImageSampleDrefExplicitLod {{.*}} Grad
10+
//CHECK_SPIRV: OpImageSampleDrefImplicitLod {{.*}} Bias
11+
12+
//CHECK_DXIL: dx.op.sampleCmpGrad.f32
13+
//CHECK_DXIL: dx.op.sampleCmpBias.f32
14+
15+
Texture2D<float> shadowMap;
16+
SamplerComparisonState shadowSampler;
17+
18+
struct PSInput
19+
{
20+
float4 position : SV_Position;
21+
float2 texCoord : TEXCOORD0;
22+
float depth : DEPTH;
23+
};
24+
25+
struct PSOutput
26+
{
27+
float4 color : SV_Target0;
28+
};
29+
30+
PSOutput fragmentMain(PSInput input)
31+
{
32+
PSOutput output;
33+
34+
float2 ddx = float2(0.001, 0.0);
35+
float2 ddy = float2(0.0, 0.001);
36+
float shadow1 = shadowMap.SampleCmpGrad(shadowSampler, input.texCoord, input.depth, ddx, ddy);
37+
38+
int2 offset = int2(1, 0);
39+
float shadow2 = shadowMap.SampleCmpGrad(shadowSampler, input.texCoord, input.depth, ddx, ddy, offset);
40+
41+
uint status;
42+
float shadow3 = shadowMap.SampleCmpGrad(shadowSampler, input.texCoord, input.depth, ddx, ddy, offset, status);
43+
44+
float bias = 0.5;
45+
float shadow4 = shadowMap.SampleCmpBias(shadowSampler, input.texCoord, input.depth, bias);
46+
47+
float shadow5 = shadowMap.SampleCmpBias(shadowSampler, input.texCoord, input.depth, bias, offset);
48+
49+
float shadow6 = shadowMap.SampleCmpBias(shadowSampler, input.texCoord, input.depth, bias, offset, status);
50+
51+
float finalShadow = (shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6) / 6.0;
52+
53+
output.color = float4(finalShadow, finalShadow, finalShadow, 1.0);
54+
return output;
55+
}
56+

0 commit comments

Comments
 (0)