Skip to content

Commit 3ecbeac

Browse files
authored
Fix depth texture sampling on Metal. (#6168)
1 parent a7958af commit 3ecbeac

8 files changed

+157
-92
lines changed

source/slang/hlsl.meta.slang

+98-76
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,10 @@ float __glsl_texture_level_offset_1d_shadow<TTexture, TCoord, TOffset>(TTexture
855855
}
856856
}
857857

858+
__intrinsic_op($(kIROp_MetalCastToDepthTexture))
859+
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
860+
_Texture<T,Shape,isArray,isMS,sampleCount,access,1,isCombined,format> __metal_asDepthTexture(_Texture<T,Shape,isArray,isMS,sampleCount,access,isShadow,isCombined,format> tex);
861+
858862
//@public:
859863

860864
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let isShadow:int, let format:int>
@@ -1676,6 +1680,96 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,access,isShadow,0,format>
16761680
}
16771681
}
16781682
}
1683+
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let format:int>
1684+
float __metal_SampleCmp(_Texture<T,Shape,isArray,isMS,sampleCount,0,1,0,format> t, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue)
1685+
{
1686+
if (isArray == 1)
1687+
{
1688+
switch (Shape.flavor)
1689+
{
1690+
case $(SLANG_TEXTURE_2D):
1691+
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3)";
1692+
case $(SLANG_TEXTURE_CUBE):
1693+
__intrinsic_asm "$0.sample_compare($1, ($2).xyz, uint(($2).w), $3)";
1694+
}
1695+
}
1696+
else
1697+
{
1698+
switch (Shape.flavor)
1699+
{
1700+
case $(SLANG_TEXTURE_2D):
1701+
case $(SLANG_TEXTURE_CUBE):
1702+
__intrinsic_asm ".sample_compare";
1703+
}
1704+
}
1705+
__intrinsic_asm "<invalid intrinsic>";
1706+
}
1707+
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let format:int>
1708+
float __metal_SampleCmp(_Texture<T,Shape,isArray,isMS,sampleCount,0,1,0,format> t, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset)
1709+
{
1710+
if (isArray == 1)
1711+
{
1712+
switch (Shape.flavor)
1713+
{
1714+
case $(SLANG_TEXTURE_2D):
1715+
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, $4)";
1716+
}
1717+
}
1718+
else
1719+
{
1720+
switch (Shape.flavor)
1721+
{
1722+
case $(SLANG_TEXTURE_2D):
1723+
__intrinsic_asm "$0.sample_compare($1, $2, $3, $4)";
1724+
}
1725+
}
1726+
__intrinsic_asm "<invalid intrinsic>";
1727+
}
1728+
1729+
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let format:int>
1730+
float __metal_SampleCmpLevel(_Texture<T,Shape,isArray,isMS,sampleCount,0,1,0,format> t, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float level)
1731+
{
1732+
if (isArray == 1)
1733+
{
1734+
switch (Shape.flavor)
1735+
{
1736+
case $(SLANG_TEXTURE_2D):
1737+
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, level($4))";
1738+
case $(SLANG_TEXTURE_CUBE):
1739+
__intrinsic_asm "$0.sample_compare($1, ($2).xyz, uint(($2).w), $3, level($4))";
1740+
}
1741+
}
1742+
else
1743+
{
1744+
switch (Shape.flavor)
1745+
{
1746+
case $(SLANG_TEXTURE_2D):
1747+
case $(SLANG_TEXTURE_CUBE):
1748+
__intrinsic_asm "$0.sample_compare($1, $2, $3, level($4))";
1749+
}
1750+
}
1751+
__intrinsic_asm "<invalid intrinsic>";
1752+
}
1753+
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let format:int>
1754+
float __metal_SampleCmpLevel(_Texture<T,Shape,isArray,isMS,sampleCount,0,1,0,format> t, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float level, constexpr vector<int, Shape.planeDimensions> offset)
1755+
{
1756+
switch (Shape.flavor)
1757+
{
1758+
case $(SLANG_TEXTURE_2D):
1759+
if (isArray == 1)
1760+
{
1761+
// T sample_compare(sampler s, float2 coord, uint array, float compare_value, lod_options options, int2 offset = int2(0)) const
1762+
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, level($4), $5)";
1763+
}
1764+
else
1765+
{
1766+
// T sample_compare(sampler s, float2 coord, float compare_value, lod_options options, int2 offset = int2(0)) const
1767+
__intrinsic_asm "$0.sample_compare($1, $2, $3, level($4), $5)";
1768+
}
1769+
break;
1770+
}
1771+
__intrinsic_asm "<invalid intrinsic>";
1772+
}
16791773

16801774
__generic<T:ITexelElement, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let isShadow:int, let format:int>
16811775
extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
@@ -2082,26 +2176,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
20822176
, "HLSL supports only float and half type textures");
20832177
__intrinsic_asm ".SampleCmp";
20842178
case metal:
2085-
if (isArray == 1)
2086-
{
2087-
switch (Shape.flavor)
2088-
{
2089-
case $(SLANG_TEXTURE_2D):
2090-
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3)";
2091-
case $(SLANG_TEXTURE_CUBE):
2092-
__intrinsic_asm "$0.sample_compare($1, ($2).xyz, uint(($2).w), $3)";
2093-
}
2094-
}
2095-
else
2096-
{
2097-
switch (Shape.flavor)
2098-
{
2099-
case $(SLANG_TEXTURE_2D):
2100-
case $(SLANG_TEXTURE_CUBE):
2101-
__intrinsic_asm ".sample_compare";
2102-
}
2103-
}
2104-
__intrinsic_asm "<invalid intrinsic>";
2179+
return __metal_SampleCmp(__metal_asDepthTexture(this), s, location, compareValue);
21052180
case spirv:
21062181
return spirv_asm
21072182
{
@@ -2183,23 +2258,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
21832258
, "HLSL supports only float and half type textures");
21842259
__intrinsic_asm ".SampleCmp";
21852260
case metal:
2186-
if (isArray == 1)
2187-
{
2188-
switch (Shape.flavor)
2189-
{
2190-
case $(SLANG_TEXTURE_2D):
2191-
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, $4)";
2192-
}
2193-
}
2194-
else
2195-
{
2196-
switch (Shape.flavor)
2197-
{
2198-
case $(SLANG_TEXTURE_2D):
2199-
__intrinsic_asm ".sample_compare";
2200-
}
2201-
}
2202-
__intrinsic_asm "<invalid intrinsic>";
2261+
return __metal_SampleCmp(__metal_asDepthTexture(this), s, location, compareValue, offset);
22032262
case spirv:
22042263
return spirv_asm
22052264
{
@@ -2311,26 +2370,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
23112370
, "HLSL supports only float and half type textures");
23122371
__intrinsic_asm ".SampleCmpLevel";
23132372
case metal:
2314-
if (isArray == 1)
2315-
{
2316-
switch (Shape.flavor)
2317-
{
2318-
case $(SLANG_TEXTURE_2D):
2319-
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, level($4))";
2320-
case $(SLANG_TEXTURE_CUBE):
2321-
__intrinsic_asm "$0.sample_compare($1, ($2).xyz, uint(($2).w), $3, level($4))";
2322-
}
2323-
}
2324-
else
2325-
{
2326-
switch (Shape.flavor)
2327-
{
2328-
case $(SLANG_TEXTURE_2D):
2329-
case $(SLANG_TEXTURE_CUBE):
2330-
__intrinsic_asm "$0.sample_compare($1, $2, $3, level($4))";
2331-
}
2332-
}
2333-
__intrinsic_asm "<invalid intrinsic>";
2373+
return __metal_SampleCmpLevel(__metal_asDepthTexture(this), s, location, compareValue, level);
23342374
case spirv:
23352375
return spirv_asm
23362376
{
@@ -2362,25 +2402,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
23622402
, "HLSL supports only float and half type textures");
23632403
__intrinsic_asm ".SampleCmpLevel";
23642404
case metal:
2365-
if (isShadow == 1)
2366-
{
2367-
switch (Shape.flavor)
2368-
{
2369-
case $(SLANG_TEXTURE_2D):
2370-
if (isArray == 1)
2371-
{
2372-
// T sample_compare(sampler s, float2 coord, uint array, float compare_value, lod_options options, int2 offset = int2(0)) const
2373-
__intrinsic_asm "$0.sample_compare($1, ($2).xy, uint(($2).z), $3, level($4), $5)";
2374-
}
2375-
else
2376-
{
2377-
// T sample_compare(sampler s, float2 coord, float compare_value, lod_options options, int2 offset = int2(0)) const
2378-
__intrinsic_asm "$0.sample_compare($1, $2, $3, level($4), $5)";
2379-
}
2380-
break;
2381-
}
2382-
}
2383-
__intrinsic_asm "<invalid intrinsic>";
2405+
return __metal_SampleCmpLevel(__metal_asDepthTexture(this), s, location, compareValue, level, offset);
23842406
case spirv:
23852407
return spirv_asm
23862408
{

source/slang/slang-emit-c-like.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
14131413
// or statement).
14141414
case kIROp_UpdateElement:
14151415
case kIROp_DefaultConstruct:
1416+
case kIROp_MetalCastToDepthTexture:
14161417
return false;
14171418

14181419
// Always fold these in, because they are trivial
@@ -3129,6 +3130,7 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
31293130
case kIROp_AtomicCompareExchange:
31303131
case kIROp_StructuredBufferGetDimensions:
31313132
case kIROp_MetalAtomicCast:
3133+
case kIROp_MetalCastToDepthTexture:
31323134
emitInstStmt(inst);
31333135
break;
31343136

source/slang/slang-emit-metal.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,22 @@ bool MetalSourceEmitter::tryEmitInstStmtImpl(IRInst* inst)
636636
m_writer->emit(");\n");
637637
return true;
638638
}
639+
case kIROp_MetalCastToDepthTexture:
640+
{
641+
emitType(inst->getDataType(), getName(inst));
642+
m_writer->emit(";\n{\n");
643+
m_writer->indent();
644+
m_writer->emit("auto _slang_ordinary_texture = ");
645+
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
646+
m_writer->emit(";\n");
647+
m_writer->emit(getName(inst));
648+
m_writer->emit(" = *(");
649+
emitType(inst->getDataType());
650+
m_writer->emit(" thread*)(&_slang_ordinary_texture);\n");
651+
m_writer->dedent();
652+
m_writer->emit("}\n");
653+
return true;
654+
}
639655
}
640656
return false;
641657
}

source/slang/slang-ir-inst-defs.h

+2
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@ INST(MetalSetVertex, metalSetVertex, 2, 0)
555555
INST(MetalSetPrimitive, metalSetPrimitive, 2, 0)
556556
INST(MetalSetIndices, metalSetIndices, 2, 0)
557557

558+
INST(MetalCastToDepthTexture, MetalCastToDepthTexture, 1, 0)
559+
558560
// Construct a vector from a scalar
559561
//
560562
// %dst = MakeVectorFromScalar %T %N %val

source/slang/slang-ir-metal-legalize.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,17 @@ static void processInst(IRInst* inst)
206206
case kIROp_Leq:
207207
legalizeBinaryOp(inst);
208208
break;
209-
209+
case kIROp_MetalCastToDepthTexture:
210+
{
211+
// If the operand is already a depth texture, don't do anything.
212+
auto textureType = as<IRTextureTypeBase>(inst->getOperand(0)->getDataType());
213+
if (textureType && getIntVal(textureType->getIsShadowInst()) == 1)
214+
{
215+
inst->replaceUsesWith(inst->getOperand(0));
216+
inst->removeAndDeallocate();
217+
}
218+
break;
219+
}
210220
default:
211221
for (auto child : inst->getModifiableChildren())
212222
{

source/slang/slang-ir.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -8248,6 +8248,7 @@ bool IRInst::mightHaveSideEffects(SideEffectAnalysisOptions options)
82488248
case kIROp_GetArrayLength:
82498249
case kIROp_ResolveVaryingInputRef:
82508250
case kIROp_GetPerVertexInputArray:
8251+
case kIROp_MetalCastToDepthTexture:
82518252
return false;
82528253

82538254
case kIROp_ForwardDifferentiate:

tests/metal/depth-texture.slang

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//TEST:SIMPLE(filecheck=CHECK): -target metallib
2+
//CHECK: sample_compare_depth_2d
3+
Texture2D texture;
4+
SamplerComparisonState sampler;
5+
6+
RWStructuredBuffer<float> output;
7+
8+
[numthreads(1,1,1)]
9+
void computeMain()
10+
{
11+
output[0] = texture.SampleCmpLevelZero(sampler, float2(0, 0), 0);
12+
}

tests/metal/texture.slang

+15-15
Original file line numberDiff line numberDiff line change
@@ -566,51 +566,51 @@ bool TEST_texture<T>(
566566
// float SampleCmp()
567567
// ==================
568568

569-
// METAL: d2D{{.*}}.sample_compare(
569+
// METAL: {{.*}}.sample_compare(
570570
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
571571
&& float(0) == d2D.SampleCmp(shadowSampler, float2(u, u), 0)
572572

573-
// METAL: d2DArray{{.*}}.sample_compare(
573+
// METAL: {{.*}}.sample_compare(
574574
// METALLIB: call {{.*}}.sample_compare_depth_2d_array.f32(
575575
&& float(0) == d2DArray.SampleCmp(shadowSampler, float3(u, u, 0), 0)
576576

577-
// METAL: dCube{{.*}}.sample_compare(
577+
// METAL: {{.*}}.sample_compare(
578578
// METALLIB: call {{.*}}.sample_compare_depth_cube.f32(
579579
&& float(0) == dCube.SampleCmp(shadowSampler, normalize(float3(u, 1 - u, u)), 0)
580580

581-
// METAL: dCubeArray{{.*}}.sample_compare(
581+
// METAL: {{.*}}.sample_compare(
582582
// METALLIB: call {{.*}}.sample_compare_depth_cube_array.f32(
583583
&& float(0) == dCubeArray.SampleCmp(shadowSampler, float4(normalize(float3(u, 1 - u, u)), 0), 0)
584584

585585
// Offset variant
586586

587-
// METAL: d2D{{.*}}.sample_compare(
587+
// METAL: {{.*}}.sample_compare(
588588
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
589589
&& float(0) == d2D.SampleCmp(shadowSampler, float2(u2, u), 0, int2(0, 0))
590590

591591
// ===================================
592592
// float SampleCmpLevelZero()
593593
// ===================================
594594

595-
// METAL: d2D{{.*}}.sample_compare(
595+
// METAL: {{.*}}.sample_compare(
596596
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
597597
&& float(0) == d2D.SampleCmpLevelZero(shadowSampler, float2(u, u), 0)
598598

599-
// METAL: d2DArray{{.*}}.sample_compare(
599+
// METAL: {{.*}}.sample_compare(
600600
// METALLIB: call {{.*}}.sample_compare_depth_2d_array.f32(
601601
&& float(0) == d2DArray.SampleCmpLevelZero(shadowSampler, float3(u, u, 0), 0)
602602

603-
// METAL: dCube{{.*}}.sample_compare(
603+
// METAL: {{.*}}.sample_compare(
604604
// METALLIB: call {{.*}}.sample_compare_depth_cube.f32(
605605
&& float(0) == dCube.SampleCmpLevelZero(shadowSampler, normalize(float3(u, 1 - u, u)), 0)
606606

607-
// METAL: dCubeArray{{.*}}.sample_compare(
607+
// METAL: {{.*}}.sample_compare(
608608
// METALLIB: call {{.*}}.sample_compare_depth_cube_array.f32(
609609
&& float(0) == dCubeArray.SampleCmpLevelZero(shadowSampler, float4(normalize(float3(u, 1-u, u)), 0), 0)
610610

611611
// Offset variant
612612

613-
// METAL: d2D{{.*}}.sample_compare(
613+
// METAL: {{.*}}.sample_compare(
614614
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
615615
&& float(0) == d2D.SampleCmpLevelZero(shadowSampler, float2(u2, u), 0, int2(0, 0))
616616

@@ -620,25 +620,25 @@ bool TEST_texture<T>(
620620

621621
// These require SM 6.7 for dx12 but functional compute tests currently do not run with the cs_6_7.
622622
#if !defined(EXCLUDE_SM_6_7)
623-
// METAL: d2D{{.*}}.sample_compare(
623+
// METAL: {{.*}}.sample_compare(
624624
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
625625
&& float(0) == d2D.SampleCmpLevel(shadowSampler, float2(u, u), 0, 0.0)
626626

627-
// METAL: d2DArray{{.*}}.sample_compare(
627+
// METAL: {{.*}}.sample_compare(
628628
// METALLIB: call {{.*}}.sample_compare_depth_2d_array.f32(
629629
&& float(0) == d2DArray.SampleCmpLevel(shadowSampler, float3(u, u, 0), 0, 0.0)
630630

631-
// METAL: dCube{{.*}}.sample_compare(
631+
// METAL: {{.*}}.sample_compare(
632632
// METALLIB: call {{.*}}.sample_compare_depth_cube.f32(
633633
&& float(0) == dCube.SampleCmpLevel(shadowSampler, normalize(float3(u, 1 - u, u)), 0, 0.0)
634634

635-
// METAL: dCubeArray{{.*}}.sample_compare(
635+
// METAL: {{.*}}.sample_compare(
636636
// METALLIB: call {{.*}}.sample_compare_depth_cube_array.f32(
637637
&& float(0) == dCubeArray.SampleCmpLevel(shadowSampler, float4(normalize(float3(u, 1-u, u)), 0), 0, 0.0)
638638

639639
// Offset variant
640640

641-
// METAL: d2D{{.*}}.sample_compare(
641+
// METAL: {{.*}}.sample_compare(
642642
// METALLIB: call {{.*}}.sample_compare_depth_2d.f32(
643643
&& float(0) == d2D.SampleCmpLevel(shadowSampler, float2(u2, u), 0, 0.0, int2(0, 0))
644644
#endif

0 commit comments

Comments
 (0)