diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index a671a3dc44..d2abfc7fee 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -1079,6 +1079,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [ForceInline] T Sample(vector<float, Shape.dimensions+isArray> location, vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { + __requireComputeDerivative(); __target_switch { case hlsl: @@ -1086,6 +1087,20 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); __intrinsic_asm ".Sample"; + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + + %sparseResult:%sparseResultType = OpImageSparseSampleImplicitLod $this $location ConstOffset|MinLod $offset $clamp; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; default: status = 0; return Sample(location, offset, clamp); @@ -1153,17 +1168,30 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleBias(vector<float, Shape.dimensions+isArray> location, float bias, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { __requireComputeDerivative(); __target_switch { - case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - return __getTexture().SampleBias(__getSampler(), location, bias, offset, clamp, status); + case hlsl: + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + return __getTexture().SampleBias(__getSampler(), location, bias, offset, clamp, status); + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + + %sparseResult:%sparseResultType = OpImageSparseSampleImplicitLod $this $location Bias|ConstOffset $bias $offset; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } @@ -1261,7 +1289,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] float SampleCmp(vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { __requireComputeDerivative(); @@ -1272,6 +1300,19 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); return __getTexture().SampleCmp(__getComparisonSampler(), location, compareValue, offset, clamp, status); + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint $$float; + + %sparseResult:%sparseResultType = OpImageSparseSampleDrefImplicitLod $this $location $compareValue ConstOffset|MinLod $offset $clamp; + + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + OpStore &status %residentCode; + result:$$float = OpCompositeExtract %sparseResult 1; + }; } } @@ -1296,7 +1337,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] float SampleCmpLevelZero(vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch @@ -1306,6 +1347,8 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); return __getTexture().SampleCmpLevelZero(__getComparisonSampler(), location, compareValue, offset, status); + case spirv: + return SampleCmpLevel(location, compareValue, 0.0, offset, status); } } @@ -1373,7 +1416,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, texture_shadowlod)] + [require(hlsl_spirv, texture_shadowlod)] float SampleCmpLevel(vector<float, Shape.dimensions+isArray> location, float compareValue, float level, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch @@ -1383,6 +1426,18 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); return __getTexture().SampleCmpLevel(__getComparisonSampler(), location, compareValue, level, offset, status); + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint $$float; + + %sparseResult:%sparseResultType = OpImageSparseSampleDrefExplicitLod $this $location $compareValue Lod|ConstOffset $level $offset; + + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + OpStore &status %residentCode; + result:$$float = OpCompositeExtract %sparseResult 1; + }; } } @@ -1472,16 +1527,30 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleGrad(vector<float, Shape.dimensions+isArray> location, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.dimensions> offset, float lodClamp, out uint status) { __target_switch { - case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY, offset, lodClamp, status); + case hlsl: + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + return __getTexture().SampleGrad(__getSampler(), location, gradX, gradY, offset, lodClamp, status); + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + + %sparseResult:%sparseResultType = OpImageSparseSampleExplicitLod $this $location Grad|ConstOffset|MinLod $gradX $gradY $offset $lodClamp; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } @@ -1574,16 +1643,29 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleLevel(vector<float, Shape.dimensions+isArray> location, float level, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch { - case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - return __getTexture().SampleLevel(__getSampler(), location, level, offset, status); + case hlsl: + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + return __getTexture().SampleLevel(__getSampler(), location, level, offset, status); + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + + %sparseResult:%sparseResultType = OpImageSparseSampleExplicitLod $this $location Lod|ConstOffset $level $offset; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } } @@ -1998,6 +2080,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [ForceInline] T Sample(SamplerState s, vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { + __requireComputeDerivative(); __target_switch { case hlsl: @@ -2005,6 +2088,21 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); __intrinsic_asm ".Sample"; + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleImplicitLod %sampledImage $location ConstOffset|MinLod $offset $clamp; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; default: status = 0; return Sample(s, location, offset, clamp); @@ -2142,17 +2240,32 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleBias(SamplerState s, vector<float, Shape.dimensions+isArray> location, float bias, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { __requireComputeDerivative(); __target_switch { - case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - __intrinsic_asm ".SampleBias"; + case hlsl: + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + __intrinsic_asm ".SampleBias"; + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleImplicitLod %sampledImage $location Bias|ConstOffset|MinLod $bias $offset $clamp; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } @@ -2293,7 +2406,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] float SampleCmp(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status) { __requireComputeDerivative(); @@ -2304,6 +2417,20 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); __intrinsic_asm ".SampleCmp"; + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint $$float; + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleDrefImplicitLod %sampledImage $location $compareValue ConstOffset|MinLod $offset $clamp; + + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + OpStore &status %residentCode; + result:$$float = OpCompositeExtract %sparseResult 1; + }; } } @@ -2342,7 +2469,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] float SampleCmpLevelZero(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch @@ -2352,6 +2479,8 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); __intrinsic_asm ".SampleCmpLevelZero"; + case spirv: + return SampleCmpLevel(s, location, compareValue, 0.0, offset, status); } } @@ -2421,7 +2550,7 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, texture_shadowlod)] + [require(hlsl_spirv, texture_shadowlod)] float SampleCmpLevel(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, float level, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch @@ -2431,6 +2560,19 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> , "HLSL supports only float and half type textures"); __intrinsic_asm ".SampleCmpLevel"; + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint $$float; + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleDrefExplicitLod %sampledImage $location $compareValue Lod|ConstOffset $level $offset; + + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + OpStore &status %residentCode; + result:$$float = OpCompositeExtract %sparseResult 1; + }; } } @@ -2616,16 +2758,31 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleGrad(SamplerState s, vector<float, Shape.dimensions+isArray> location, vector<float, Shape.dimensions> gradX, vector<float, Shape.dimensions> gradY, constexpr vector<int, Shape.dimensions> offset, float lodClamp, out uint status) { __target_switch { - case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - __intrinsic_asm ".SampleGrad"; + case hlsl: + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + __intrinsic_asm ".SampleGrad"; + case spirv: + return spirv_asm + { + OpCapability MinLod; + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleExplicitLod %sampledImage $location Grad|ConstOffset|MinLod $gradX $gradY $offset $lodClamp; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } @@ -2795,16 +2952,30 @@ extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format> [__readNone] [ForceInline] - [require(hlsl, sm_5_0)] + [require(hlsl_spirv, sm_5_0)] T SampleLevel(SamplerState s, vector<float, Shape.dimensions+isArray> location, float level, constexpr vector<int, Shape.planeDimensions> offset, out uint status) { __target_switch { case hlsl: - static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> - || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> - , "HLSL supports only float and half type textures"); - __intrinsic_asm ".SampleLevel"; + static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4> + || T is half || T is vector<half,2> || T is vector<half,3> || T is vector<half,4> + , "HLSL supports only float and half type textures"); + __intrinsic_asm ".SampleLevel"; + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + %sparseResultType = OpTypeStruct $$uint __sampledType(T); + %sampledImage:__sampledImageType(this) = OpSampledImage $this $s; + + %sparseResult:%sparseResultType = OpImageSparseSampleExplicitLod %sampledImage $location Lod|ConstOffset $level $offset; + %residentCode:$$uint = OpCompositeExtract %sparseResult 0; + %sampled:__sampledType(T) = OpCompositeExtract %sparseResult 1; + + OpStore &status %residentCode; + __truncate $$T result __sampledType(T) %sampled; + }; } } } @@ -7469,12 +7640,18 @@ T copysign(T x, T y) // Check access status to tiled resource [ForceInline] -[require(hlsl, sm_5_0)] -bool CheckAccessFullyMapped(out uint status) +[require(hlsl_spirv, sm_5_0)] +bool CheckAccessFullyMapped(uint status) { __target_switch { case hlsl: __intrinsic_asm "CheckAccessFullyMapped"; + case spirv: + return spirv_asm + { + OpCapability SparseResidency; + result:$$bool = OpImageSparseTexelsResident $status; + }; } } diff --git a/tests/expected-failure-github.txt b/tests/expected-failure-github.txt index 10897b31e7..c36e142f65 100644 --- a/tests/expected-failure-github.txt +++ b/tests/expected-failure-github.txt @@ -13,3 +13,4 @@ tests/compute/interface-shader-param.slang.5 syn (wgpu) tests/language-feature/shader-params/interface-shader-param-ordinary.slang.4 syn (wgpu) tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables.slang.8 (mtl) tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables-2.slang.3 (mtl) +tests/hlsl-intrinsic/texture/partial-resident-texture-combined.slang (dx12) diff --git a/tests/hlsl-intrinsic/texture/partial-resident-texture-combined.slang b/tests/hlsl-intrinsic/texture/partial-resident-texture-combined.slang new file mode 100644 index 0000000000..21b16eba8d --- /dev/null +++ b/tests/hlsl-intrinsic/texture/partial-resident-texture-combined.slang @@ -0,0 +1,205 @@ +// TODO: There are issues running tests combined texture samplers in DX12. +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHK):-slang -compute -shaderobj -output-using-type -use-dxil -profile cs_6_7 -dx12 + +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHK):-vk -compute -shaderobj -output-using-type -emit-spirv-directly -render-feature hardware-device -xslang -DVK + +//TEST_INPUT: ubuffer(data=[2], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +//TEST_INPUT:ubuffer(data=[1 1 1 1]):name=iBuf +RWByteAddressBuffer iBuf; + +// +// Combined texture samplers. +// + +//TEST_INPUT: TextureSampler1D(size=4, content = one):name st1D_f32v3 +Sampler1D<float3> st1D_f32v3; +//TEST_INPUT: TextureSampler2D(size=4, content = one):name st2D_f32v3 +Sampler2D<float3> st2D_f32v3; +//TEST_INPUT: TextureSampler3D(size=4, content = one):name st3D_f32v3 +Sampler3D<float3> st3D_f32v3; + +//TEST_INPUT: TextureSampler1D(size=4, content = one, arrayLength=2):name st1DArray_f32v3 +Sampler1DArray<float3> st1DArray_f32v3; +//TEST_INPUT: TextureSampler2D(size=4, content = one, arrayLength=2):name st2DArray_f32v3 +Sampler2DArray<float3> st2DArray_f32v3; + +//TEST_INPUT: TextureSampler1D(size=4, content = one):name st1D_f32v4 +Sampler1D<float4> st1D_f32v4; +//TEST_INPUT: TextureSampler2D(size=4, content = one):name st2D_f32v4 +Sampler2D<float4> st2D_f32v4; +//TEST_INPUT: TextureSampler3D(size=4, content = one):name st3D_f32v4 +Sampler3D<float4> st3D_f32v4; + +//TEST_INPUT: TextureSampler1D(size=4, content = one, arrayLength=2):name st1DArray_f32v4 +Sampler1DArray<float4> st1DArray_f32v4; +//TEST_INPUT: TextureSampler2D(size=4, content = one, arrayLength=2):name st2DArray_f32v4 +Sampler2DArray<float4> st2DArray_f32v4; + +// +// Combined depth texture samplers. +// + +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias CombinedDepth2d = _Texture< + T, + __Shape2D, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 1, // isCombined + format +>; + +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias CombinedDepth2d_array = _Texture< + T, + __Shape2D, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 1, // isCombined + format +>; + + +//TEST_INPUT: TextureSampler2D(size=4, content = zero):name cd2D +CombinedDepth2d<float> cd2D; +//TEST_INPUT: TextureSampler2D(size=4, content = zero, arrayLength=2):name cd2DArray +CombinedDepth2d_array<float> cd2DArray; + +uint getNotMapped() +{ + // We want to return a status uint that causes `CheckAccessFullyMapped` to return false. + // These are just educated guesses - actual implementation differ between platforms and drivers. +#if defined(VK) + return 0xFFFFFFFFU; +#else + return 0; +#endif +} + +bool TEST_combinedDepth() +{ + float u = 0.0; + int offset = 0; + float clamp = 0.0; + float slice = 0.0; + float level = 0.0; + float compareValue = 0.0; + + uint status; + + return true + // ================= + // float SampleCmp() + // ================= + && (status = getNotMapped(), all(0.0 == cd2D.SampleCmp(float2(u), compareValue, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == cd2DArray.SampleCmp(float3(u, u, slice), compareValue, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + + // ========================== + // float SampleCmpLevelZero() + // ========================== + && (status = getNotMapped(), all(0.0 == cd2D.SampleCmpLevelZero(float2(u), compareValue, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == cd2DArray.SampleCmpLevelZero(float3(u, u, slice), compareValue, int2(offset), status))) && CheckAccessFullyMapped(status) + + // ====================== + // float SampleCmpLevel() + // ====================== + && (status = getNotMapped(), all(0.0 == cd2D.SampleCmpLevel(float2(u), compareValue, level, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == cd2DArray.SampleCmpLevel(float3(u, u, slice), compareValue, level, int2(offset), status))) && CheckAccessFullyMapped(status) + ; +} + +bool TEST_sampler<T>( + Sampler1D<T> t1D, + Sampler2D<T> t2D, + Sampler3D<T> t3D, + Sampler1DArray<T> t1DArray, + Sampler2DArray<T> t2DArray, +) where T : ITexelElement, IArithmetic +{ + typealias TN = T; + + float u = 0.0; + int offset = 0; + float clamp = 0.0; + float slice = 0.0; + float bias = 0.0; + float grad = 0.0; + float level = 0.0; + constexpr const float ddx = 0.0f; + constexpr const float ddy = 0.0f; + + uint status; + + return true + // ========== + // T Sample() + // ========== + && (status = getNotMapped(), all(TN(T(1)) == t1D.Sample(u, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.Sample(float2(u), int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.Sample(float3(u), int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.Sample(float2(u, slice), offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.Sample(float3(u, u, slice), offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleBias() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleBias(u, bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleBias(float2(u), bias, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleBias(float3(u), bias, int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleBias(float2(u, slice), bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleBias(float3(u, u, slice), bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleGrad() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleGrad(u, ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleGrad(float2(u), ddx, ddy, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleGrad(float3(u), ddx, ddy, int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleGrad(float2(u, slice), ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleGrad(float3(u, u, slice), ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleLevel() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleLevel(u, level, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleLevel(float2(u), level, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleLevel(float3(u), level, int3(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleLevel(float2(u, slice), level, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleLevel(float3(u, u, slice), level, offset, status))) && CheckAccessFullyMapped(status) + ; +} + +[numthreads(4, 1, 1)] +void computeMain(int3 dispatchThreadID: SV_DispatchThreadID) +{ + bool result = true + // Make sure CheckAccessFullyMapped can return false + && (!CheckAccessFullyMapped(getNotMapped())) + && TEST_sampler( + st1D_f32v3, + st2D_f32v3, + st3D_f32v3, + st1DArray_f32v3, + st2DArray_f32v3, + ) + && TEST_sampler( + st1D_f32v4, + st2D_f32v4, + st3D_f32v4, + st1DArray_f32v4, + st2DArray_f32v4, + ) + && TEST_combinedDepth() + ; + + //CHK:1 + outputBuffer[0] = int(result); +} diff --git a/tests/hlsl-intrinsic/texture/partial-resident-texture.slang b/tests/hlsl-intrinsic/texture/partial-resident-texture.slang index ba7e318358..ee2c21225f 100644 --- a/tests/hlsl-intrinsic/texture/partial-resident-texture.slang +++ b/tests/hlsl-intrinsic/texture/partial-resident-texture.slang @@ -1,21 +1,224 @@ -//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHK):-slang -compute -shaderobj -output-using-type -use-dxil -profile cs_6_6 -dx12 +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHK):-slang -compute -shaderobj -output-using-type -use-dxil -profile cs_6_7 -dx12 +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHK):-vk -compute -shaderobj -output-using-type -emit-spirv-directly -render-feature hardware-device -xslang -DVK //TEST_INPUT: ubuffer(data=[2], stride=4):out,name outputBuffer RWStructuredBuffer<int> outputBuffer; -//TEST_INPUT: Texture2D(size=4, content = one):name t2D_f32 -Texture2D<float4> t2D_f32; - -//TEST_INPUT: Texture2D(size=4, content = one):name t2DMS_f32 -Texture2DMS<float4> t2DMS_f32; - //TEST_INPUT:ubuffer(data=[1 1 1 1]):name=iBuf RWByteAddressBuffer iBuf; //TEST_INPUT: Sampler:name samplerState SamplerState samplerState; +//TEST_INPUT: Sampler:name samplerCmpState +SamplerComparisonState samplerCmpState; + +// +// Textures. +// + +//TEST_INPUT: Texture1D(size=4, content = one):name t1D_f32v3 +Texture1D<float3> t1D_f32v3; +//TEST_INPUT: Texture2D(size=4, content = one):name t2D_f32v3 +Texture2D<float3> t2D_f32v3; +//TEST_INPUT: Texture3D(size=4, content = one):name t3D_f32v3 +Texture3D<float3> t3D_f32v3; +//TEST_INPUT: TextureCube(size=4, content = one):name tCube_f32v3 +TextureCube<float3> tCube_f32v3; +//TEST_INPUT: Texture1D(size=4, content = one, arrayLength=2):name t1DArray_f32v3 +Texture1DArray<float3> t1DArray_f32v3; +//TEST_INPUT: Texture2D(size=4, content = one, arrayLength=2):name t2DArray_f32v3 +Texture2DArray<float3> t2DArray_f32v3; +//TEST_INPUT: TextureCube(size=4, content = one, arrayLength=2):name tCubeArray_f32v3 +TextureCubeArray<float3> tCubeArray_f32v3; + +//TEST_INPUT: Texture1D(size=4, content = one):name t1D_f32v4 +Texture1D<float4> t1D_f32v4; +//TEST_INPUT: Texture2D(size=4, content = one):name t2D_f32v4 +Texture2D<float4> t2D_f32v4; +//TEST_INPUT: Texture3D(size=4, content = one):name t3D_f32v4 +Texture3D<float4> t3D_f32v4; +//TEST_INPUT: TextureCube(size=4, content = one):name tCube_f32v4 +TextureCube<float4> tCube_f32v4; + +//TEST_INPUT: Texture1D(size=4, content = one, arrayLength=2):name t1DArray_f32v4 +Texture1DArray<float4> t1DArray_f32v4; +//TEST_INPUT: Texture2D(size=4, content = one, arrayLength=2):name t2DArray_f32v4 +Texture2DArray<float4> t2DArray_f32v4; +//TEST_INPUT: TextureCube(size=4, content = one, arrayLength=2):name tCubeArray_f32v4 +TextureCubeArray<float4> tCubeArray_f32v4; + +//TEST_INPUT: Texture2D(size=4, content = one):name t2DMS_f32v4 +Texture2DMS<float4> t2DMS_f32v4; + +// +// Depth textures. +// +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias depth2d = _Texture< + T, + __Shape2D, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias depth2d_array = _Texture< + T, + __Shape2D, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias depthcube = _Texture< + T, + __ShapeCube, + 0, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +__generic<T : ITexelElement, let sampleCount:int=0, let format:int=0> +typealias depthcube_array = _Texture< + T, + __ShapeCube, + 1, // isArray + 0, // isMS + sampleCount, + 0, // access + 1, // isShadow + 0, // isCombined + format +>; + +//TEST_INPUT: Texture2D(size=4, content = zero):name d2D +depth2d<float> d2D; +//TEST_INPUT: Texture2D(size=4, content = zero, arrayLength=2):name d2DArray +depth2d_array<float> d2DArray; + +uint getNotMapped() +{ + // We want to return a status uint that causes `CheckAccessFullyMapped` to return false. + // These are just educated guesses - actual implementation differ between platforms and drivers. +#if defined(VK) + return 0xFFFFFFFFU; +#else + return 0; +#endif +} + +bool TEST_depthTexture() +{ + float u = 0.0; + int offset = 0; + float clamp = 0.0; + float slice = 0.0; + float level = 0.0; + float compareValue = 0.0; + + uint status; + + return true + // ================= + // float SampleCmp() + // ================= + && (status = getNotMapped(), all(0.0 == d2D.SampleCmp(samplerCmpState, float2(u), compareValue, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == d2DArray.SampleCmp(samplerCmpState, float3(u, u, slice), compareValue, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + + // ========================== + // float SampleCmpLevelZero() + // ========================== + && (status = getNotMapped(), all(0.0 == d2D.SampleCmpLevelZero(samplerCmpState, float2(u), compareValue, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == d2DArray.SampleCmpLevelZero(samplerCmpState, float3(u, u, slice), compareValue, int2(offset), status))) && CheckAccessFullyMapped(status) + + // ====================== + // float SampleCmpLevel() + // ====================== + && (status = getNotMapped(), all(0.0 == d2D.SampleCmpLevel(samplerCmpState, float2(u), compareValue, level, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(0.0 == d2DArray.SampleCmpLevel(samplerCmpState, float3(u, u, slice), compareValue, level, int2(offset), status))) && CheckAccessFullyMapped(status) + ; +} + bool TEST_texture<T>( + Texture1D<T> t1D, + Texture2D<T> t2D, + Texture3D<T> t3D, + TextureCube<T> tCube, + Texture1DArray<T> t1DArray, + Texture2DArray<T> t2DArray, + TextureCubeArray<T> tCubeArray, + ) + where T : ITexelElement, IArithmetic +{ + typealias TN = T; + + float u = 0.0; + int offset = 0; + float clamp = 0.0; + float slice = 0.0; + float bias = 0.0; + float grad = 0.0; + float level = 0.0; + constexpr const float ddx = 0.0f; + constexpr const float ddy = 0.0f; + + uint status; + + return true + // ========== + // T Sample() + // ========== + && (status = getNotMapped(), all(TN(T(1)) == t1D.Sample(samplerState, u, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.Sample(samplerState, float2(u), int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.Sample(samplerState, float3(u), int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.Sample(samplerState, float2(u, slice), offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.Sample(samplerState, float3(u, u, slice), offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleBias() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleBias(samplerState, u, bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleBias(samplerState, float2(u), bias, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleBias(samplerState, float3(u), bias, int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleBias(samplerState, float2(u, slice), bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleBias(samplerState, float3(u, u, slice), bias, offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleGrad() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleGrad(samplerState, u, ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleGrad(samplerState, float2(u), ddx, ddy, int2(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleGrad(samplerState, float3(u), ddx, ddy, int3(offset), clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleGrad(samplerState, float2(u, slice), ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleGrad(samplerState, float3(u, u, slice), ddx, ddy, offset, clamp, status))) && CheckAccessFullyMapped(status) + + // ============== + // T SampleLevel() + // ============== + && (status = getNotMapped(), all(TN(T(1)) == t1D.SampleLevel(samplerState, u, level, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.SampleLevel(samplerState, float2(u), level, int2(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t3D.SampleLevel(samplerState, float3(u), level, int3(offset), status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t1DArray.SampleLevel(samplerState, float2(u, slice), level, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2DArray.SampleLevel(samplerState, float3(u, u, slice), level, offset, status))) && CheckAccessFullyMapped(status) + ; +} + +bool TEST_load<T>( Texture2D<T> t2D, Texture2DMS<T> t2DMS) where T : ITexelElement, IArithmetic @@ -32,20 +235,16 @@ bool TEST_texture<T>( int3 iuvs = int3(iuv, sampleIndex); return true - // Make sure CheckAccessFullyMapped can return false - && (status = 0, !CheckAccessFullyMapped(status)) - - // Sample - && (status = 0, all(TN(T(1)) == t2D.Sample(samplerState, uv, offset, clamp, status))) && CheckAccessFullyMapped(status) - - // Load - && (status = 0, all(TN(T(1)) == t2DMS.Load(iuv, sampleIndex, offset, status))) && CheckAccessFullyMapped(status) - && (status = 0, all(TN(T(1)) == t2D.Load(iuvs, offset, status))) && CheckAccessFullyMapped(status) - && (status = 0, 2 == outputBuffer.Load(0, status)) && CheckAccessFullyMapped(status) - && (status = 0, 1 == iBuf.Load(0, status)) && CheckAccessFullyMapped(status) - && (status = 0, all(int2(1) == iBuf.Load2(0, status))) && CheckAccessFullyMapped(status) - && (status = 0, all(int3(1) == iBuf.Load3(0, status))) && CheckAccessFullyMapped(status) - && (status = 0, all(int4(1) == iBuf.Load4(0, status))) && CheckAccessFullyMapped(status) + // Currently not supported by Slang on VK. +#if !defined(VK) + && (status = getNotMapped(), all(TN(T(1)) == t2DMS.Load(iuv, sampleIndex, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(TN(T(1)) == t2D.Load(iuvs, offset, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), 2 == outputBuffer.Load(0, status)) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), 1 == iBuf.Load(0, status)) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(int2(1) == iBuf.Load2(0, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(int3(1) == iBuf.Load3(0, status))) && CheckAccessFullyMapped(status) + && (status = getNotMapped(), all(int4(1) == iBuf.Load4(0, status))) && CheckAccessFullyMapped(status) +#endif ; } @@ -53,7 +252,28 @@ bool TEST_texture<T>( void computeMain(int3 dispatchThreadID: SV_DispatchThreadID) { bool result = true - && TEST_texture(t2D_f32, t2DMS_f32) + // Make sure CheckAccessFullyMapped can return false + && (!CheckAccessFullyMapped(getNotMapped())) + && TEST_texture( + t1D_f32v3, + t2D_f32v3, + t3D_f32v3, + tCube_f32v3, + t1DArray_f32v3, + t2DArray_f32v3, + tCubeArray_f32v3, + ) + && TEST_texture( + t1D_f32v4, + t2D_f32v4, + t3D_f32v4, + tCube_f32v4, + t1DArray_f32v4, + t2DArray_f32v4, + tCubeArray_f32v4, + ) + && TEST_depthTexture() + && TEST_load(t2D_f32v4, t2DMS_f32v4) ; //CHK:1