summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-11-16 14:32:33 -0800
committerGitHub <noreply@github.com>2023-11-16 14:32:33 -0800
commit4c78efd0c34442866f20e9d00bbb6908115c9a01 (patch)
tree03ca8584847f0937a926f6b27386dcd982ed7780 /source
parent12f7237e4060388494c549623f4a640327b7ca08 (diff)
Unify stdlib `Texture` types into one generic type. (#3327)
* Unify Texture types in stdlib into 1 generic type. * Fixes. * Fix. * Fixes. * Fix reflection. * Fix binding reflection. * Add gather intrinsics. * Fix gather intrinsics. * Fix texture type toText. * Fix intrinsic. * fix cuda intrinsic. * Fix project files. * cleanup. * Fix. * Fix. * Fix sampler feedback test. * Fix getDimension intrinsics. * Fix spirv sample image intrinsics. * Fix test. * Fix GLSL intrinsic. * Cleanup. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang19
-rw-r--r--source/slang/glsl.meta.slang82
-rw-r--r--source/slang/hlsl.meta.slang1594
-rw-r--r--source/slang/slang-ast-dump.cpp7
-rw-r--r--source/slang/slang-ast-expr.h2
-rw-r--r--source/slang/slang-ast-type.cpp192
-rw-r--r--source/slang/slang-ast-type.h55
-rw-r--r--source/slang/slang-ast-val.cpp18
-rw-r--r--source/slang/slang-check-expr.cpp13
-rw-r--r--source/slang/slang-emit-c-like.cpp5
-rw-r--r--source/slang/slang-emit-cpp.cpp23
-rw-r--r--source/slang/slang-emit-cuda.cpp6
-rw-r--r--source/slang/slang-emit-glsl.cpp20
-rw-r--r--source/slang/slang-emit-hlsl.cpp33
-rw-r--r--source/slang/slang-emit-spirv.cpp57
-rw-r--r--source/slang/slang-emit.cpp13
-rw-r--r--source/slang/slang-intrinsic-expand.cpp106
-rw-r--r--source/slang/slang-ir-inst-defs.h21
-rw-r--r--source/slang/slang-ir-insts.h13
-rw-r--r--source/slang/slang-ir-lower-generic-call.cpp15
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp3
-rw-r--r--source/slang/slang-ir-simplify-cfg.cpp5
-rw-r--r--source/slang/slang-ir-spirv-legalize.cpp22
-rw-r--r--source/slang/slang-ir.cpp61
-rw-r--r--source/slang/slang-ir.h75
-rw-r--r--source/slang/slang-lookup.cpp1
-rw-r--r--source/slang/slang-lower-to-ir.cpp26
-rw-r--r--source/slang/slang-parameter-binding.cpp5
-rw-r--r--source/slang/slang-parser.cpp15
-rw-r--r--source/slang/slang-reflection-api.cpp9
-rw-r--r--source/slang/slang-serialize-ir.cpp31
-rw-r--r--source/slang/slang-serialize-misc-type-info.h13
-rw-r--r--source/slang/slang-stdlib-textures.cpp1192
-rw-r--r--source/slang/slang-stdlib-textures.h43
-rw-r--r--source/slang/slang-stdlib.cpp2
-rw-r--r--source/slang/slang-syntax.cpp6
-rw-r--r--source/slang/slang-type-layout.cpp51
-rw-r--r--source/slang/slang-type-system-shared.cpp14
-rw-r--r--source/slang/slang-type-system-shared.h87
-rw-r--r--source/slang/slang.natvis40
40 files changed, 2352 insertions, 1643 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index b1437670e..3a19d345a 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1476,25 +1476,6 @@ struct SamplerComparisonState
{
}
-${{{{
-
-for(auto& prefixInfo : kTexturePrefixes)
-for(auto& shapeInfo : kBaseTextureShapes)
-for(int isArray = 0; isArray < 2; ++isArray)
-for(int isMultisample = 0; isMultisample < 2; ++isMultisample)
-for(int isShadow = 0; isShadow < 2; ++isShadow)
-for(auto& accessInfo : kBaseTextureAccessLevels)
-{
- // Define `Shadow` flavored types only for combined texture-samplers.
- if (!prefixInfo.combined && isShadow == 1)
- continue;
-
- TextureTypeInfo info(prefixInfo, shapeInfo, isArray, isMultisample, isShadow, accessInfo, sb, path);
- info.emitTypeDecl();
-}
-
-}}}}
-
//@ hidden:
${{{{
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
index a9518f914..98f30cd3c 100644
--- a/source/slang/glsl.meta.slang
+++ b/source/slang/glsl.meta.slang
@@ -94,17 +94,20 @@ typealias usamplerCube = SamplerCube<uint4>;
typealias isamplerCube = SamplerCube<int4>;
typealias samplerCube = SamplerCube<float4>;
-typealias usampler1DShadow = Sampler1DShadow<uint4>;
-typealias isampler1DShadow = Sampler1DShadow<int4>;
-typealias sampler1DShadow = Sampler1DShadow<float4>;
+typealias Sampler1DShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usampler1DShadow = Sampler1DShadow<uint>;
+typealias isampler1DShadow = Sampler1DShadow<int>;
+typealias sampler1DShadow = Sampler1DShadow<float>;
-typealias usampler2DShadow = Sampler2DShadow<uint4>;
-typealias isampler2DShadow = Sampler2DShadow<int4>;
-typealias sampler2DShadow = Sampler2DShadow<float4>;
+typealias Sampler2DShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usampler2DShadow = Sampler2DShadow<uint>;
+typealias isampler2DShadow = Sampler2DShadow<int>;
+typealias sampler2DShadow = Sampler2DShadow<float>;
-typealias usamplerCubeShadow = SamplerCubeShadow<uint4>;
-typealias isamplerCubeShadow = SamplerCubeShadow<int4>;
-typealias samplerCubeShadow = SamplerCubeShadow<float4>;
+typealias SamplerCubeShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usamplerCubeShadow = SamplerCubeShadow<uint>;
+typealias isamplerCubeShadow = SamplerCubeShadow<int>;
+typealias samplerCubeShadow = SamplerCubeShadow<float>;
typealias usampler1DArray = Sampler1DArray<uint4>;
typealias isampler1DArray = Sampler1DArray<int4>;
@@ -118,20 +121,20 @@ typealias usamplerCubeArray = SamplerCubeArray<uint4>;
typealias isamplerCubeArray = SamplerCubeArray<int4>;
typealias samplerCubeArray = SamplerCubeArray<float4>;
-typealias usampler1DArrayShadow = Sampler1DArrayShadow<uint4>;
-typealias isampler1DArrayShadow = Sampler1DArrayShadow<int4>;
-typealias sampler1DArrayShadow = Sampler1DArrayShadow<float4>;
+typealias Sampler1DArrayShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usampler1DArrayShadow = Sampler1DArrayShadow<uint>;
+typealias isampler1DArrayShadow = Sampler1DArrayShadow<int>;
+typealias sampler1DArrayShadow = Sampler1DArrayShadow<float>;
-typealias usampler2DArrayShadow = Sampler2DArrayShadow<uint4>;
-typealias isampler2DArrayShadow = Sampler2DArrayShadow<int4>;
-typealias sampler2DArrayShadow = Sampler2DArrayShadow<float4>;
+typealias Sampler2DArrayShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usampler2DArrayShadow = Sampler2DArrayShadow<uint>;
+typealias isampler2DArrayShadow = Sampler2DArrayShadow<int>;
+typealias sampler2DArrayShadow = Sampler2DArrayShadow<float>;
-typealias usamplerCubeArrayShadow = SamplerCubeArrayShadow<uint4>;
-typealias isamplerCubeArrayShadow = SamplerCubeArrayShadow<int4>;
-typealias samplerCubeArrayShadow = SamplerCubeArrayShadow<float4>;
-
-__intrinsic_op(vectorReshape)
-vector<T,N> __vectorReshape<let N : int, T, let M : int>(vector<T,M> vin);
+typealias SamplerCubeArrayShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+typealias usamplerCubeArrayShadow = SamplerCubeArrayShadow<uint>;
+typealias isamplerCubeArrayShadow = SamplerCubeArrayShadow<int>;
+typealias samplerCubeArrayShadow = SamplerCubeArrayShadow<float>;
[ForceInline]
vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, int p, int lod)
@@ -235,45 +238,12 @@ float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArrayShadow<vect
return sampler.SampleCmp(p.xyz, p.w);
}
-// TODO: define `texture` for SamplerCubeArrayShadow.
-
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, float P, float dPdx, float dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, vec2 P, vec2 dPdx, vec2 dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, vec3 P, vec3 dPdx, vec3 dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (SamplerCube<vector<T,N>> sampler, vec3 P, vec3 dPdx, vec3 dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, vec2 P, float dPdx, float dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, vec3 P, vec2 dPdx, vec2 dPdy)
+__generic<T:__BuiltinArithmeticType, let N : int, shape:__ITextureShape, let sampleCount: int, let isArray:int, let format:int>
+vector<T,4> textureGrad(__TextureImpl<vector<T,N>, shape, isArray, 0, sampleCount, 0, 1, 1, format> sampler, vector<float, shape.dimensions+isArray> P, vector<float,shape.planeDimensions> dPdx, vector<float,shape.planeDimensions> dPdy)
{
return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
}
-vector<T,4> textureGrad<T:__BuiltinArithmeticType, let N : int> (SamplerCubeArray<vector<T,N>> sampler, vec4 P, vec3 dPdx, vec3 dPdy)
-{
- return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
-}
-
-
out float4 gl_Position : SV_Position;
out float gl_PointSize : SV_PointSize;
in vec4 gl_FragCoord : SV_Position;
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 6520ab1fa..501723931 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -112,6 +112,1528 @@ struct ByteAddressBuffer
}
};
+// Texture
+[sealed]
+[builtin]
+interface __ITextureShape
+{
+ static const int flavor;
+ static const int dimensions;
+ static const int planeDimensions;
+}
+__magic_type(TextureShape1DType)
+__intrinsic_type($(kIROp_TextureShape1DType))
+struct __Shape1D : __ITextureShape
+{
+ static const int flavor = $(SLANG_TEXTURE_1D);
+ static const int dimensions = 1;
+ static const int planeDimensions = 1;
+}
+__magic_type(TextureShape2DType)
+__intrinsic_type($(kIROp_TextureShape2DType))
+struct __Shape2D : __ITextureShape
+{
+ static const int flavor = $(SLANG_TEXTURE_2D);
+ static const int dimensions = 2;
+ static const int planeDimensions = 2;
+}
+__magic_type(TextureShape3DType)
+__intrinsic_type($(kIROp_TextureShape3DType))
+struct __Shape3D : __ITextureShape
+{
+ static const int flavor = $(SLANG_TEXTURE_3D);
+ static const int dimensions = 3;
+ static const int planeDimensions = 3;
+}
+__magic_type(TextureShapeCubeType)
+__intrinsic_type($(kIROp_TextureShapeCubeType))
+struct __ShapeCube : __ITextureShape
+{
+ static const int flavor = $(SLANG_TEXTURE_CUBE);
+ static const int dimensions = 3;
+ static const int planeDimensions = 2;
+}
+__magic_type(TextureShapeBufferType)
+__intrinsic_type($(kIROp_TextureShapeBufferType))
+struct __ShapeBuffer : __ITextureShape
+{
+ static const int flavor = $(SLANG_TEXTURE_BUFFER);
+ static const int dimensions = 1;
+ static const int planeDimensions = 1;
+}
+__intrinsic_op(vectorReshape)
+vector<T,N> __vectorReshape<let N : int, T, let M : int>(vector<T,M> vin);
+
+__intrinsic_op(makeVector)
+__generic<T, let N:int>
+vector<T,N+1> __makeVector(vector<T,N> vec, T scalar);
+
+
+__magic_type(TextureType)
+__intrinsic_type($(kIROp_TextureType))
+struct __TextureImpl<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
+{
+}
+
+// Combined texture sampler specific functions
+__generic<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let isShadow:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
+{
+ static const int access = 0;
+
+ typealias TextureCoord = vector<float, Shape.dimensions>;
+
+ __target_intrinsic(glsl, "textureQueryLod($0, $1).x")
+ float CalculateLevelOfDetail(TextureCoord location);
+
+ __target_intrinsic(glsl, "textureQueryLod($0, $1).y")
+ float CalculateLevelOfDetailUnclamped(TextureCoord location);
+
+ [__readNone]
+ T Sample(vector<float, Shape.dimensions+isArray> location)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Sample";
+ case glsl:
+ __intrinsic_asm "$ctexture($0, $1)$z";
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLayered<$T0>($0, ($1).x, int(($1).y))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLayered<$T0>($0, ($1).x, ($1).y, int(($1).z))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLayered<$T0>($0, ($1).x, ($1).y, ($1).z, int(($1).w))";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1D<$T0>($0, ($1))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2D<$T0>($0, ($1).x, ($1).y)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "tex3D<$T0>($0, ($1).x, ($1).y, ($1).z)";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemap<$T0>($0, ($1).x, ($1).y, ($1).z)";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ __glsl_extension(GL_ARB_sparse_texture_clamp)
+ T Sample(vector<float, Shape.dimensions+isArray> location, vector<int, Shape.planeDimensions> offset, float clamp)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Sample";
+ case glsl:
+ __intrinsic_asm "$ctextureOffsetClampARB($0, $1, $2, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ OpCapability MinLod;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None|ConstOffset|MinLod $offset $clamp;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ __target_intrinsic(hlsl)
+ T Sample(vector<float, Shape.dimensions+isArray> location, vector<int, Shape.planeDimensions> offset, float clamp, out uint status)
+ {
+ status = 0;
+ return Sample(location, offset, clamp);
+ }
+
+ [__readNone]
+ T SampleBias(vector<float, Shape.dimensions+isArray> location, float bias)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleBias";
+ case glsl:
+ __intrinsic_asm "$ctexture($0, $1, $2)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None|Bias $bias;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleBias(vector<float, Shape.dimensions+isArray> location, float bias, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleBias";
+ case glsl:
+ __intrinsic_asm "$ctextureOffset($0, $1, $3, $2)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod $this $location None|Bias|ConstOffset $bias $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ __target_intrinsic(glsl, "texture($0, $1)")
+ float __glsl_texture(vector<float, Shape.dimensions+isArray+1> value);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureOffset($0, $1, $2)")
+ float __glsl_texture_offset(vector<float, Shape.dimensions+isArray+1> value, constexpr vector<int, Shape.planeDimensions> offset);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureLod($0, $1, 0)")
+ float __glsl_texture_level_zero(vector<float, Shape.dimensions+isArray+1> value);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureLodOffset($0, $1, 0, $2)")
+ float __glsl_texture_offset_level_zero(vector<float, Shape.dimensions+isArray+1> value, constexpr vector<int, Shape.planeDimensions> offset);
+
+ [__readNone]
+ [ForceInline]
+ float SampleCmp(vector<float, Shape.dimensions+isArray> location, float compareValue)
+ {
+ __target_switch
+ {
+ case glsl:
+ __glsl_texture(__makeVector(location, compareValue));
+ case hlsl:
+ __intrinsic_asm ".SampleCmp";
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ float SampleCmpLevelZero(vector<float, Shape.dimensions+isArray> location, float compareValue)
+ {
+ __target_switch
+ {
+ case glsl:
+ __glsl_texture_level_zero(__makeVector(location, compareValue));
+ case hlsl:
+ __intrinsic_asm ".SampleCmpLevelZero";
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ float SampleCmp(vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case glsl:
+ __glsl_texture_offset(__makeVector(location, compareValue), offset);
+ case hlsl:
+ __intrinsic_asm ".SampleCmp";
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ float SampleCmpLevelZero(vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case glsl:
+ __glsl_texture_offset_level_zero(__makeVector(location, compareValue), offset);
+ case hlsl:
+ __intrinsic_asm ".SampleCmpLevelZero";
+ }
+ }
+
+ [__readNone]
+ T SampleGrad(vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGrad($0, $1, $2, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Grad $gradX $gradY;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleGrad(vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGradOffset($0, $1, $2, $3, $4)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Grad|ConstOffset $gradX $gradY $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ __glsl_extension(GL_ARB_sparse_texture_clamp)
+ [__readNone]
+ T SampleGrad(vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset, float lodClamp)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGradOffsetClampARB($0, $1, $2, $3, $4, $5)$z";
+ case spirv:
+ return spirv_asm
+ {
+ OpCapability MinLod;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Grad|ConstOffset|MinLod $gradX $gradY $offset $lodClamp;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleLevel(vector<float, Shape.dimensions+isArray> location, float level)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleLevel";
+ case glsl:
+ __intrinsic_asm "$ctextureLod($0, $1, $2)$z";
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLayeredLod<$T0>($0, ($1).x, int(($1).y), ($2))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLayeredLod<$T0>($0, ($1).x, ($1).y, int(($1).z), ($2))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLayeredLod<$T0>($0, ($1).x, ($1).y, ($1).z, int(($1).w), ($2))";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLod<$T0>($0, ($1), ($2))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLod<$T0>($0, ($1).x, ($1).y, ($2))";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "tex3DLod<$T0>($0, ($1).x, ($1).y, ($1).z, ($2))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLod<$T0>($0, ($1).x, ($1).y, ($1).z, ($2))";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Lod $level;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleLevel(vector<float, Shape.dimensions+isArray> location, float level, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleLevel";
+ case glsl:
+ __intrinsic_asm "$ctextureLodOffset($0, $1, $2, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod $this $location None|Lod|ConstOffset $level $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+}
+
+// Non-combined texture types specific functions
+__generic<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,access,isShadow,0,format>
+{
+ typealias TextureCoord = vector<float, Shape.dimensions>;
+
+ __target_intrinsic(glsl, "textureQueryLod($p, $2).x")
+ float CalculateLevelOfDetail(SamplerState s, TextureCoord location);
+
+ __target_intrinsic(glsl, "textureQueryLod($p, $2).y")
+ float CalculateLevelOfDetailUnclamped(SamplerState s, TextureCoord location);
+
+ [__readNone]
+ T Sample(SamplerState s, vector<float, Shape.dimensions+isArray> location)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Sample";
+ case glsl:
+ __intrinsic_asm "$ctexture($p, $2)$z";
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLayered<$T0>($0, ($2).x, int(($2).y))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLayered<$T0>($0, ($2).x, ($2).y, int(($2).z))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLayered<$T0>($0, ($2).x, ($2).y, ($2).z, int(($2).w))";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1D<$T0>($0, ($2))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2D<$T0>($0, ($2).x, ($2).y)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "tex3D<$T0>($0, ($2).x, ($2).y, ($2).z)";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemap<$T0>($0, ($2).x, ($2).y, ($2).z)";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ T Sample(SamplerState s, vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Sample";
+ case glsl:
+ __intrinsic_asm "$ctextureOffset($p, $2, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|ConstOffset $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ __glsl_extension(GL_ARB_sparse_texture_clamp)
+ T Sample(SamplerState s, vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset, float clamp)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Sample";
+ case glsl:
+ __intrinsic_asm "$ctextureOffsetClampARB($p, $2, $3, $4)$z";
+ case spirv:
+ return spirv_asm
+ {
+ OpCapability MinLod;
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|ConstOffset|MinLod $offset $clamp;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ __target_intrinsic(hlsl)
+ T Sample(SamplerState s, vector<float, Shape.dimensions+isArray> location, constexpr vector<int, Shape.planeDimensions> offset, float clamp, out uint status)
+ {
+ status = 0;
+ return Sample(s, location, offset, clamp);
+ }
+
+ [__readNone]
+ T SampleBias(SamplerState s, vector<float, Shape.dimensions+isArray> location, float bias)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleBias";
+ case glsl:
+ __intrinsic_asm "$ctexture($p, $2, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias $bias;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleBias(SamplerState s, vector<float, Shape.dimensions+isArray> location, float bias, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleBias";
+ case glsl:
+ __intrinsic_asm "$ctextureOffset($p, $2, $4, $3)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleImplicitLod %sampledImage $location None|Bias|ConstOffset $bias $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ __target_intrinsic(glsl, "texture($p, $2)")
+ float __glsl_texture(SamplerComparisonState s, vector<float, Shape.dimensions+isArray+1> value);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureOffset($p, $2, $3)")
+ float __glsl_texture_offset(SamplerComparisonState s, vector<float, Shape.dimensions+isArray+1> value, constexpr vector<int, Shape.planeDimensions> offset);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureLod($p, $2, 0)")
+ float __glsl_texture_level_zero(SamplerComparisonState s, vector<float, Shape.dimensions+isArray+1> value);
+
+ __glsl_extension(GL_EXT_texture_shadow_lod)
+ __target_intrinsic(glsl, "textureLodOffset($p, $2, 0, $3)")
+ float __glsl_texture_offset_level_zero(SamplerComparisonState s, vector<float, Shape.dimensions+isArray+1> value, constexpr vector<int, Shape.planeDimensions> offset);
+
+ [__readNone] [ForceInline]
+ float SampleCmp(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue)
+ {
+ __target_switch
+ {
+ case glsl:
+ return __glsl_texture(s, __makeVector(location,compareValue));
+ case hlsl:
+ __intrinsic_asm ".SampleCmp";
+ }
+ }
+
+ [__readNone] [ForceInline]
+ float SampleCmpLevelZero(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue)
+ {
+ __target_switch
+ {
+ case glsl:
+ return __glsl_texture_level_zero(s, __makeVector(location,compareValue));
+ case hlsl:
+ __intrinsic_asm ".SampleCmpLevelZero";
+ }
+ }
+
+ [__readNone] [ForceInline]
+ float SampleCmp(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case glsl:
+ return __glsl_texture_offset(s, __makeVector(location,compareValue), offset);
+ case hlsl:
+ __intrinsic_asm ".SampleCmpLevelZero";
+ }
+ }
+
+ [__readNone] [ForceInline]
+ float SampleCmpLevelZero(SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, float compareValue, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case glsl:
+ return __glsl_texture_offset_level_zero(s, __makeVector(location,compareValue), offset);
+ case hlsl:
+ __intrinsic_asm ".SampleCmpLevelZero";
+ }
+ }
+
+ [__readNone]
+ T SampleGrad(SamplerState s, vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGrad($p, $2, $3, $4)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Grad $gradX $gradY;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleGrad(SamplerState s, vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGradOffset($p, $2, $3, $4, $5)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Grad|ConstOffset $gradX $gradY $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ __glsl_extension(GL_ARB_sparse_texture_clamp)
+ [__readNone]
+ T SampleGrad(SamplerState s, vector<float, Shape.dimensions+isArray> location, vector<float, Shape.planeDimensions> gradX, vector<float, Shape.planeDimensions> gradY, constexpr vector<int, Shape.planeDimensions> offset, float lodClamp)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleGrad";
+ case glsl:
+ __intrinsic_asm "$ctextureGradOffsetClampARB($p, $2, $3, $4, $5, $6)$z";
+ case spirv:
+ return spirv_asm
+ {
+ OpCapability MinLod;
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Grad|ConstOffset|MinLod $gradX $gradY $offset $lodClamp;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleLevel(SamplerState s, vector<float, Shape.dimensions+isArray> location, float level)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleLevel";
+ case glsl:
+ __intrinsic_asm "$ctextureLod($p, $2, $3)$z";
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLayeredLod<$T0>($0, ($2).x, int(($2).y), ($3))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLayeredLod<$T0>($0, ($2).x, ($2).y, int(($2).z), ($3))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLayeredLod<$T0>($0, ($2).x, ($2).y, ($2).z, int(($2).w), ($3))";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "tex1DLod<$T0>($0, ($2), ($3))";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "tex2DLod<$T0>($0, ($2).x, ($2).y, ($3))";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "tex3DLod<$T0>($0, ($2).x, ($2).y, ($2).z, ($3))";
+ case $(SLANG_TEXTURE_CUBE):
+ __intrinsic_asm "texCubemapLod<$T0>($0, ($2).x, ($2).y, ($2).z, ($3))";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Lod $level;
+ __truncate $$T result __sampledType(T) %sampled;
+
+ };
+ }
+ }
+
+ [__readNone]
+ T SampleLevel(SamplerState s, vector<float, Shape.dimensions+isArray> location, float level, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".SampleLevel";
+ case glsl:
+ __intrinsic_asm "$ctextureLodOffset($p, $2, $3, $4)$z";
+ case spirv:
+ return spirv_asm
+ {
+ %sampledImage : __sampledImageType(this) = OpSampledImage $this $s;
+ %sampled : __sampledType(T) = OpImageSampleExplicitLod %sampledImage $location None|Lod|ConstOffset $level $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+}
+
+// Texture.GetDimensions
+${{{{
+const char* kTextureShapeTypeNames[] = {
+ "__Shape1D", "__Shape2D", "__Shape3D", "__ShapeCube"};
+for (int shapeIndex = 0; shapeIndex < 4; shapeIndex++)
+for (int isArray = 0; isArray <= 1; isArray++)
+for (int isMS = 0; isMS <= 1; isMS++) {
+ if (isMS)
+ {
+ if (shapeIndex != kStdlibShapeIndex2D)
+ continue;
+ }
+ if (isArray)
+ {
+ if (shapeIndex == kStdlibShapeIndex3D)
+ continue;
+ }
+ auto shapeTypeName = kTextureShapeTypeNames[shapeIndex];
+ TextureTypeInfo textureTypeInfo(kBaseTextureShapes[shapeIndex], isArray, isMS, 0, sb, path);
+}}}}
+
+__generic<T, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
+extension __TextureImpl<T,$(shapeTypeName),$(isArray),$(isMS),sampleCount,access,isShadow,isCombined,format>
+{
+ ${{{{
+ textureTypeInfo.writeGetDimensionFunctions();
+ }}}}
+}
+
+${{{{
+}
+}}}}
+
+// Texture.GetSamplePosition(int s);
+__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,1,sampleCount,access,isShadow,isCombined,format>
+{
+ float2 GetSamplePosition(int s);
+}
+
+__intrinsic_op($(kIROp_MakeArray))
+Array<T,4> __makeArray<T>(T v0, T v1, T v2, T v3);
+
+// Gather for scalar textures.
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gather(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, vector<float, Shape.dimensions+isArray> location, int component)
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGather($p, $2, $3)";
+ case spirv:
+ return spirv_asm {
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component;
+ };
+ }
+}
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gather_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, vector<float, Shape.dimensions+isArray> location, int component, vector<int, Shape.planeDimensions> offset)
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGatherOffset($p, $2, $3, $4)";
+ case spirv:
+ return spirv_asm {
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component ConstOffset $offset;
+ };
+ }
+}
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gather_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerState s, vector<float, Shape.dimensions+isArray> location, int component,
+ vector<int, Shape.planeDimensions> offset1,
+ vector<int, Shape.planeDimensions> offset2,
+ vector<int, Shape.planeDimensions> offset3,
+ vector<int, Shape.planeDimensions> offset4)
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGatherOffsets($p, $2, $3, $T4[]($4, $5, $6, $7))";
+ case spirv:
+ let offsets = __makeArray(offset1,offset2,offset3,offset4);
+ return spirv_asm {
+ OpCapability ImageGatherExtended;
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component ConstOffsets $offsets;
+ };
+ }
+}
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gatherCmp(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, int componentIndex, TElement compareValue)
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGather($p, $2, $4)";
+ case spirv:
+ return spirv_asm {
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue;
+ };
+ }
+}
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gatherCmp_offset(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, int componentIndex, TElement compareValue, vector<int, Shape.planeDimensions> offset)
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGatherOffset($p, $2, $4, $5)";
+ case spirv:
+ return spirv_asm {
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue ConstOffset $offset;
+ };
+ }
+}
+__generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
+[ForceInline]
+vector<TElement,4> __glsl_gatherCmp_offsets(__TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture, SamplerComparisonState s, vector<float, Shape.dimensions+isArray> location, int componentIndex, TElement compareValue,
+ vector<int, Shape.planeDimensions> offset1,
+ vector<int, Shape.planeDimensions> offset2,
+ vector<int, Shape.planeDimensions> offset3,
+ vector<int, Shape.planeDimensions> offset4
+ )
+{
+ __target_switch
+ {
+ case glsl:
+ __intrinsic_asm "textureGatherOffsets($p, $2, $4, $T5[]($5, $6, $7, $8))";
+ case spirv:
+ let offsets = __makeArray(offset1,offset2,offset3,offset4);
+ return spirv_asm {
+ OpCapability ImageGatherExtended;
+ %sampledImage : __sampledImageType(texture) = OpSampledImage $texture $s;
+ result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue ConstOffsets $offsets;
+ };
+ }
+}
+
+${{{{
+for (int isScalarTexture = 0; isScalarTexture <= 1; isScalarTexture++) {
+ if (isScalarTexture == 0)
+ {
+ sb << "__generic<T:__BuiltinArithmeticType, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>\n";
+ sb << "extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,0,format>\n";
+ }
+ else
+ {
+ sb << "__generic<T:__BuiltinArithmeticType, let N:int, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>\n";
+ sb << "extension __TextureImpl<vector<T,N>,Shape,isArray,0,sampleCount,0,isShadow,0,format>\n";
+ }
+}}}}
+{ // begin extension for gather
+${{{{
+ // Gather component
+ for (int isCmp = 0; isCmp <= 1; ++isCmp) {
+ const char* cmp = isCmp ? "Cmp" : "";
+ const char* cmpParam = isCmp? "T compareValue, " : "";
+ const char* compareArg = isCmp ? "compareValue, " : "";
+ const char* samplerStateType = isCmp ? "SamplerComparisonState" : "SamplerState";
+ const char* componentNames[] = {"", "Red", "Green", "Blue", "Alpha"};
+ for (auto componentId = 0; componentId < 4; componentId++) {
+ auto component = componentNames[componentId];
+ auto componentIndex = componentId == 0 ? 0 : componentId - 1;
+ }}}}
+ [ForceInline]
+ vector<T,4> Gather$(cmp)$(component)($(samplerStateType) s, vector<float, Shape.dimensions+isArray> location, $(cmpParam))
+ {
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm ".Gather$(cmp)$(component)";
+ case glsl:
+ case spirv:
+ return __glsl_gather$(cmp)<T>(this, s, location, $(componentIndex), $(compareArg));
+ }
+ }
+ [ForceInline]
+ vector<T,4> Gather$(cmp)$(component)($(samplerStateType) s, vector<float, Shape.dimensions+isArray> location, $(cmpParam) vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm ".Gather$(cmp)$(component)";
+ case glsl:
+ case spirv:
+ return __glsl_gather$(cmp)_offset<T>(this, s, location, $(componentIndex), $(compareArg) offset);
+ }
+ }
+ [ForceInline]
+ vector<T,4> Gather$(cmp)$(component)($(samplerStateType) s, vector<float, Shape.dimensions+isArray> location, $(cmpParam)
+ vector<int, Shape.planeDimensions> offset1,
+ vector<int, Shape.planeDimensions> offset2,
+ vector<int, Shape.planeDimensions> offset3,
+ vector<int, Shape.planeDimensions> offset4)
+ {
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm ".Gather$(cmp)$(component)";
+ case glsl:
+ case spirv:
+ return __glsl_gather$(cmp)_offsets<T>(this, s, location, $(componentIndex), $(compareArg) offset1,offset2,offset3,offset4);
+ }
+ }
+ ${{{{
+ } // for (component)
+ } // for (isCmp)
+ }}}}
+} // end extension for gather
+
+${{{{
+} // for (isScalarTexture)
+}}}}
+
+// Load/Subscript for readonly, no MS textures
+
+__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let isCombined:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,format>
+{
+ static const int isMS = 0;
+ static const int access = $(kStdlibResourceAccessReadOnly);
+
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ T __glsl_load(vector<int, Shape.dimensions+isArray> location)
+ {
+ __intrinsic_asm "$ctexelFetch($0, ($1), 0)$z";
+ }
+
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray+1> location)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$ctexelFetch($0, ($1).$w1b, ($1).$w1e)$z";
+ case spirv:
+ const int lodLoc = Shape.dimensions+isArray;
+ let coord = __vectorReshape<Shape.dimensions+isArray>(location);
+ let lod = location[lodLoc];
+ if (isCombined != 0)
+ {
+ return spirv_asm
+ {
+ %image:__imageType(this) = OpImage $this;
+ %sampled:__sampledType(T) = OpImageFetch %image $coord Lod $lod;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ else
+ {
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageFetch $this $coord Lod $lod;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+ }
+
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray+1> location, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$ctexelFetchOffset($0, ($1).$w1b, ($1).$w1e, ($2))$z";
+ case spirv:
+ const int lodLoc = Shape.dimensions+isArray;
+ let coord = __vectorReshape<Shape.dimensions+isArray>(location);
+ let lod = location[lodLoc];
+ if (isCombined != 0)
+ {
+ return spirv_asm
+ {
+ %image:__imageType(this) = OpImage $this;
+ %sampled:__sampledType(T) = OpImageFetch %image $coord Lod|ConstOffset $lod $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ else
+ {
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageFetch $this $coord Lod|ConstOffset $lod $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ __target_intrinsic(hlsl)
+ T Load(vector<int, Shape.dimensions+isArray+1> location, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
+ {
+ status = 0;
+ return Load(location, offset);
+ }
+
+ __subscript(vector<uint, Shape.dimensions+isArray> location) -> T
+ {
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ get
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".operator[]";
+ case glsl:
+ return __glsl_load(location);
+ case spirv:
+ if (isCombined != 0)
+ {
+ return spirv_asm
+ {
+ %image:__imageType(this) = OpImage $this;
+ %sampled:__sampledType(T) = OpImageFetch %image $location;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ else
+ {
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageFetch $this $location;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+ }
+ }
+}
+
+// Texture Load/Subscript for readonly, MS textures
+
+__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let isCombined:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,1,sampleCount,0,isShadow,isCombined,format>
+{
+ static const int access = $(kStdlibResourceAccessReadOnly);
+ static const int isMS = 1;
+
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$ctexelFetch($0, $1, ($2))$z";
+ case spirv:
+ if (isCombined != 0)
+ {
+ return spirv_asm
+ {
+ %image:__imageType(this) = OpImage $this;
+ %sampled:__sampledType(T) = OpImageFetch %image $location Sample $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ else
+ {
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageFetch $this $location Sample $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+ }
+
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex, constexpr vector<int, Shape.planeDimensions> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$ctexelFetchOffset($0, $1, ($2), ($3))$z";
+ case spirv:
+ if (isCombined != 0)
+ {
+ return spirv_asm
+ {
+ %image:__imageType(this) = OpImage $this;
+ %sampled:__sampledType(T) = OpImageFetch %image $location ConstOffset|Sample $offset $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ else
+ {
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageFetch $this $location ConstOffset|Sample $offset $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ __target_intrinsic(hlsl)
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex, constexpr vector<int, Shape.planeDimensions> offset, out uint status)
+ {
+ status = 0;
+ return Load(location, sampleIndex, offset);
+ }
+
+ __subscript(vector<uint, Shape.dimensions+isArray> location, int sampleIndex) -> T
+ {
+ __glsl_extension(GL_EXT_samplerless_texture_functions)
+ [__readNone]
+ [ForceInline]
+ get
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm "($0).sample[$2][$1]";
+ case glsl:
+ case spirv:
+ case cuda:
+ return Load(location, sampleIndex);
+ }
+ }
+ }
+}
+
+// Load/Subscript for readwrite textures
+${{{{
+ for (int access = kStdlibResourceAccessReadWrite; access<=kStdlibResourceAccessRasterizerOrdered; access++) {
+ const char* glslIntrinsic = "$cimageLoad($0, $1)$z";
+ const char* glslIntrinsicOffset = "$cimageLoad($0, ($1)+($2))$z";
+ const char* glslIntrinsicMS = "$cimageLoad($0, $1, $2)$z";
+ const char* glslIntrinsicMSOffset = "$cimageLoad($0, ($1)+($3), $2)$z";
+}}}}
+__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,format>
+{
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$(glslIntrinsic)";
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "surf1DLayeredread$C<$T0>($0, ($1).x * $E, ($1).y, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "surf2DLayeredread$C<$T0>($0, ($1).x * $E, ($1).y, ($1).z, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "surf3DLayeredread$C<$T0>($0, ($1).x * $E, ($1).y, ($1).z, ($1).w, SLANG_CUDA_BOUNDARY_MODE)";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "surf1Dread$C<$T0>($0, ($1) * $E, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "surf2Dread$C<$T0>($0, ($1).x * $E, ($1).y, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "surf3Dread$C<$T0>($0, ($1).x * $E, ($1).y, ($1).z, SLANG_CUDA_BOUNDARY_MODE)";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageRead $this $location;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, vector<int, Shape.dimensions+isArray> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$(glslIntrinsicOffset)";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageRead $this $location ConstOffset $offset;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, vector<int, Shape.dimensions+isArray> offset, out uint status)
+ {
+ __target_switch
+ {
+ case hlsl:
+ case cpp:
+ __intrinsic_asm ".Load";
+ default:
+ status = 0;
+ return Load(location, offset);
+ }
+ }
+
+ void __glslImageStore(vector<int, Shape.dimensions+isArray> location, T value)
+ {
+ __intrinsic_asm "imageStore($0, $1, $V2)";
+ }
+
+ __subscript(vector<uint, Shape.dimensions+isArray> location) -> T
+ {
+ [__readNone]
+ [ForceInline]
+ get
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".operator[]";
+ case glsl:
+ case spirv:
+ case cuda:
+ return Load(location);
+ }
+ }
+
+ [nonmutating]
+ [ForceInline]
+ set(T newValue)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".operator[]";
+ case glsl:
+ __glslImageStore(location, newValue);
+ case cuda:
+ if (isArray != 0)
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "surf1DLayeredwrite$C<$T0>($2, $0, ($1).x * $E, ($1).y, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "surf2DLayeredwrite$C<$T0>($2, $0, ($1).x * $E, ($1).y, ($1).z, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "surf3DLayeredwrite$C<$T0>($2, $0, ($1).x * $E, ($1).y, ($1).z, ($1).w, SLANG_CUDA_BOUNDARY_MODE)";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ else
+ {
+ switch(Shape.flavor)
+ {
+ case $(SLANG_TEXTURE_1D):
+ __intrinsic_asm "surf1Dwrite$C<$T0>($2, $0, ($1) * $E, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_2D):
+ __intrinsic_asm "surf2Dwrite$C<$T0>($2, $0, ($1).x * $E, ($1).y, SLANG_CUDA_BOUNDARY_MODE)";
+ case $(SLANG_TEXTURE_3D):
+ __intrinsic_asm "surf3Dwrite$C<$T0>($2, $0, ($1).x * $E, ($1).y, ($1).z, SLANG_CUDA_BOUNDARY_MODE)";
+ default:
+ __intrinsic_asm "<invalid intrinsic>";
+ }
+ }
+ case spirv:
+ return spirv_asm
+ {
+ OpImageWrite $this $location $newValue;
+ };
+ }
+ }
+
+ __intrinsic_op($(kIROp_ImageSubscript)) ref;
+ }
+}
+
+${{{{
+if (access == kStdlibResourceAccessReadWrite) {
+}}}}
+// RW MS textures.
+__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
+extension __TextureImpl<T,Shape,isArray,1,sampleCount,$(access),isShadow, 0,format>
+{
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$(glslIntrinsicMS)";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageRead $this $location Sample $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex, vector<int, Shape.dimensions+isArray> offset)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm ".Load";
+ case glsl:
+ __intrinsic_asm "$(glslIntrinsicMSOffset)";
+ case spirv:
+ return spirv_asm
+ {
+ %sampled:__sampledType(T) = OpImageRead $this $location ConstOffset|Sample $offset $sampleIndex;
+ __truncate $$T result __sampledType(T) %sampled;
+ };
+ }
+ }
+
+ [__readNone]
+ [ForceInline]
+ T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex, vector<int, Shape.dimensions+isArray> offset, out uint status)
+ {
+ __target_switch
+ {
+ case hlsl:
+ case cpp:
+ __intrinsic_asm ".Load";
+ default:
+ status = 0;
+ return Load(location, sampleIndex, offset);
+ }
+ }
+
+ void __glslImageStore(vector<int, Shape.dimensions+isArray> location, int sampleIndex, T value)
+ {
+ __intrinsic_asm "imageStore($0, $1, $2, $V3)";
+ }
+
+ __subscript(vector<uint, Shape.dimensions+isArray> location, int sampleIndex) -> T
+ {
+ [__readNone]
+ [ForceInline]
+ get
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm "$0.sample[$2][$1]";
+ case glsl:
+ case spirv:
+ case cuda:
+ return Load(location, sampleIndex);
+ }
+ }
+
+ [nonmutating]
+ [ForceInline]
+ set(T newValue)
+ {
+ __target_switch
+ {
+ case cpp:
+ case hlsl:
+ __intrinsic_asm "$0.sample[$2][$1]";
+ case glsl:
+ __glslImageStore(location, sampleIndex, newValue);
+ case spirv:
+ return spirv_asm
+ {
+ OpImageWrite $this $location $newValue Sample $sampleIndex;
+ };
+ }
+ }
+
+ __intrinsic_op($(kIROp_ImageSubscript)) ref;
+ }
+}
+
+${{{{
+} // if (access == kStdlibResourceAccessReadWrite) // for RW MS textures.
+} // for (access).
+}}}}
+
+// Texture type aliases.
+// T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int
+${{{{
+ const char* shapeTypeNames[] = {"1D", "2D", "3D", "Cube"};
+ const char* accessPrefix[] = {"", "RW", "RasterizerOrdered", "Feedback"};
+ const char* arrayPostFix[] = {"", "Array"};
+ const char* msPostFix[] = {"", "MS"};
+ for (int shape = 0; shape < 4; shape++)
+ for (int isArray = 0; isArray<=1; isArray++)
+ for (int isMS = 0; isMS<=1; isMS++)
+ for (int isCombined = 0; isCombined<=1; isCombined++)
+ for (int access = kStdlibResourceAccessReadOnly; access<=kStdlibResourceAccessFeedback; access++) {
+ if (access != kStdlibResourceAccessReadOnly)
+ {
+ // No RW Cube.
+ if (shape == kStdlibShapeIndexCube) continue;
+ }
+ if (access == kStdlibResourceAccessFeedback)
+ {
+ // Feedback only defined for Texture2D and Texture2DArray.
+ if (shape != 1) continue;
+ if (isMS) continue;
+ if (isCombined) continue;
+ }
+ if (isMS)
+ {
+ // Only Texture2DMS.
+ if (shape != kStdlibShapeIndex2D)
+ continue;
+ // Only Texture2DMS or RWTexture2DMS.
+ if (access >= kStdlibShapeIndex3D)
+ continue;
+ }
+ // No 3D Array.
+ if (shape == kStdlibShapeIndex3D && isArray == 1)
+ continue;
+ const char* textureTypeName = isCombined ? "Sampler" : "Texture";
+}}}}
+typealias $(accessPrefix[access])$(textureTypeName)$(shapeTypeNames[shape])$(arrayPostFix[isArray])$(msPostFix[isMS])<T=float4, let sampleCount:int=0, let format:int=0> = __TextureImpl<T, __Shape$(shapeTypeNames[shape]), $(isArray), $(isMS), sampleCount, $(access), 0, $(isCombined), format>;
+${{{{
+}
+}}}}
+
// AtomicAdd
// Make the GLSL atomicAdd available.
@@ -4362,6 +5884,7 @@ __generic<let N : int> float noise(vector<float, N> x)
/// is more semantically "correct."
__glsl_extension(GL_EXT_nonuniform_qualifier)
[__readNone]
+[ForceInline]
uint NonUniformResourceIndex(uint index)
{
__target_switch
@@ -7289,8 +8812,6 @@ matrix<T,N,M> WaveMultiPrefixSum(matrix<T,N,M> value, uint4 mask);
// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points
typedef Texture2D texture2D;
-
-
${{{{
// Buffer types
@@ -7308,19 +8829,21 @@ static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) /
for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
{
auto access = kBaseBufferAccessLevels[aa].access;
- bool isReadOnly = (access == SLANG_RESOURCE_ACCESS_READ);
- auto flavor = TextureFlavor::create(TextureFlavor::Shape::ShapeBuffer, access).flavor;
- sb << "__generic<T>\n";
- sb << "__magic_type(TextureType," << int(flavor) << ")\n";
- sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n";
- sb << "struct ";
+ sb << "__generic<T,let format:int=0>\n";
+ sb << "typealias ";
sb << kBaseBufferAccessLevels[aa].name;
- sb << "Buffer {\n";
+ sb << "Buffer = __TextureImpl<T, __ShapeBuffer, 0, 0, 0, " << aa << ", 0, 0, format>;\n";
+
+ bool isReadOnly = aa == 0;
- char const* glslTextureSizeFunc = (access == SLANG_RESOURCE_ACCESS_READ) ? "textureSize" : "imageSize";
- char const* glslLoadFuncName = (access == SLANG_RESOURCE_ACCESS_READ) ? "texelFetch" : "imageLoad";
- char const* spvLoadInstName = (access == SLANG_RESOURCE_ACCESS_READ) ? "OpImageFetch" : "OpImageRead";
+ char const* glslTextureSizeFunc = (isReadOnly) ? "textureSize" : "imageSize";
+ char const* glslLoadFuncName = (isReadOnly) ? "texelFetch" : "imageLoad";
+ char const* spvLoadInstName = (isReadOnly) ? "OpImageFetch" : "OpImageRead";
}}}}
+
+__generic<T, let format:int>
+extension __TextureImpl<T, __ShapeBuffer, 0, 0, 0, $(aa), 0, 0, format>
+{
[__readNone]
void GetDimensions(out uint dim)
{
@@ -7380,10 +8903,10 @@ ${{{{
} // access != SLANG_RESOURCE_ACCESS_READ
}}}}
- }
+ }
- };
+ }; // end extension
${{{{
}
}}}}
@@ -8164,29 +9687,9 @@ __target_intrinsic(hlsl, SAMPLER_FEEDBACK_MIP_REGION_USED)
struct SAMPLER_FEEDBACK_MIP_REGION_USED : __BuiltinSamplerFeedbackType {};
// All of these objects are write-only resources that point to a special kind of unordered access view meant for sampler feedback.
-
-// Calculate the flavor constants
-${{{{
-static const int feedbackTexture2DFlavor = int(TextureFlavor::create(TextureFlavor::Shape::Shape2D, SLANG_RESOURCE_ACCESS_WRITE, SLANG_TEXTURE_FEEDBACK_FLAG).flavor);
-static const int feedbackTexture2DArrayFlavor = int(TextureFlavor::create(TextureFlavor::Shape::Shape2D, SLANG_RESOURCE_ACCESS_WRITE, SLANG_TEXTURE_FEEDBACK_FLAG | SLANG_TEXTURE_ARRAY_FLAG).flavor);
-}}}}
-
-__magic_type(TextureType, $(feedbackTexture2DFlavor))
-__intrinsic_type($(kIROp_TextureType + (feedbackTexture2DFlavor << kIROpMeta_OtherShift)))
-struct FeedbackTexture2D<T : __BuiltinSamplerFeedbackType>
+__generic<T:__BuiltinSamplerFeedbackType>
+extension __TextureImpl<T,__Shape2D, 0, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
{
- __target_intrinsic
- void GetDimensions(out uint width, out uint height);
-
- __target_intrinsic
- void GetDimensions(uint mipLevel, out uint width, out uint height, out uint numberOfLevels);
-
- __target_intrinsic
- void GetDimensions(out float width,out float height);
-
- __target_intrinsic
- void GetDimensions(uint mipLevel, out float width,out float height, out float numberOfLevels);
-
// With Clamp
__target_intrinsic(hlsl, "($0).WriteSamplerFeedback($1, $2, $3, $4)")
@@ -8222,24 +9725,9 @@ struct FeedbackTexture2D<T : __BuiltinSamplerFeedbackType>
void WriteSamplerFeedbackGrad<S>(Texture2D<S> tex, SamplerState samp, float2 location, float2 ddx, float2 ddy);
};
-
-
-__magic_type(TextureType, $(feedbackTexture2DArrayFlavor))
-__intrinsic_type($(kIROp_TextureType + (feedbackTexture2DArrayFlavor << kIROpMeta_OtherShift)))
-struct FeedbackTexture2DArray<T : __BuiltinSamplerFeedbackType>
+__generic<T:__BuiltinSamplerFeedbackType>
+extension __TextureImpl<T,__Shape2D, 1, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
{
- __target_intrinsic
- void GetDimensions(out uint width,out uint height, out uint elements);
-
- __target_intrinsic
- void GetDimensions(uint mipLevel, out uint width,out uint height, out uint elements, out uint numberOfLevels);
-
- __target_intrinsic
- void GetDimensions(out float width,out float height, out float elements);
-
- __target_intrinsic
- void GetDimensions(uint mipLevel, out float width,out float height, out float elements, out float numberOfLevels);
-
// With Clamp
__target_intrinsic(hlsl, "($0).WriteSamplerFeedback($1, $2, $3, $4)")
diff --git a/source/slang/slang-ast-dump.cpp b/source/slang/slang-ast-dump.cpp
index 96a0afe6d..e05f0a455 100644
--- a/source/slang/slang-ast-dump.cpp
+++ b/source/slang/slang-ast-dump.cpp
@@ -435,13 +435,6 @@ struct ASTDumpContext
ScopeWrite(this).getBuf() << "DeclCheckStateExt{" << extState.isBeingChecked() << ", " << Index(state) << "}";
}
- void dump(TextureFlavor texFlavor)
- {
- m_buf.clear();
- m_buf << "TextureFlavor{" << Index(texFlavor.flavor) << "}";
- m_writer->emit(m_buf);
- }
-
void dump(FeedbackType::Kind kind)
{
m_buf.clear();
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
index 5238cd4e2..b23b43430 100644
--- a/source/slang/slang-ast-expr.h
+++ b/source/slang/slang-ast-expr.h
@@ -658,6 +658,8 @@ public:
SlangValueAddr,
SlangType,
SampledType, // __sampledType(T), this becomes a 4 vector of the component type of T
+ ImageType, // __imageType(texture), returns the equivalaent OpTypeImage of a given texture typed value.
+ SampledImageType, // __sampledImageType(texture), returns the equivalent OpTypeSampledImage of a given texture typed value.
TruncateMarker, // __truncate, an invented instruction which coerces to the result type by truncating the element count
EntryPoint, // __entryPoint, a placeholder for the id of a referencing entryPoint.
BuiltinVar,
diff --git a/source/slang/slang-ast-type.cpp b/source/slang/slang-ast-type.cpp
index af4f6d124..e8d702062 100644
--- a/source/slang/slang-ast-type.cpp
+++ b/source/slang/slang-ast-type.cpp
@@ -770,10 +770,97 @@ FeedbackType::Kind FeedbackType::getKind() const
return FeedbackType::Kind(magicMod->tag);
}
-TextureFlavor ResourceType::getFlavor() const
+SlangResourceShape ResourceType::getBaseShape()
+{
+ auto shape = _getGenericTypeArg(getDeclRefBase(), 1);
+ if (as<TextureShape1DType>(shape))
+ return SLANG_TEXTURE_1D;
+ else if (as<TextureShape2DType>(shape))
+ return SLANG_TEXTURE_2D;
+ else if (as<TextureShape3DType>(shape))
+ return SLANG_TEXTURE_3D;
+ else if (as<TextureShapeCubeType>(shape))
+ return SLANG_TEXTURE_CUBE;
+ else if (as<TextureShapeBufferType>(shape))
+ return SLANG_TEXTURE_BUFFER;
+
+ return SLANG_RESOURCE_NONE;
+}
+
+SlangResourceShape ResourceType::getShape()
+{
+ auto baseShape = (SlangResourceShape)getBaseShape();
+ if (isArray())
+ baseShape = (SlangResourceShape)((uint32_t)baseShape | SLANG_TEXTURE_ARRAY_FLAG);
+ if (isMultisample())
+ baseShape = (SlangResourceShape)((uint32_t)baseShape | SLANG_TEXTURE_MULTISAMPLE_FLAG);
+ if (isShadow())
+ baseShape = (SlangResourceShape)((uint32_t)baseShape | SLANG_TEXTURE_SHADOW_FLAG);
+ if (isFeedback())
+ baseShape = (SlangResourceShape)((uint32_t)baseShape | SLANG_TEXTURE_FEEDBACK_FLAG);
+ return baseShape;
+}
+
+bool ResourceType::isArray()
+{
+ auto isArray = _getGenericTypeArg(this, kStdlibTextureIsArrayParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(isArray))
+ return constIntVal->getValue() != 0;
+ return false;
+}
+
+bool ResourceType::isMultisample()
{
- auto magicMod = getDeclRef().getDecl()->findModifier<MagicTypeModifier>();
- return TextureFlavor(magicMod->tag);
+ auto isMS = _getGenericTypeArg(this, kStdlibTextureIsMultisampleParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(isMS))
+ return constIntVal->getValue() != 0;
+ return false;
+}
+
+bool ResourceType::isShadow()
+{
+ auto isShadow = _getGenericTypeArg(this, kStdlibTextureIsShadowParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(isShadow))
+ return constIntVal->getValue() != 0;
+ return false;
+}
+
+bool ResourceType::isFeedback()
+{
+ auto access = _getGenericTypeArg(this, kStdlibTextureAccessParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(access))
+ return constIntVal->getValue() == kStdlibResourceAccessFeedback;
+ return false;
+}
+
+bool ResourceType::isCombined()
+{
+ auto combined = _getGenericTypeArg(this, kStdlibTextureIsCombinedParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(combined))
+ return constIntVal->getValue() != 0;
+ return false;
+}
+
+SlangResourceAccess ResourceType::getAccess()
+{
+ auto access = _getGenericTypeArg(this, kStdlibTextureAccessParameterIndex);
+ if (auto constIntVal = as<ConstantIntVal>(access))
+ {
+ switch (constIntVal->getValue())
+ {
+ case kStdlibResourceAccessReadOnly:
+ return SLANG_RESOURCE_ACCESS_READ;
+ case kStdlibResourceAccessReadWrite:
+ return SLANG_RESOURCE_ACCESS_READ_WRITE;
+ case kStdlibResourceAccessRasterizerOrdered:
+ return SLANG_RESOURCE_ACCESS_RASTER_ORDERED;
+ case kStdlibResourceAccessFeedback:
+ return SLANG_RESOURCE_ACCESS_FEEDBACK;
+ default:
+ break;
+ }
+ }
+ return SLANG_RESOURCE_ACCESS_NONE;
}
SamplerStateFlavor SamplerStateType::getFlavor() const
@@ -792,9 +879,106 @@ Type* ResourceType::getElementType()
return as<Type>(_getGenericTypeArg(this, 0));
}
+void ResourceType::_toTextOverride(StringBuilder& out)
+{
+ auto tryPrintSimpleName = [&](String& outString) -> bool
+ {
+ StringBuilder resultSB;
+ auto access = getAccess();
+ switch (access)
+ {
+ case SLANG_RESOURCE_ACCESS_READ:
+ break;
+ case SLANG_RESOURCE_ACCESS_READ_WRITE:
+ resultSB << "RW";;
+ break;
+ case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
+ resultSB << "RasterizerOrdered";
+ break;
+ case SLANG_RESOURCE_ACCESS_FEEDBACK:
+ resultSB << "Feedback";
+ break;
+ default:
+ return false;
+ }
+ auto combined = as<ConstantIntVal>(_getGenericTypeArg(this, 7));
+ auto shapeVal = _getGenericTypeArg(this, 1);
+ if (!as<TextureShapeType>(shapeVal))
+ return false;
+ auto shape = getBaseShape();
+ if (!combined)
+ return false;
+ if (combined->getValue() != 0)
+ resultSB << "Sampler";
+ else
+ {
+ if (shape == SLANG_TEXTURE_BUFFER)
+ resultSB << "Buffer";
+ else
+ resultSB << "Texture";
+ }
+ switch (shape)
+ {
+ case SLANG_TEXTURE_1D:
+ resultSB << "1D";
+ break;
+ case SLANG_TEXTURE_2D:
+ resultSB << "2D";
+ break;
+ case SLANG_TEXTURE_3D:
+ resultSB << "3D";
+ break;
+ case SLANG_TEXTURE_CUBE:
+ resultSB << "Cube";
+ break;
+ }
+ auto isArrayVal = as<ConstantIntVal>(_getGenericTypeArg(this, 2));
+ if (!isArrayVal)
+ return false;
+ if (isArray())
+ resultSB << "Array";
+ auto isMultisampleVal = as<ConstantIntVal>(_getGenericTypeArg(this, 3));
+ if (!isMultisampleVal)
+ return false;
+ if (isMultisample())
+ resultSB << "MS";
+ auto isShadowVal = as<ConstantIntVal>(_getGenericTypeArg(this, 6));
+ if (!isShadowVal)
+ return false;
+ if (isShadow())
+ return false;
+ auto elementType = getElementType();
+ if (elementType)
+ {
+ resultSB << "<";
+ resultSB << elementType->toString();
+ auto sampleCount = _getGenericTypeArg(this, 4);
+ if (auto constIntVal = as<ConstantIntVal>(sampleCount))
+ {
+ if (constIntVal->getValue() != 0)
+ resultSB << ", " << constIntVal->getValue();
+ }
+ else
+ {
+ return false;
+ }
+ resultSB << ">";
+ }
+ outString = resultSB.toString();
+ return true;
+ };
+
+ String simpleName;
+
+ if (tryPrintSimpleName(simpleName))
+ out << simpleName;
+ else
+ DeclRefType::_toTextOverride(out);
+}
+
Val* TextureTypeBase::getSampleCount()
{
- return as<Type>(_getGenericTypeArg(this, 1));
+ return as<Type>(_getGenericTypeArg(this, 4));
}
Type* removeParamDirType(Type* type)
diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h
index 638012652..214d80916 100644
--- a/source/slang/slang-ast-type.h
+++ b/source/slang/slang-ast-type.h
@@ -118,22 +118,47 @@ class FeedbackType : public BuiltinType
Kind getKind() const;
};
+class TextureShapeType : public BuiltinType
+{
+ SLANG_ABSTRACT_AST_CLASS(TextureShapeType)
+};
+
+class TextureShape1DType : public TextureShapeType
+{
+ SLANG_AST_CLASS(TextureShape1DType)
+};
+class TextureShape2DType : public TextureShapeType
+{
+ SLANG_AST_CLASS(TextureShape2DType)
+};
+class TextureShape3DType : public TextureShapeType
+{
+ SLANG_AST_CLASS(TextureShape3DType)
+};
+class TextureShapeCubeType : public TextureShapeType
+{
+ SLANG_AST_CLASS(TextureShapeCubeType)
+};
+class TextureShapeBufferType : public TextureShapeType
+{
+ SLANG_AST_CLASS(TextureShapeBufferType)
+};
+
// Resources that contain "elements" that can be fetched
class ResourceType : public BuiltinType
{
SLANG_ABSTRACT_AST_CLASS(ResourceType)
- TextureFlavor getFlavor() const;
-
- TextureFlavor::Shape getBaseShape()
- {
- return getFlavor().getBaseShape();
- }
- bool isMultisample() { return getFlavor().isMultisample(); }
- bool isArray() { return getFlavor().isArray(); }
- SlangResourceShape getShape() const { return getFlavor().getShape(); }
- SlangResourceAccess getAccess() { return getFlavor().getAccess(); }
+ bool isMultisample();
+ bool isArray();
+ bool isShadow();
+ bool isFeedback();
+ bool isCombined();
+ SlangResourceShape getBaseShape();
+ SlangResourceShape getShape();
+ SlangResourceAccess getAccess();
Type* getElementType();
+ void _toTextOverride(StringBuilder& out);
};
class TextureTypeBase : public ResourceType
@@ -143,21 +168,11 @@ class TextureTypeBase : public ResourceType
Val* getSampleCount();
};
-
-
class TextureType : public TextureTypeBase
{
SLANG_AST_CLASS(TextureType)
};
-
-// This is a base type for texture/sampler pairs,
-// as they exist in, e.g., GLSL
-class TextureSamplerType : public TextureTypeBase
-{
- SLANG_AST_CLASS(TextureSamplerType)
-};
-
// This is a base type for `image*` types, as they exist in GLSL
class GLSLImageType : public TextureTypeBase
{
diff --git a/source/slang/slang-ast-val.cpp b/source/slang/slang-ast-val.cpp
index 8afc6e689..e860e1ec6 100644
--- a/source/slang/slang-ast-val.cpp
+++ b/source/slang/slang-ast-val.cpp
@@ -810,6 +810,7 @@ Val* PolynomialIntVal::_substituteImplOverride(ASTBuilder* astBuilder, Substitut
{
int diff = 0;
PolynomialIntValBuilder builder(astBuilder);
+ builder.constantTerm = getConstantTerm();
for (auto& term : getTerms())
{
IntegerLiteralValue evaluatedTermConstFactor;
@@ -835,6 +836,14 @@ Val* PolynomialIntVal::_substituteImplOverride(ASTBuilder* astBuilder, Substitut
}
else
{
+ if (evaluatedTermParamFactors.getCount() == 1 && evaluatedTermParamFactors[0]->getPower() == 1)
+ {
+ if (auto polyTerm = as<PolynomialIntVal>(evaluatedTermParamFactors[0]->getParam()))
+ {
+ builder.addToPolynomialTerm(polyTerm, evaluatedTermConstFactor);
+ continue;
+ }
+ }
auto newTerm = astBuilder->getOrCreate<PolynomialIntValTerm>(
evaluatedTermConstFactor, evaluatedTermParamFactors.getArrayView());
builder.terms.add(newTerm);
@@ -1335,14 +1344,19 @@ Val* WitnessLookupIntVal::_substituteImplOverride(ASTBuilder* astBuilder, Substi
{
int diff = 0;
auto newWitness = getWitness()->substituteImpl(astBuilder, subst, &diff);
- *ioDiff += diff;
if (diff)
{
+ *ioDiff += diff;
auto witnessEntry = tryFoldOrNull(astBuilder, as<SubtypeWitness>(newWitness), getKey());
if (witnessEntry)
+ {
return witnessEntry;
+ }
+ else
+ {
+ return astBuilder->getOrCreate<WitnessLookupIntVal>(getType(), newWitness, getKey());
+ }
}
- // Nothing found: don't substitute.
return this;
}
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index e130275bb..7edf27b30 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -723,7 +723,11 @@ namespace Slang
expr->loc = loc;
if (auto declRefExpr = as<DeclRefExpr>(originalExpr))
expr->scope = declRefExpr->scope;
-
+ else if (auto invokeExpr = as<InvokeExpr>(originalExpr))
+ {
+ if (auto calleeDeclRefExpr = as<DeclRefExpr>(invokeExpr->originalFunctionExpr))
+ expr->scope = calleeDeclRefExpr->scope;
+ }
// Whether or not the implicit `this` is mutable depends
// on the context in which it is used, and the lookup
// logic will have computed an appropriate "mode" based
@@ -2246,8 +2250,9 @@ namespace Slang
Expr* SemanticsExprVisitor::visitInvokeExpr(InvokeExpr* expr)
{
// check the base expression first
+ if (!expr->originalFunctionExpr)
+ expr->originalFunctionExpr = expr->functionExpr;
expr->functionExpr = CheckTerm(expr->functionExpr);
-
auto treatAsDifferentiableExpr = m_treatAsDifferentiableExpr;
m_treatAsDifferentiableExpr = nullptr;
// Next check the argument expressions
@@ -4018,7 +4023,9 @@ namespace Slang
operand.expr = typeExpr.exp;
}
else if(operand.flavor == SPIRVAsmOperand::SlangValue
- || operand.flavor == SPIRVAsmOperand::SlangValueAddr)
+ || operand.flavor == SPIRVAsmOperand::SlangValueAddr
+ || operand.flavor == SPIRVAsmOperand::ImageType
+ || operand.flavor == SPIRVAsmOperand::SampledImageType)
{
// This is a $expr operand, check the expr
operand.expr = dispatch(operand.expr);
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 7eebf1cac..d0efce0f5 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -1893,10 +1893,11 @@ void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec)
// We want to detect any call to an intrinsic operation,
// that we can emit it directly without mangling, etc.
UnownedStringSlice intrinsicDefinition;
- if (findTargetIntrinsicDefinition(funcValue, intrinsicDefinition))
+ auto resolvedFunc = getResolvedInstForDecorations(funcValue);
+ if (findTargetIntrinsicDefinition(resolvedFunc, intrinsicDefinition))
{
// Make sure we register all required preludes for emit.
- if (auto func = as<IRFunc>(getResolvedInstForDecorations(funcValue)))
+ if (auto func = as<IRFunc>(resolvedFunc))
{
for (auto block : func->getBlocks())
{
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index c48fa369d..95a6ea4ff 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -137,11 +137,8 @@ SlangResult CPPSourceEmitter::_calcCPPTextureTypeName(IRTextureTypeBase* texType
case SLANG_RESOURCE_ACCESS_CONSUME:
outName << "Consume";
break;
- case SLANG_RESOURCE_ACCESS_WRITE:
- if (texType->isFeedback())
- {
- outName << "Feedback";
- }
+ case SLANG_RESOURCE_ACCESS_FEEDBACK:
+ outName << "Feedback";
break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled resource access mode");
@@ -150,11 +147,11 @@ SlangResult CPPSourceEmitter::_calcCPPTextureTypeName(IRTextureTypeBase* texType
switch (texType->GetBaseShape())
{
- case TextureFlavor::Shape::Shape1D: outName << "Texture1D"; break;
- case TextureFlavor::Shape::Shape2D: outName << "Texture2D"; break;
- case TextureFlavor::Shape::Shape3D: outName << "Texture3D"; break;
- case TextureFlavor::Shape::ShapeCube: outName << "TextureCube"; break;
- case TextureFlavor::Shape::ShapeBuffer: outName << "Buffer"; break;
+ case SLANG_TEXTURE_1D: outName << "Texture1D"; break;
+ case SLANG_TEXTURE_2D: outName << "Texture2D"; break;
+ case SLANG_TEXTURE_3D: outName << "Texture3D"; break;
+ case SLANG_TEXTURE_CUBE: outName << "TextureCube"; break;
+ case SLANG_TEXTURE_BUFFER: outName << "Buffer"; break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled resource shape");
return SLANG_FAIL;
@@ -332,11 +329,7 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S
if (auto texType = as<IRTextureTypeBase>(type))
{
- // We don't support TextureSampler, so ignore that
- if (texType->getOp() != kIROp_TextureSamplerType)
- {
- return _calcCPPTextureTypeName(texType, out);
- }
+ return _calcCPPTextureTypeName(texType, out);
}
// If _getResourceTypePrefix returns something, we assume can output any specialization after it in order.
diff --git a/source/slang/slang-emit-cuda.cpp b/source/slang/slang-emit-cuda.cpp
index bd891928c..633b065c7 100644
--- a/source/slang/slang-emit-cuda.cpp
+++ b/source/slang/slang-emit-cuda.cpp
@@ -181,11 +181,7 @@ SlangResult CUDASourceEmitter::calcTypeName(IRType* type, CodeGenTarget target,
if (auto texType = as<IRTextureTypeBase>(type))
{
- // We don't support TextureSampler, so ignore that
- if (texType->getOp() != kIROp_TextureSamplerType)
- {
- return _calcCUDATextureTypeName(texType, out);
- }
+ return _calcCUDATextureTypeName(texType, out);
}
switch (type->getOp())
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index 4a75e84a0..bbfefc75c 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -714,11 +714,11 @@ void GLSLSourceEmitter::_emitGLSLTextureOrTextureSamplerType(IRTextureTypeBase*
m_writer->emit(baseName);
switch (type->GetBaseShape())
{
- case TextureFlavor::Shape::Shape1D: m_writer->emit("1D"); break;
- case TextureFlavor::Shape::Shape2D: m_writer->emit("2D"); break;
- case TextureFlavor::Shape::Shape3D: m_writer->emit("3D"); break;
- case TextureFlavor::Shape::ShapeCube: m_writer->emit("Cube"); break;
- case TextureFlavor::Shape::ShapeBuffer: m_writer->emit("Buffer"); break;
+ case SLANG_TEXTURE_1D: m_writer->emit("1D"); break;
+ case SLANG_TEXTURE_2D: m_writer->emit("2D"); break;
+ case SLANG_TEXTURE_3D: m_writer->emit("3D"); break;
+ case SLANG_TEXTURE_CUBE: m_writer->emit("Cube"); break;
+ case SLANG_TEXTURE_BUFFER: m_writer->emit("Buffer"); break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled resource shape");
break;
@@ -2355,6 +2355,11 @@ void GLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
// each of these IR opcodes.
if (auto texType = as<IRTextureType>(type))
{
+ if (texType->isCombined())
+ {
+ _emitGLSLTextureOrTextureSamplerType(texType, "sampler");
+ return;
+ }
switch (texType->getAccess())
{
case SLANG_RESOURCE_ACCESS_READ_WRITE:
@@ -2368,11 +2373,6 @@ void GLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
}
return;
}
- else if (auto textureSamplerType = as<IRTextureSamplerType>(type))
- {
- _emitGLSLTextureOrTextureSamplerType(textureSamplerType, "sampler");
- return;
- }
else if (auto imageType = as<IRGLSLImageType>(type))
{
_emitGLSLTextureOrTextureSamplerType(imageType, "image");
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 9defc9adc..9b333c281 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -253,11 +253,8 @@ void HLSLSourceEmitter::_emitHLSLTextureType(IRTextureTypeBase* texType)
m_writer->emit("Consume");
break;
- case SLANG_RESOURCE_ACCESS_WRITE:
- if (texType->isFeedback())
- {
- m_writer->emit("Feedback");
- }
+ case SLANG_RESOURCE_ACCESS_FEEDBACK:
+ m_writer->emit("Feedback");
break;
default:
@@ -267,11 +264,11 @@ void HLSLSourceEmitter::_emitHLSLTextureType(IRTextureTypeBase* texType)
switch (texType->GetBaseShape())
{
- case TextureFlavor::Shape::Shape1D: m_writer->emit("Texture1D"); break;
- case TextureFlavor::Shape::Shape2D: m_writer->emit("Texture2D"); break;
- case TextureFlavor::Shape::Shape3D: m_writer->emit("Texture3D"); break;
- case TextureFlavor::Shape::ShapeCube: m_writer->emit("TextureCube"); break;
- case TextureFlavor::Shape::ShapeBuffer: m_writer->emit("Buffer"); break;
+ case SLANG_TEXTURE_1D: m_writer->emit("Texture1D"); break;
+ case SLANG_TEXTURE_2D: m_writer->emit("Texture2D"); break;
+ case SLANG_TEXTURE_3D: m_writer->emit("Texture3D"); break;
+ case SLANG_TEXTURE_CUBE: m_writer->emit("TextureCube"); break;
+ case SLANG_TEXTURE_BUFFER: m_writer->emit("Buffer"); break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled resource shape");
break;
@@ -287,14 +284,11 @@ void HLSLSourceEmitter::_emitHLSLTextureType(IRTextureTypeBase* texType)
}
m_writer->emit("<");
emitType(texType->getElementType());
- if (texType->getOperandCount() == 2)
+ auto sampleCount = as<IRIntLit>(texType->getSampleCount());
+ if (sampleCount->getValue() != 0)
{
- auto sampleCount = as<IRIntLit>(texType->getSampleCount());
- if (sampleCount->getValue() != 0)
- {
- m_writer->emit(", ");
- m_writer->emit(sampleCount->getValue());
- }
+ m_writer->emit(", ");
+ m_writer->emit(sampleCount->getValue());
}
m_writer->emit(" >");
}
@@ -954,11 +948,6 @@ void HLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
_emitHLSLTextureType(texType);
return;
}
- else if (const auto textureSamplerType = as<IRTextureSamplerType>(type))
- {
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "this target should see combined texture-sampler types");
- return;
- }
else if (auto imageType = as<IRGLSLImageType>(type))
{
_emitHLSLTextureType(imageType);
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 19c46f373..4c802641d 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -1361,12 +1361,8 @@ struct SPIRVEmitContext
case kIROp_TextureType:
return ensureTextureType(inst, cast<IRTextureType>(inst));
case kIROp_SamplerStateType:
+ case kIROp_SamplerComparisonStateType:
return emitOpTypeSampler(inst);
- case kIROp_TextureSamplerType:
- return emitOpTypeSampledImage(
- inst,
- ensureTextureType(nullptr, cast<IRTextureTypeBase>(inst))
- );
case kIROp_RaytracingAccelerationStructureType:
requireSPIRVCapability(SpvCapabilityRayTracingKHR);
@@ -1627,22 +1623,19 @@ struct SPIRVEmitContext
SpvDim dim = SpvDim1D; // Silence uninitialized warnings from msvc...
switch(inst->GetBaseShape())
{
- case TextureFlavor::Shape1D:
- case TextureFlavor::Shape1DArray:
+ case SLANG_TEXTURE_1D:
dim = SpvDim1D;
break;
- case TextureFlavor::Shape2D:
- case TextureFlavor::Shape2DArray:
+ case SLANG_TEXTURE_2D:
dim = SpvDim2D;
break;
- case TextureFlavor::Shape3D:
+ case SLANG_TEXTURE_3D:
dim = SpvDim3D;
break;
- case TextureFlavor::ShapeCube:
- case TextureFlavor::ShapeCubeArray:
+ case SLANG_TEXTURE_CUBE:
dim = SpvDimCube;
break;
- case TextureFlavor::ShapeBuffer:
+ case SLANG_TEXTURE_BUFFER:
dim = SpvDimBuffer;
break;
}
@@ -1717,6 +1710,24 @@ struct SPIRVEmitContext
//
// The op itself
//
+
+ if (inst->isCombined())
+ {
+ auto imageType = emitOpTypeImage(
+ nullptr,
+ dropVector(sampledType),
+ dim,
+ SpvLiteralInteger::from32(depth),
+ SpvLiteralInteger::from32(arrayed),
+ SpvLiteralInteger::from32(ms),
+ SpvLiteralInteger::from32(sampled),
+ format
+ );
+ return emitOpTypeSampledImage(
+ assignee,
+ imageType);
+ }
+
return emitOpTypeImage(
assignee,
dropVector(sampledType),
@@ -4578,6 +4589,24 @@ struct SPIRVEmitContext
emitOperand(ensureInst(sampledType));
break;
}
+ case kIROp_SPIRVAsmOperandImageType:
+ case kIROp_SPIRVAsmOperandSampledImageType:
+ {
+ IRBuilder builder(m_irModule);
+ auto textureInst = as<IRTextureTypeBase>(operand->getValue()->getDataType());
+ auto imageType = builder.getTextureType(
+ textureInst->getElementType(),
+ textureInst->getShapeInst(),
+ textureInst->getIsArrayInst(),
+ textureInst->getIsMultisampleInst(),
+ textureInst->getSampleCountInst(),
+ textureInst->getAccessInst(),
+ textureInst->getIsShadowInst(),
+ builder.getIntValue(builder.getIntType(), (operand->getOp() == kIROp_SPIRVAsmOperandSampledImageType ? 1 : 0)),
+ textureInst->getFormatInst());
+ emitOperand(ensureInst(imageType));
+ break;
+ }
case kIROp_SPIRVAsmOperandBuiltinVar:
{
emitOperand(ensureInst(operand));
@@ -4774,7 +4803,7 @@ struct SPIRVEmitContext
}
else
{
- emitInstCustomOperandFunc(
+ last = emitInstCustomOperandFunc(
opParent,
assignedInst,
opcode,
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 1ee5ba67c..bd7db604f 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -401,14 +401,16 @@ Result linkAndOptimizeIR(
for (;;)
{
bool changed = false;
-
+ auto b1 = dumpIRToString(irModule->getModuleInst());
dumpIRIfEnabled(codeGenContext, irModule, "BEFORE-SPECIALIZE");
if (!codeGenContext->isSpecializationDisabled())
changed |= specializeModule(irModule, codeGenContext->getSink());
if (codeGenContext->getSink()->getErrorCount() != 0)
return SLANG_FAIL;
dumpIRIfEnabled(codeGenContext, irModule, "AFTER-SPECIALIZE");
+ auto b2 = dumpIRToString(irModule->getModuleInst());
+ applySparseConditionalConstantPropagation(irModule, codeGenContext->getSink());
eliminateDeadCode(irModule);
validateIRModuleIfEnabled(codeGenContext, irModule);
@@ -420,9 +422,6 @@ Result linkAndOptimizeIR(
// Unroll loops.
if (codeGenContext->getSink()->getErrorCount() == 0)
{
- applySparseConditionalConstantPropagationForGlobalScope(
- irModule, codeGenContext->getSink());
-
if (!unrollLoopsInModule(irModule, codeGenContext->getSink()))
return SLANG_FAIL;
}
@@ -587,11 +586,7 @@ Result linkAndOptimizeIR(
sink);
}
- if(isKhronosTarget(targetRequest))
- {
- // SPIR-V doesn't support 1-vectors
- legalizeVectorTypes(irModule, sink);
- }
+ legalizeVectorTypes(irModule, sink);
// Once specialization and type legalization have been performed,
// we should perform some of our basic optimization steps again,
diff --git a/source/slang/slang-intrinsic-expand.cpp b/source/slang/slang-intrinsic-expand.cpp
index f17f564c8..d65fdf8bb 100644
--- a/source/slang/slang-intrinsic-expand.cpp
+++ b/source/slang/slang-intrinsic-expand.cpp
@@ -351,47 +351,50 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
SLANG_RELEASE_ASSERT(m_argCount >= 1);
auto textureArg = m_args[0].get();
-
- if (const auto baseTextureSamplerType = as<IRTextureSamplerType>(textureArg->getDataType()))
- {
- // If the base object (first argument) has a combined texture-sampler type,
- // then we can simply use that argument as-is.
- //
- m_emitter->emitOperand(textureArg, getInfo(EmitOp::General));
-
- // HACK: Because the target intrinsic strings are using indices based on the
- // parameter list with the `SamplerState` parameter in place, seeing this opcode
- // and this type tells us that we are about to have an off-by-one sort of
- // situation. We quietly patch it up by offseting the index-based access for
- // all the other operands.
- //
- m_argIndexOffset -= 1;
- }
- else if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
+
+ if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
{
- // If the base object (first argument) has a texture type, then we expect
- // the next argument to be a sampler to pair with it.
- //
- SLANG_RELEASE_ASSERT(m_argCount >= 2);
- auto samplerArg = m_args[1].get();
-
- // We will emit GLSL code to construct the corresponding combined texture/sampler
- // type from the separate pieces.
- //
- m_emitter->emitTextureOrTextureSamplerType(baseTextureType, "sampler");
- if (auto samplerType = as<IRSamplerStateTypeBase>(samplerArg->getDataType()))
+ if (baseTextureType->isCombined())
{
- if (as<IRSamplerComparisonStateType>(samplerType))
+ // If the base object (first argument) has a combined texture-sampler type,
+ // then we can simply use that argument as-is.
+ //
+ m_emitter->emitOperand(textureArg, getInfo(EmitOp::General));
+
+ // HACK: Because the target intrinsic strings are using indices based on the
+ // parameter list with the `SamplerState` parameter in place, seeing this opcode
+ // and this type tells us that we are about to have an off-by-one sort of
+ // situation. We quietly patch it up by offseting the index-based access for
+ // all the other operands.
+ //
+ m_argIndexOffset -= 1;
+ }
+ else
+ {
+ // If the base object (first argument) has a texture type, then we expect
+ // the next argument to be a sampler to pair with it.
+ //
+ SLANG_RELEASE_ASSERT(m_argCount >= 2);
+ auto samplerArg = m_args[1].get();
+
+ // We will emit GLSL code to construct the corresponding combined texture/sampler
+ // type from the separate pieces.
+ //
+ m_emitter->emitTextureOrTextureSamplerType(baseTextureType, "sampler");
+ if (auto samplerType = as<IRSamplerStateTypeBase>(samplerArg->getDataType()))
{
- m_writer->emit("Shadow");
+ if (as<IRSamplerComparisonStateType>(samplerType))
+ {
+ m_writer->emit("Shadow");
+ }
}
- }
- m_writer->emit("(");
- m_emitter->emitOperand(textureArg, getInfo(EmitOp::General));
- m_writer->emit(",");
- m_emitter->emitOperand(samplerArg, getInfo(EmitOp::General));
- m_writer->emit(")");
+ m_writer->emit("(");
+ m_emitter->emitOperand(textureArg, getInfo(EmitOp::General));
+ m_writer->emit(",");
+ m_emitter->emitOperand(samplerArg, getInfo(EmitOp::General));
+ m_writer->emit(")");
+ }
}
else
{
@@ -516,14 +519,10 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
auto textureArg = m_args[0].get();
IRType* elementType = nullptr;
- if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
+ if (auto baseTextureType = as<IRTextureTypeBase>(textureArg->getDataType()))
{
elementType = baseTextureType->getElementType();
}
- else if(auto baseTextureSamplerType = as<IRTextureSamplerType>(textureArg->getDataType()))
- {
- elementType = baseTextureSamplerType->getElementType();
- }
else
{
SLANG_UNEXPECTED("bad format in intrinsic definition");
@@ -797,6 +796,31 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
}
break;
+ case 'w':
+ {
+ // Emit a swizzle of the argument.
+ Index argIndex = parseNat() + m_argIndexOffset;
+ SLANG_RELEASE_ASSERT((0 <= argIndex) && (argIndex < m_argCount));
+ auto arg = m_args[argIndex];
+ d = *cursor++;
+ auto vectorType = as<IRVectorType>(arg.get()->getDataType());
+ auto vectorSize = as<IRIntLit>(vectorType->getElementCount())->getValue();
+ const char swizzleNames[] = { 'x', 'y', 'z', 'w' };
+ if (d == 'b')
+ {
+ // Emit the first half the vector up to the n-1'th element.
+ for (int i = 0; i < Math::Min(4, (int)vectorSize - 1); i++)
+ m_writer->emitChar(swizzleNames[i]);
+ }
+ else if (d == 'e')
+ {
+ // Emit the swizzle to get the last element.
+ if (vectorSize <= 4)
+ m_writer->emitChar(swizzleNames[vectorSize - 1]);
+ }
+ }
+ break;
+
default:
SLANG_UNEXPECTED("bad format in intrinsic definition");
break;
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 8f87d23e7..88d398070 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -133,23 +133,25 @@ INST(Nop, nop, 0, 0)
INST(SamplerComparisonStateType, SamplerComparisonState, 0, HOISTABLE)
INST_RANGE(SamplerStateTypeBase, SamplerStateType, SamplerComparisonStateType)
+ INST(TextureShape1DType, TextureShape1DType, 0, HOISTABLE)
+ INST(TextureShape2DType, TextureShape1DType, 0, HOISTABLE)
+ INST(TextureShape3DType, TextureShape1DType, 0, HOISTABLE)
+ INST(TextureShapeCubeType, TextureShape1DType, 0, HOISTABLE)
+ INST(TextureShapeBufferType, TextureShapeBufferType, 0, HOISTABLE)
+
// TODO: Why do we have all this hierarchy here, when everything
// that actually matters is currently nested under `TextureTypeBase`?
/* ResourceTypeBase */
/* ResourceType */
/* TextureTypeBase */
- // NOTE! TextureFlavor::Flavor is stored in 'other' bits for these types.
/* TextureType */
- INST(TextureType, TextureType, 0, USE_OTHER | HOISTABLE)
- /* TextureSamplerType */
- INST(TextureSamplerType, TextureSamplerType, 0, USE_OTHER | HOISTABLE)
+ INST(TextureType, TextureType, 8, HOISTABLE)
/* GLSLImageType */
INST(GLSLImageType, GLSLImageType, 0, USE_OTHER | HOISTABLE)
INST_RANGE(TextureTypeBase, TextureType, GLSLImageType)
INST_RANGE(ResourceType, TextureType, GLSLImageType)
INST_RANGE(ResourceTypeBase, TextureType, GLSLImageType)
-
/* UntypedBufferResourceType */
/* ByteAddressBufferTypeBase */
INST(HLSLByteAddressBufferType, ByteAddressBuffer, 0, HOISTABLE)
@@ -1124,7 +1126,14 @@ INST(SPIRVAsmInst, SPIRVAsmInst, 1, 0)
// A type function which returns the result type of sampling an image of
// this component type
INST(SPIRVAsmOperandSampledType, __sampledType, 1, HOISTABLE)
-INST_RANGE(SPIRVAsmOperand, SPIRVAsmOperandLiteral, SPIRVAsmOperandSampledType)
+
+ // A type function which returns the equivalent OpTypeImage type of sampled image value
+ INST(SPIRVAsmOperandImageType, __imageType, 1, HOISTABLE)
+
+ // A type function which returns the equivalent OpTypeImage type of sampled image value
+ INST(SPIRVAsmOperandSampledImageType, __sampledImageType, 1, HOISTABLE)
+
+INST_RANGE(SPIRVAsmOperand, SPIRVAsmOperandLiteral, SPIRVAsmOperandSampledImageType)
#undef PARENT
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 2869f7058..434f0305e 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -3274,7 +3274,16 @@ public:
IRConstRefType* getConstRefType(IRType* valueType);
IRPtrTypeBase* getPtrType(IROp op, IRType* valueType);
IRPtrType* getPtrType(IROp op, IRType* valueType, IRIntegerValue addressSpace);
-
+ IRTextureTypeBase* getTextureType(
+ IRType* elementType,
+ IRInst* shape,
+ IRInst* isArray,
+ IRInst* isMS,
+ IRInst* sampleCount,
+ IRInst* access,
+ IRInst* isShadow,
+ IRInst* isCombined,
+ IRInst* format);
IRComPtrType* getComPtrType(IRType* valueType);
/// Get a 'SPIRV literal'
@@ -4063,6 +4072,8 @@ public:
IRSPIRVAsmOperand* emitSPIRVAsmOperandBuiltinVar(IRInst* type, IRInst* builtinKind);
IRSPIRVAsmOperand* emitSPIRVAsmOperandGLSL450Set();
IRSPIRVAsmOperand* emitSPIRVAsmOperandSampledType(IRType* elementType);
+ IRSPIRVAsmOperand* emitSPIRVAsmOperandImageType(IRInst* element);
+ IRSPIRVAsmOperand* emitSPIRVAsmOperandSampledImageType(IRInst* element);
IRSPIRVAsmOperand* emitSPIRVAsmOperandTruncate();
IRSPIRVAsmOperand* emitSPIRVAsmOperandEntryPoint();
IRSPIRVAsmInst* emitSPIRVAsmInst(IRInst* opcode, List<IRInst*> operands);
diff --git a/source/slang/slang-ir-lower-generic-call.cpp b/source/slang/slang-ir-lower-generic-call.cpp
index aaa419b2e..c312d3c88 100644
--- a/source/slang/slang-ir-lower-generic-call.cpp
+++ b/source/slang/slang-ir-lower-generic-call.cpp
@@ -239,6 +239,13 @@ namespace Slang
// If we see a call(specialize(gFunc, Targs), args),
// translate it into call(gFunc, args, Targs).
auto loweredFunc = specializeInst->getBase();
+
+ // Don't process intrinsic functions.
+ UnownedStringSlice intrinsicDef;
+ if (findTargetIntrinsicDefinition(getResolvedInstForDecorations(loweredFunc),
+ sharedContext->targetReq->getTargetCaps(), intrinsicDef))
+ return;
+
// All callees should have already been lowered in lower-generic-functions pass.
// For intrinsic generic functions, they are left as is, and we also need to ignore
// them here.
@@ -251,14 +258,6 @@ namespace Slang
// All nested generic functions are supposed to be flattend before this pass.
// If they are not, they represent an intrinsic function that should not be
// modified in this pass.
- auto innerMostFunc = findInnerMostSpecializingBase(static_cast<IRSpecialize*>(loweredFunc));
- if (innerMostFunc && innerMostFunc->getOp() == kIROp_Generic)
- {
- innerMostFunc =
- findInnerMostGenericReturnVal(static_cast<IRGeneric*>(innerMostFunc));
- }
- if (innerMostFunc->findDecoration<IRTargetIntrinsicDecoration>())
- return;
SLANG_UNEXPECTED("Nested generics specialization.");
}
else if (loweredFunc->getOp() == kIROp_LookupWitness)
diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp
index baedbbd22..1e15f4384 100644
--- a/source/slang/slang-ir-lower-generic-function.cpp
+++ b/source/slang/slang-ir-lower-generic-function.cpp
@@ -44,7 +44,8 @@ namespace Slang
}
SLANG_ASSERT(func);
// Do not lower intrinsic functions.
- if (!func->isDefinition() || func->findDecoration<IRTargetIntrinsicDecoration>())
+ UnownedStringSlice intrinsicDef;
+ if (!func->isDefinition() || findTargetIntrinsicDefinition(func, sharedContext->targetReq->getTargetCaps(), intrinsicDef))
{
sharedContext->loweredGenericFunctions[genericValue] = genericValue;
return genericValue;
diff --git a/source/slang/slang-ir-simplify-cfg.cpp b/source/slang/slang-ir-simplify-cfg.cpp
index 127a515ce..ad10a8c48 100644
--- a/source/slang/slang-ir-simplify-cfg.cpp
+++ b/source/slang/slang-ir-simplify-cfg.cpp
@@ -943,6 +943,11 @@ bool simplifyCFG(IRModule* module, CFGSimplificationOptions options)
bool simplifyCFG(IRGlobalValueWithCode* func, CFGSimplificationOptions options)
{
+ if (auto genericFunc = as<IRGeneric>(func))
+ {
+ if (auto inner = as<IRFunc>(findGenericReturnVal(genericFunc)))
+ processFunc(inner, options);
+ }
return processFunc(func, options);
}
diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp
index 2155ce499..7dbb02a71 100644
--- a/source/slang/slang-ir-spirv-legalize.cpp
+++ b/source/slang/slang-ir-spirv-legalize.cpp
@@ -298,7 +298,7 @@ struct SPIRVLegalizationContext : public SourceEmitterBase
static void inferTextureFormat(IRInst* textureInst, IRTextureTypeBase* textureType)
{
- ImageFormat format = ImageFormat::unknown;
+ ImageFormat format = (ImageFormat)(textureType->getFormat());
if (auto decor = textureInst->findDecoration<IRFormatDecoration>())
{
format = decor->getFormat();
@@ -390,15 +390,19 @@ struct SPIRVLegalizationContext : public SourceEmitterBase
{
IRBuilder builder(textureInst->getModule());
builder.setInsertBefore(textureInst);
- List<IRInst*> args;
- args.add(textureType->getOperand(0));
- if (textureType->getOperandCount() >= 2)
- args.add(textureType->getOperand(1));
- else
- args.add(builder.getIntValue(builder.getUIntType(), 0));
- args.add(builder.getIntValue(builder.getUIntType(), IRIntegerValue(format)));
+ auto formatArg = builder.getIntValue(builder.getUIntType(), IRIntegerValue(format));
+
+ auto newType = builder.getTextureType(
+ textureType->getElementType(),
+ textureType->getShapeInst(),
+ textureType->getIsArrayInst(),
+ textureType->getIsMultisampleInst(),
+ textureType->getSampleCountInst(),
+ textureType->getAccessInst(),
+ textureType->getIsShadowInst(),
+ textureType->getIsCombinedInst(),
+ formatArg);
- auto newType = (IRType*)builder.emitIntrinsicInst(builder.getTypeKind(), textureType->getOp(), 3, args.getBuffer());
if (textureInst->getFullType() == textureType)
{
// Simple texture typed global param.
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index c40a62941..adac4cd10 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2784,6 +2784,12 @@ namespace Slang
return (IRPtrType*)getType(op, 2, operands);
}
+ IRTextureTypeBase* IRBuilder::getTextureType(IRType* elementType, IRInst* shape, IRInst* isArray, IRInst* isMS, IRInst* sampleCount, IRInst* access, IRInst* isShadow, IRInst* isCombined, IRInst* format)
+ {
+ IRInst* args[] = {(IRInst*)elementType, shape, isArray, isMS, sampleCount, access, isShadow, isCombined, format};
+ return as<IRTextureTypeBase>(emitIntrinsicInst(getTypeKind(), kIROp_TextureType, (UInt)(sizeof(args)/sizeof(IRInst*)), args));
+ }
+
IRComPtrType* IRBuilder::getComPtrType(IRType* valueType)
{
return (IRComPtrType*)getType(kIROp_ComPtrType, valueType);
@@ -5832,6 +5838,32 @@ namespace Slang
return i;
}
+ IRSPIRVAsmOperand* IRBuilder::emitSPIRVAsmOperandImageType(IRInst* element)
+ {
+ SLANG_ASSERT(as<IRSPIRVAsm>(m_insertLoc.getParent()));
+ const auto i = createInst<IRSPIRVAsmOperand>(
+ this,
+ kIROp_SPIRVAsmOperandImageType,
+ getTypeType(),
+ element
+ );
+ addInst(i);
+ return i;
+ }
+
+ IRSPIRVAsmOperand* IRBuilder::emitSPIRVAsmOperandSampledImageType(IRInst* element)
+ {
+ SLANG_ASSERT(as<IRSPIRVAsm>(m_insertLoc.getParent()));
+ const auto i = createInst<IRSPIRVAsmOperand>(
+ this,
+ kIROp_SPIRVAsmOperandSampledImageType,
+ getTypeType(),
+ element
+ );
+ addInst(i);
+ return i;
+ }
+
IRSPIRVAsmOperand* IRBuilder::emitSPIRVAsmOperandTruncate()
{
SLANG_ASSERT(as<IRSPIRVAsm>(m_insertLoc.getParent()));
@@ -6723,6 +6755,16 @@ namespace Slang
dumpInstExpr(context, inst->getOperand(0));
dump(context, ")");
return;
+ case kIROp_SPIRVAsmOperandImageType:
+ dump(context, "__imageType(");
+ dumpInstExpr(context, inst->getOperand(0));
+ dump(context, ")");
+ return;
+ case kIROp_SPIRVAsmOperandSampledImageType:
+ dump(context, "__sampledImageType(");
+ dumpInstExpr(context, inst->getOperand(0));
+ dump(context, ")");
+ return;
}
dump(context, opInfo.name);
@@ -7011,13 +7053,6 @@ namespace Slang
//
// We may want to care about decorations.
- // If it's a resource type - special case the handling of the resource flavor
- if (IRResourceTypeBase::isaImpl(opA) &&
- static_cast<const IRResourceTypeBase*>(a)->getFlavor() != static_cast<const IRResourceTypeBase*>(b)->getFlavor())
- {
- return false;
- }
-
// TODO(JS): There is a question here about what to do about decorations.
// For now we ignore decorations. Are two types potentially different if there decorations different?
// If decorations play a part in difference in types - the order of decorations presumably is not important.
@@ -7940,13 +7975,13 @@ namespace Slang
auto func = as<IRGlobalValueWithCode>(callee);
if (!func)
return false;
- auto block = func->getFirstBlock();
- if (!block)
- return false;
- if (auto genAsm = as<IRGenericAsm>(block->getTerminator()))
+ for (auto block : func->getBlocks())
{
- outDefinition = genAsm->getAsm();
- return true;
+ if (auto genAsm = as<IRGenericAsm>(block->getTerminator()))
+ {
+ outDefinition = genAsm->getAsm();
+ return true;
+ }
}
return false;
}
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index f0be72248..6b055b19e 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -1366,21 +1366,61 @@ SIMPLE_IR_TYPE(BasicBlockType, Type)
struct IRResourceTypeBase : IRType
{
- TextureFlavor getFlavor() const
- {
- return TextureFlavor((getOp() >> kIROpMeta_OtherShift) & 0xFFFF);
+ IRInst* getShapeInst() { return getOperand(kStdlibTextureShapeParameterIndex); }
+ IRInst* getIsArrayInst() { return getOperand(kStdlibTextureIsArrayParameterIndex); }
+ IRInst* getIsMultisampleInst() { return getOperand(kStdlibTextureIsMultisampleParameterIndex); }
+ IRInst* getSampleCountInst() { return getOperand(kStdlibTextureSampleCountParameterIndex); }
+ IRInst* getAccessInst() { return getOperand(kStdlibTextureAccessParameterIndex); }
+ IRInst* getIsShadowInst() { return getOperand(kStdlibTextureIsShadowParameterIndex); }
+ IRInst* getIsCombinedInst() { return getOperand(kStdlibTextureIsCombinedParameterIndex); }
+ IRInst* getFormatInst() { return getOperand(kStdlibTextureFormatParameterIndex); }
+
+ SlangResourceShape GetBaseShape()
+ {
+ switch (getOperand(1)->getOp())
+ {
+ case kIROp_TextureShape1DType:
+ return SLANG_TEXTURE_1D;
+ case kIROp_TextureShape2DType:
+ return SLANG_TEXTURE_2D;
+ case kIROp_TextureShape3DType:
+ return SLANG_TEXTURE_3D;
+ case kIROp_TextureShapeCubeType:
+ return SLANG_TEXTURE_CUBE;
+ case kIROp_TextureShapeBufferType:
+ return SLANG_TEXTURE_BUFFER;
+ default:
+ return SLANG_RESOURCE_NONE;
+ }
}
-
- TextureFlavor::Shape GetBaseShape() const
+ bool isFeedback() { return getIntVal(getAccessInst()) == kStdlibResourceAccessFeedback; }
+ bool isMultisample() { return getIntVal(getIsMultisampleInst()) != 0; }
+ bool isArray() { return getIntVal(getIsArrayInst()) != 0; }
+ bool isShadow() { return getIntVal(getIsShadowInst()) != 0; }
+ bool isCombined() { return getIntVal(getIsCombinedInst()) != 0; }
+
+ SlangResourceShape getShape() { return (SlangResourceShape)((uint32_t)GetBaseShape() | (isArray() ? SLANG_TEXTURE_ARRAY_FLAG : 0)); }
+ SlangResourceAccess getAccess()
{
- return getFlavor().getBaseShape();
+ auto constVal = as<IRIntLit>(getOperand(kStdlibTextureAccessParameterIndex));
+ if (constVal)
+ {
+ switch (getIntVal(constVal))
+ {
+ case kStdlibResourceAccessReadOnly:
+ return SLANG_RESOURCE_ACCESS_READ;
+ case kStdlibResourceAccessReadWrite:
+ return SLANG_RESOURCE_ACCESS_READ_WRITE;
+ case kStdlibResourceAccessRasterizerOrdered:
+ return SLANG_RESOURCE_ACCESS_RASTER_ORDERED;
+ case kStdlibResourceAccessFeedback:
+ return SLANG_RESOURCE_ACCESS_FEEDBACK;
+ default:
+ break;
+ }
+ }
+ return SLANG_RESOURCE_ACCESS_UNKNOWN;
}
- bool isFeedback() const { return getFlavor().isFeedback(); }
- bool isMultisample() const { return getFlavor().isMultisample(); }
- bool isArray() const { return getFlavor().isArray(); }
- bool isShadow() const { return getFlavor().isShadow(); }
- SlangResourceShape getShape() const { return getFlavor().getShape(); }
- SlangResourceAccess getAccess() const { return getFlavor().getAccess(); }
IR_PARENT_ISA(ResourceTypeBase);
};
@@ -1388,9 +1428,9 @@ struct IRResourceTypeBase : IRType
struct IRResourceType : IRResourceTypeBase
{
IRType* getElementType() { return (IRType*)getOperand(0); }
- IRType* getSampleCount() { return (IRType*)getOperand(1); }
- bool hasFormat() { return getOperandCount() >= 2; }
- IRIntegerValue getFormat() { return getIntVal(getOperand(2)); }
+ IRInst* getSampleCount() { return getSampleCountInst(); }
+ bool hasFormat() { return getOperandCount() >= 9; }
+ IRIntegerValue getFormat() { return getIntVal(getFormatInst()); }
IR_PARENT_ISA(ResourceType)
};
@@ -1405,11 +1445,6 @@ struct IRTextureType : IRTextureTypeBase
IR_LEAF_ISA(TextureType)
};
-struct IRTextureSamplerType : IRTextureTypeBase
-{
- IR_LEAF_ISA(TextureSamplerType)
-};
-
struct IRGLSLImageType : IRTextureTypeBase
{
IR_LEAF_ISA(GLSLImageType)
diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp
index b32236019..d71227b6c 100644
--- a/source/slang/slang-lookup.cpp
+++ b/source/slang/slang-lookup.cpp
@@ -406,6 +406,7 @@ static void _lookUpMembersInSuperTypeDeclImpl(
else
{
auto selfType = DeclRefType::create(astBuilder, declRef);
+ selfType = selfType->getCanonicalType();
inheritanceInfo = semantics->getShared()->getInheritanceInfo(selfType);
}
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 38651c5a4..cd9d19bcc 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -3983,6 +3983,26 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo>
}
return builder->emitSPIRVAsmOperandSampledType(i);
}
+ case SPIRVAsmOperand::ImageType:
+ {
+ IRInst* i;
+ {
+ IRBuilderInsertLocScope insertScope(builder);
+ builder->setInsertBefore(spirvAsmInst);
+ i = getSimpleVal(context, lowerRValueExpr(context, operand.expr));
+ }
+ return builder->emitSPIRVAsmOperandImageType(i);
+ }
+ case SPIRVAsmOperand::SampledImageType:
+ {
+ IRInst* i;
+ {
+ IRBuilderInsertLocScope insertScope(builder);
+ builder->setInsertBefore(spirvAsmInst);
+ i = getSimpleVal(context, lowerRValueExpr(context, operand.expr));
+ }
+ return builder->emitSPIRVAsmOperandSampledImageType(i);
+ }
case SPIRVAsmOperand::TruncateMarker:
{
return builder->emitSPIRVAsmOperandTruncate();
@@ -8945,6 +8965,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
IRFunc* irFunc = subBuilder->createFunc();
addNameHint(subContext, irFunc, decl);
addLinkageDecoration(subContext, irFunc, decl);
+
+ // Register the value now, to avoid any possible infinite recursion when lowering the body or attributes.
+ context->setGlobalValue(decl, LoweredValInfo::simple(findOuterMostGeneric(irFunc)));
// Always force inline diff setter accessor to prevent downstream compiler from complaining
// fields are not fully initialized for the first `inout` parameter.
@@ -9226,9 +9249,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
addCatchAllIntrinsicDecorationIfNeeded(irFunc, decl);
- // Register the value now, to avoid any possible infinite recursion when lowering ForwardDerivativeAttribute
- context->setGlobalValue(decl, LoweredValInfo::simple(findOuterMostGeneric(irFunc)));
-
bool isInline = false;
for (auto modifier : decl->modifiers)
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index 7241fdd6e..4ddafa425 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -1135,9 +1135,10 @@ static void addExplicitParameterBindings_GLSL(
// We can't infer TextureSampler from HLSL (it's not an HLSL concept)
// So use default layout
auto varType = varDecl.getDecl()->getType();
- if (as<TextureSamplerType>(varType))
+ if (auto textureType = as<TextureType>(varType))
{
- return;
+ if (textureType->isCombined())
+ return;
}
// Can we map to a Vulkan kind in principal?
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 0a2076fd0..52c91cfbe 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -6494,6 +6494,21 @@ namespace Slang
parser->ReadMatchingToken(TokenType::RParent);
return SPIRVAsmOperand{SPIRVAsmOperand::SampledType, Token{}, typeExpr};
}
+ // The __imageType function
+ if (AdvanceIf(parser, "__imageType"))
+ {
+ parser->ReadToken(TokenType::LParent);
+ const auto typeExpr = parser->ParseExpression();
+ parser->ReadMatchingToken(TokenType::RParent);
+ return SPIRVAsmOperand{ SPIRVAsmOperand::ImageType, Token{}, typeExpr };
+ }
+ if (AdvanceIf(parser, "__sampledImageType"))
+ {
+ parser->ReadToken(TokenType::LParent);
+ const auto typeExpr = parser->ParseExpression();
+ parser->ReadMatchingToken(TokenType::RParent);
+ return SPIRVAsmOperand{ SPIRVAsmOperand::SampledImageType, Token{}, typeExpr };
+ }
// The pseudo-operand for component truncation
else if(parser->LookAheadToken("__truncate"))
{
diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp
index 3a521589e..f0540deb3 100644
--- a/source/slang/slang-reflection-api.cpp
+++ b/source/slang/slang-reflection-api.cpp
@@ -1263,12 +1263,11 @@ namespace Slang
SlangBindingType _calcResourceBindingType(
Type* type)
{
- if(const auto combinedTextureSamplerType = as<TextureSamplerType>(type))
- {
- return SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER;
- }
- else if( auto resourceType = as<ResourceType>(type) )
+ if( auto resourceType = as<ResourceType>(type) )
{
+ if (resourceType->isCombined())
+ return SlangBindingType(SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER);
+
auto shape = resourceType->getBaseShape();
auto access = resourceType->getAccess();
diff --git a/source/slang/slang-serialize-ir.cpp b/source/slang/slang-serialize-ir.cpp
index d84049b74..ccd5a2e7d 100644
--- a/source/slang/slang-serialize-ir.cpp
+++ b/source/slang/slang-serialize-ir.cpp
@@ -10,12 +10,6 @@
namespace Slang {
-static bool _isTextureTypeBase(IROp opIn)
-{
- const int op = (kIROpMask_OpMask & opIn);
- return op >= kIROp_FirstTextureTypeBase && op <= kIROp_LastTextureTypeBase;
-}
-
static bool _isConstant(IROp opIn)
{
const int op = (kIROpMask_OpMask & opIn);
@@ -246,15 +240,6 @@ Result IRSerialWriter::write(IRModule* module, SerialSourceLocWriter* sourceLocW
continue;
}
- IRTextureTypeBase* textureBase = as<IRTextureTypeBase>(srcInst);
- if (textureBase)
- {
- dstInst.m_payloadType = PayloadType::OperandAndUInt32;
- dstInst.m_payload.m_operandAndUInt32.m_uint32 = uint32_t(srcInst->getOp()) >> kIROpMeta_OtherShift;
- dstInst.m_payload.m_operandAndUInt32.m_operand = getInstIndex(textureBase->getElementType());
- continue;
- }
-
// ModuleInst is different, in so far as it holds a pointer to IRModule, but we don't need
// to save that off in a special way, so can just use regular path
@@ -834,22 +819,6 @@ Result IRSerialReader::read(const IRSerialData& data, Session* session, SerialSo
insts[i] = irConst;
}
- else if (_isTextureTypeBase(op))
- {
- // TODO: We should clean up the IR encoding of texture types so that
- // they do not need to have special-case suport in the serialization layer.
-
- // All IR texture types currently have a single operand
- Int operandCount = 1;
- IRTextureTypeBase* inst = module->_allocateInst<IRTextureTypeBase>(op, operandCount);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::OperandAndUInt32);
-
- // Reintroduce the texture type bits into the the
- const uint32_t other = srcInst.m_payload.m_operandAndUInt32.m_uint32;
- inst->m_op = IROp(uint32_t(inst->getOp()) | (other << kIROpMeta_OtherShift));
-
- insts[i] = inst;
- }
else
{
int numOperands = srcInst.getNumOperands();
diff --git a/source/slang/slang-serialize-misc-type-info.h b/source/slang/slang-serialize-misc-type-info.h
index d3d83e1d0..c40edc1e7 100644
--- a/source/slang/slang-serialize-misc-type-info.h
+++ b/source/slang/slang-serialize-misc-type-info.h
@@ -22,19 +22,6 @@ struct SerialTypeInfo<FeedbackType::Kind> : public SerialIdentityTypeInfo<Feedba
template <>
struct SerialTypeInfo<SamplerStateFlavor> : public SerialConvertTypeInfo<SamplerStateFlavor, uint8_t> {};
-// TextureFlavor
-
-template <>
-struct SerialTypeInfo<TextureFlavor>
-{
- typedef TextureFlavor NativeType;
- typedef uint16_t SerialType;
- enum { SerialAlignment = sizeof(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial) { SLANG_UNUSED(writer); *(SerialType*)serial = ((const NativeType*)native)->flavor; }
- static void toNative(SerialReader* reader, const void* serial, void* native) { SLANG_UNUSED(reader); ((NativeType*)native)->flavor = *(const SerialType*)serial; }
-};
-
// ImageFormat
template <>
struct SerialTypeInfo<ImageFormat> : public SerialConvertTypeInfo<ImageFormat, uint8_t> {};
diff --git a/source/slang/slang-stdlib-textures.cpp b/source/slang/slang-stdlib-textures.cpp
index 98380033c..9ebfc54d6 100644
--- a/source/slang/slang-stdlib-textures.cpp
+++ b/source/slang/slang-stdlib-textures.cpp
@@ -46,20 +46,16 @@ struct BraceScope
};
TextureTypeInfo::TextureTypeInfo(
- TextureTypePrefixInfo const& prefixInfo,
BaseTextureShapeInfo const& base,
bool isArray,
bool isMultisample,
bool isShadow,
- BaseTextureAccessInfo const& accessInfo,
StringBuilder& inSB,
String const& inPath)
- : prefixInfo(prefixInfo)
- , base(base)
+ : base(base)
, isArray(isArray)
, isMultisample(isMultisample)
, isShadow(isShadow)
- , accessInfo(accessInfo)
, sb(inSB)
, path(inPath)
{
@@ -82,7 +78,10 @@ void TextureTypeInfo::writeFuncBody(
if(glsl.getLength())
{
sb << i << "case glsl:\n";
- sb << i << "__intrinsic_asm \"" << glsl << "\";\n";
+ if (glsl.startsWith("if"))
+ sb << glsl;
+ else
+ sb << i << "__intrinsic_asm \"" << glsl << "\";\n";
}
if(cuda.getLength())
{
@@ -99,16 +98,6 @@ void TextureTypeInfo::writeFuncBody(
}
}
-void TextureTypeInfo::writeFuncDecorations(
- const String& glsl,
- const String& cuda)
-{
- if(glsl.getLength())
- sb << i << "__target_intrinsic(glsl, \"" << glsl << "\")\n";
- if(cuda.getLength())
- sb << i << "__target_intrinsic(cuda, \"" << cuda << "\")\n";
-}
-
void TextureTypeInfo::writeFuncWithSig(
const char* funcName,
const String& sig,
@@ -117,24 +106,12 @@ void TextureTypeInfo::writeFuncWithSig(
const String& cuda,
const ReadNoneMode readNoneMode)
{
- const bool isReadOnly = (accessInfo.access == SLANG_RESOURCE_ACCESS_READ);
- const bool rn =
- readNoneMode == ReadNoneMode::Always
- || readNoneMode == ReadNoneMode::IfReadOnly && isReadOnly;
- if(spirv.getLength())
- {
- if(rn)
- sb << i << "[__readNone]\n";
- sb << i << sig << "\n";
- writeFuncBody(funcName, glsl, cuda, spirv);
- }
- else
- {
- writeFuncDecorations(glsl, cuda);
- if(rn)
- sb << i << "[__readNone]\n";
- sb << i << sig << ";\n";
- }
+ if (readNoneMode == ReadNoneMode::Always)
+ sb << i << "[__readNone]\n";
+ sb << i << "[__readNone]\n";
+ sb << i << "[ForceInline]\n";
+ sb << i << sig << "\n";
+ writeFuncBody(funcName, glsl, cuda, spirv);
sb << "\n";
}
@@ -157,108 +134,14 @@ void TextureTypeInfo::writeFunc(
);
}
-void TextureTypeInfo::emitTypeDecl()
-{
- char const* baseName = prefixInfo.name;
- char const* baseShapeName = base.shapeName;
- TextureFlavor::Shape baseShape = base.baseShape;
-
- // Arrays of 3D textures aren't allowed
- if (isArray && baseShape == TextureFlavor::Shape::Shape3D) return;
-
- auto access = accessInfo.access;
-
- // No such thing as RWTextureCube
- if (access == SLANG_RESOURCE_ACCESS_READ_WRITE && baseShape == TextureFlavor::Shape::ShapeCube)
- {
- return;
- }
-
- // TODO: any constraints to enforce on what gets to be multisampled?
-
- unsigned flavor = baseShape;
- if (isArray) flavor |= TextureFlavor::ArrayFlag;
- if (isMultisample) flavor |= TextureFlavor::MultisampleFlag;
- if (isShadow) flavor |= TextureFlavor::ShadowFlag;
-
- flavor |= (access << 8);
-
- // emit a generic signature
- sb << "__generic<T = float4";
- // Multi-sample rw texture types have an optional sampleCount parameter.
- if (isMultisample)
- sb << ", let sampleCount : int = 0";
- sb << ">";
-
- if(prefixInfo.combined)
- {
- sb << "__magic_type(TextureSamplerType," << int(flavor) << ")\n";
- sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n";
- }
- else
- {
- sb << "__magic_type(TextureType," << int(flavor) << ")\n";
- sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n";
- }
- sb << "struct ";
- sb << accessInfo.name;
- sb << baseName;
- sb << baseShapeName;
- if (isMultisample) sb << "MS";
- if (isArray) sb << "Array";
- if (isShadow) sb << "Shadow";
- sb << "\n";
-
- // The struct body
- {
- BraceScope structBodyScope{i, sb, ";\n"};
-
- writeQueryFunctions();
-
- if(baseShape != TextureFlavor::Shape::ShapeCube)
- writeSubscriptFunctions();
-
- if( !isMultisample )
- writeSampleFunctions();
- }
-
- writeGatherExtensions();
-} // TextureTypeInfo::emitTypeDecl
-
-void TextureTypeInfo::writeQueryFunctions()
+void TextureTypeInfo::writeGetDimensionFunctions()
{
static const char* kComponentNames[]{ "x", "y", "z", "w" };
- TextureFlavor::Shape baseShape = base.baseShape;
-
- char const* samplerStateParam = prefixInfo.combined ? "" : "SamplerState s, ";
- auto access = accessInfo.access;
-
- if( !isMultisample )
- {
- writeFunc(
- "float",
- "CalculateLevelOfDetail",
- cat(samplerStateParam, "float", base.coordCount, " location"),
- cat("textureQueryLod($p, $2).x"),
- "",
- "",
- ReadNoneMode::Never
- );
-
- writeFunc(
- "float",
- "CalculateLevelOfDetailUnclamped",
- cat(samplerStateParam, "float", base.coordCount, " location"),
- cat("textureQueryLod($p, $2).y"),
- "",
- "",
- ReadNoneMode::Never
- );
- }
+ SlangResourceShape baseShape = base.baseShape;
// `GetDimensions`
- const char* dimParamTypes[] = {"out float ", "out int ", "out uint "};
+ const char* dimParamTypes[] = { "out float ", "out int ", "out uint " };
const char* dimParamTypesInner[] = { "float", "int", "uint" };
for (int tid = 0; tid < 3; tid++)
{
@@ -274,19 +157,19 @@ void TextureTypeInfo::writeQueryFunctions()
switch (baseShape)
{
- case TextureFlavor::Shape::Shape1D:
+ case SLANG_TEXTURE_1D:
params << t << "width";
sizeDimCount = 1;
break;
- case TextureFlavor::Shape::Shape2D:
- case TextureFlavor::Shape::ShapeCube:
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
params << t << "width,";
params << t << "height";
sizeDimCount = 2;
break;
- case TextureFlavor::Shape::Shape3D:
+ case SLANG_TEXTURE_3D:
params << t << "width,";
params << t << "height,";
params << t << "depth";
@@ -315,79 +198,77 @@ void TextureTypeInfo::writeQueryFunctions()
StringBuilder glsl;
{
- glsl << "(";
-
- int aa = 1;
- String lodStr = ", 0";
- if (includeMipInfo)
- {
- int mipLevelArg = aa++;
- lodStr = ", int($";
- lodStr.append(mipLevelArg);
- lodStr.append(")");
- }
-
- String opStr = " = textureSize($0" + lodStr;
- switch (access)
- {
- case SLANG_RESOURCE_ACCESS_READ_WRITE:
- case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
- opStr = " = imageSize($0";
- break;
-
- default:
- break;
- }
-
- int cc = 0;
- switch (baseShape)
- {
- case TextureFlavor::Shape::Shape1D:
- glsl << "($" << aa++ << opStr << ")";
- if (isArray)
+ auto emitIntrinsic = [&](UnownedStringSlice funcName, bool useLodStr)
{
- glsl << ".x";
- }
- glsl << ")";
- cc = 1;
- break;
-
- case TextureFlavor::Shape::Shape2D:
- case TextureFlavor::Shape::ShapeCube:
- glsl << "($" << aa++ << opStr << ").x)";
- glsl << ", ($" << aa++ << opStr << ").y)";
- cc = 2;
- break;
-
- case TextureFlavor::Shape::Shape3D:
- glsl << "($" << aa++ << opStr << ").x)";
- glsl << ", ($" << aa++ << opStr << ").y)";
- glsl << ", ($" << aa++ << opStr << ").z)";
- cc = 3;
- break;
-
- default:
- SLANG_UNEXPECTED("unhandled resource shape");
- break;
- }
-
- if (isArray)
- {
- glsl << ", ($" << aa++ << opStr << ")." << kComponentNames[cc] << ")";
- }
-
- if (isMultisample)
- {
- glsl << ", ($" << aa++ << " = textureSamples($0))";
- }
+ int aa = 1;
+ StringBuilder opStrSB;
+ opStrSB << " = " << funcName << "($0";
+ if (useLodStr)
+ {
+ String lodStr = ", 0";
+ if (includeMipInfo)
+ {
+ int mipLevelArg = aa++;
+ lodStr = ", int($";
+ lodStr.append(mipLevelArg);
+ lodStr.append(")");
+ }
+ opStrSB << lodStr;
+ }
+ auto opStr = opStrSB.produceString();
+ int cc = 0;
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ glsl << "($" << aa++ << opStr << ")";
+ if (isArray)
+ {
+ glsl << ".x";
+ }
+ glsl << ")";
+ cc = 1;
+ break;
+
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
+ glsl << "($" << aa++ << opStr << ").x)";
+ glsl << ", ($" << aa++ << opStr << ").y)";
+ cc = 2;
+ break;
+
+ case SLANG_TEXTURE_3D:
+ glsl << "($" << aa++ << opStr << ").x)";
+ glsl << ", ($" << aa++ << opStr << ").y)";
+ glsl << ", ($" << aa++ << opStr << ").z)";
+ cc = 3;
+ break;
+
+ default:
+ SLANG_UNEXPECTED("unhandled resource shape");
+ break;
+ }
- if (includeMipInfo)
- {
- glsl << ", ($" << aa++ << " = textureQueryLevels($0))";
- }
+ if (isArray)
+ {
+ glsl << ", ($" << aa++ << opStr << ")." << kComponentNames[cc] << ")";
+ }
+ if (isMultisample)
+ {
+ glsl << ", ($" << aa++ << " = textureSamples($0))";
+ }
- glsl << ")";
+ if (includeMipInfo)
+ {
+ glsl << ", ($" << aa++ << " = textureQueryLevels($0))";
+ }
+ };
+ glsl << "if (access == " << kStdlibResourceAccessReadOnly << ") __intrinsic_asm \"";
+ emitIntrinsic(toSlice("textureSize"), true);
+ glsl << "\";\n";
+ glsl << "__intrinsic_asm \"";
+ emitIntrinsic(toSlice("imageSize"), false);
+ glsl << "\";\n";
}
StringBuilder spirv;
@@ -434,17 +315,17 @@ void TextureTypeInfo::writeQueryFunctions()
};
switch (baseShape)
{
- case TextureFlavor::Shape::Shape1D:
+ case SLANG_TEXTURE_1D:
extractSizeComponent(0, "width");
break;
- case TextureFlavor::Shape::Shape2D:
- case TextureFlavor::Shape::ShapeCube:
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
extractSizeComponent(0, "width");
extractSizeComponent(1, "height");
break;
- case TextureFlavor::Shape::Shape3D:
+ case SLANG_TEXTURE_3D:
extractSizeComponent(0, "width");
extractSizeComponent(1, "height");
extractSizeComponent(2, "depth");
@@ -485,901 +366,6 @@ void TextureTypeInfo::writeQueryFunctions()
ReadNoneMode::Always);
}
}
-
- // `GetSamplePosition()`
- if( isMultisample )
- {
- writeFunc("float2", "GetSamplePosition", "int s", "", "", "", ReadNoneMode::Never);
- }
-
- // `Load()`
-
- if( base.coordCount + isArray < 4 )
- {
- // The `Load()` operation on an ordinary `Texture2D` takes
- // an `int3` for the location, where `.xy` holds the texel
- // coordinates, and `.z` holds the mip level to use.
- //
- // The third coordinate for mip level is absent in
- // `Texure2DMS.Load()` and `RWTexture2D.Load`. This pattern
- // is repreated for all the other texture shapes.
- //
- bool needsMipLevel = !isMultisample && (access == SLANG_RESOURCE_ACCESS_READ);
-
- int loadCoordCount = base.coordCount + isArray + (needsMipLevel?1:0);
-
- char const* glslFuncName = (access == SLANG_RESOURCE_ACCESS_READ) ? "texelFetch" : "imageLoad";
-
- // When translating to GLSL, we need to break apart the `location` argument.
- //
- // TODO: this should realy be handled by having this member actually get lowered!
- static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
- static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
-
- // TODO: The GLSL translations here only handle the read-only texture
- // cases (stuff that lowers to `texture*` in GLSL) and not the stuff
- // that lowers to `image*`.
- //
- // At some point it may make sense to separate the read-only and
- // `RW`/`RasterizerOrdered` cases here rather than try to share code.
-
- // CUDA
- StringBuilder cudaBuilder;
- if(!isMultisample)
- {
- if (access == SLANG_RESOURCE_ACCESS_READ_WRITE)
- {
- const int coordCount = base.coordCount;
- const int vecCount = coordCount + int(isArray);
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- cudaBuilder << "surf" << coordCount << "D";
- if (isArray)
- {
- cudaBuilder << "Layered";
- }
- cudaBuilder << "read";
- cudaBuilder << "<$T0>($0";
- for (int j = 0; j < coordCount; ++j)
- {
- cudaBuilder << ", ($1)";
- if (vecCount > 1)
- {
- cudaBuilder << '.' << char(j + 'x');
- }
-
- // Surface access is *byte* addressed in x in CUDA
- if (j == 0)
- {
- cudaBuilder << " * $E";
- }
- }
- if (isArray)
- {
- cudaBuilder << ", int(($1)." << char(coordCount + 'x') << ")";
- }
- cudaBuilder << ", SLANG_CUDA_BOUNDARY_MODE)";
- }
- else
- {
- cudaBuilder << "__target_intrinsic(cuda, \"surfCubemap";
- if (isArray)
- {
- cudaBuilder << "Layered";
- }
- cudaBuilder << "read";
-
- // Surface access is *byte* addressed in x in CUDA
- cudaBuilder << "<$T0>($0, ($1).x * $E, ($1).y, ($1).z";
- if (isArray)
- {
- cudaBuilder << ", int(($1).w)";
- }
- cudaBuilder << ", SLANG_CUDA_BOUNDARY_MODE)";
- }
- }
- else if (access == SLANG_RESOURCE_ACCESS_READ)
- {
- // We can allow this on Texture1D
- if( baseShape == TextureFlavor::Shape::Shape1D && isArray == false)
- {
- cudaBuilder << "tex1Dfetch<$T0>($0, ($1).x)";
- }
- }
- }
-
- // SPIRV
- auto getSpirvIntrinsic = [&](bool hasSampleIndex, bool hasOffset)
- {
- StringBuilder spirv;
- spirv << "%lod:$$int = OpCompositeExtract $location " << base.coordCount + isArray << "; ";
- spirv << "%coord:$$int" << base.coordCount + isArray << " = OpVectorShuffle $location $location ";
- for (int i = 0; i < base.coordCount + isArray; i++)
- spirv << " " << i;
- spirv << "; ";
- spirv << "%sampled:__sampledType(T) = ";
- if (access == SLANG_RESOURCE_ACCESS_READ_WRITE)
- spirv << "OpImageRead";
- else
- spirv << "OpImageFetch";
- spirv << " $this %coord ";
- uint32_t operandMask = 0;
- if (!hasSampleIndex)
- operandMask |= SpvImageOperandsLodMask;
- if (hasOffset)
- operandMask |= SpvImageOperandsConstOffsetMask;
- if (hasSampleIndex)
- operandMask |= SpvImageOperandsSampleMask;
- spirv << operandMask << " ";
- if (operandMask & SpvImageOperandsLodMask)
- spirv << " %lod";
- if (operandMask & SpvImageOperandsConstOffsetMask)
- spirv << " $offset";
- if (operandMask & SpvImageOperandsSampleMask)
- spirv << " $sampleIndex";
- spirv << ";";
- spirv << i << "__truncate $$T result __sampledType(T) %sampled;";
- return spirv.produceString();
- };
-
- sb << i << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- writeFunc(
- "T",
- "Load",
- cat("int", loadCoordCount, " location", isMultisample ? ", int sampleIndex" : ""),
- isMultisample ? cat("$c", glslFuncName, "($0, $1, $2)$z")
- : needsMipLevel ? cat(
- "$c",
- glslFuncName,
- "($0, ($1).",
- kGLSLLoadCoordsSwizzle[loadCoordCount],
- ", ($1).",
- kGLSLLoadLODSwizzle[loadCoordCount],
- ")$z")
- : cat("$c", glslFuncName, "($0, $1)$z"),
- getSpirvIntrinsic(isMultisample, false),
- cudaBuilder
- );
-
- glslFuncName = (access == SLANG_RESOURCE_ACCESS_READ) ? "texelFetchOffset" : "imageLoad";
- sb << i << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- writeFunc(
- "T",
- "Load",
- cat(
- "int", loadCoordCount, " location",
- isMultisample ? ", int sampleIndex" : "",
- ", constexpr int", base.coordCount, " offset"
- ),
- isMultisample ? cat("$c", glslFuncName, "($0, $0, $1, $2)$z")
- : needsMipLevel ? cat(
- "$c", glslFuncName, "($0, ($1).", kGLSLLoadCoordsSwizzle[loadCoordCount],
- ", ($1).", kGLSLLoadLODSwizzle[loadCoordCount],
- ", $2)$z")
- : cat("$c", glslFuncName, "($0, $1, 0, $2)$z"),
- getSpirvIntrinsic(isMultisample, true)
- );
-
- writeFunc(
- "T",
- "Load",
- cat(
- "int", loadCoordCount, " location",
- isMultisample ? ", int sampleIndex" : "",
- ", constexpr int", base.coordCount, " offset",
- ", out uint status"
- )
- );
- }
-}
-
-static String spirvReadIntrinsic(SlangResourceAccess access)
-{
- StringBuilder spirvBuilder;
- const char* i = " ";
- switch (access)
- {
- case SLANG_RESOURCE_ACCESS_NONE:
- case SLANG_RESOURCE_ACCESS_READ:
- spirvBuilder << i << "%sampled : __sampledType(T) = OpImageFetch $this $location;\n";
- spirvBuilder << i << "__truncate $$T result __sampledType(T) %sampled;";
- break;
-
- default:
- spirvBuilder << i << "%sampled : __sampledType(T) = OpImageRead $this $location;\n";
- spirvBuilder << i << "__truncate $$T result __sampledType(T) %sampled;";
- break;
- }
- return spirvBuilder;
-}
-
-static String spirvWriteIntrinsic()
-{
- StringBuilder spirvBuilder;
- const char* i = " ";
- spirvBuilder << i << "OpImageWrite $this $location $newValue;";
- return spirvBuilder;
-}
-
-void TextureTypeInfo::writeSubscriptFunctions()
-{
- TextureFlavor::Shape baseShape = base.baseShape;
- auto access = accessInfo.access;
-
- int N = base.coordCount + isArray;
-
- char const* uintNs[] = { "", "uint", "uint2", "uint3", "uint4" };
- char const* ivecNs[] = { "", "int", "ivec2", "ivec3", "ivec4" };
-
- auto uintN = uintNs[N];
- auto ivecN = ivecNs[N];
-
- // subscript operator
- sb << i << "__subscript(" << uintN << " location) -> T\n";
- BraceScope subscriptScope{i, sb};
-
- // !!!!!!!!!!!!!!!!!!!! get !!!!!!!!!!!!!!!!!!!!!!!
-
- // GLSL/SPIR-V distinguishes sampled vs. non-sampled images
- StringBuilder glslBuilder;
- {
- switch( access )
- {
- case SLANG_RESOURCE_ACCESS_NONE:
- case SLANG_RESOURCE_ACCESS_READ:
- sb << i << "__glsl_extension(GL_EXT_samplerless_texture_functions)\n";
- glslBuilder << "$ctexelFetch($0, " << ivecN << "($1)";
- if( !isMultisample )
- {
- glslBuilder << ", 0";
- }
- else
- {
- // TODO: how to handle passing through sample index?
- glslBuilder << ", 0";
- }
- break;
-
- default:
- glslBuilder << "$cimageLoad($0, " << ivecN << "($1)";
- if( isMultisample )
- {
- // TODO: how to handle passing through sample index?
- glslBuilder << ", 0";
- }
- break;
- }
- glslBuilder << ")$z";
- }
-
- // CUDA
- StringBuilder cudaBuilder;
- {
- if (access == SLANG_RESOURCE_ACCESS_READ_WRITE)
- {
- const int coordCount = base.coordCount;
- const int vecCount = coordCount + int(isArray);
-
- cudaBuilder << "surf";
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- cudaBuilder << coordCount << "D";
- }
- else
- {
- cudaBuilder << "Cubemap";
- }
-
- cudaBuilder << (isArray ? "Layered" : "");
- cudaBuilder << "read$C<$T0>($0";
-
- for (int j = 0; j < vecCount; ++j)
- {
- cudaBuilder << ", ($1)";
- if (vecCount > 1)
- {
- cudaBuilder << '.' << char(j + 'x');
- }
- // Surface access is *byte* addressed in x in CUDA
- if (j == 0)
- {
- cudaBuilder << " * $E";
- }
- }
-
- cudaBuilder << ", SLANG_CUDA_BOUNDARY_MODE)";
- }
- else if (access == SLANG_RESOURCE_ACCESS_READ)
- {
- // We can allow this on Texture1D
- if( baseShape == TextureFlavor::Shape::Shape1D && isArray == false)
- {
- cudaBuilder << "tex1Dfetch<$T0>($0, $1)";
- }
- }
- }
-
- // Output that has get
- writeFuncWithSig(
- "operator[]",
- "get",
- glslBuilder,
- spirvReadIntrinsic(access),
- cudaBuilder
- );
-
- // !!!!!!!!!!!!!!!!!!!! set !!!!!!!!!!!!!!!!!!!!!!!
-
- if (!(access == SLANG_RESOURCE_ACCESS_NONE || access == SLANG_RESOURCE_ACCESS_READ))
- {
- // CUDA
- cudaBuilder.clear();
- {
- const int coordCount = base.coordCount;
- const int vecCount = coordCount + int(isArray);
-
- cudaBuilder << "surf";
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- cudaBuilder << coordCount << "D";
- }
- else
- {
- cudaBuilder << "Cubemap";
- }
-
- cudaBuilder << (isArray ? "Layered" : "");
- cudaBuilder << "write$C<$T0>($2, $0";
- for (int j = 0; j < vecCount; ++j)
- {
- cudaBuilder << ", ($1)";
- if (vecCount > 1)
- {
- cudaBuilder << '.' << char(j + 'x');
- }
-
- // Surface access is *byte* addressed in x in CUDA
- if (j == 0)
- {
- cudaBuilder << " * $E";
- }
- }
-
- cudaBuilder << ", SLANG_CUDA_BOUNDARY_MODE)";
- }
-
- // Set
- sb << i << "[nonmutating]\n";
- writeFuncWithSig(
- "operator[]",
- "set(T newValue)",
- cat("imageStore($0, ", ivecN, "($1), $V2)"),
- spirvWriteIntrinsic(),
- cudaBuilder
- );
- }
-
- // !!!!!!!!!!!!!!!!!! ref !!!!!!!!!!!!!!!!!!!!!!!!!
-
- // Depending on the access level of the texture type,
- // we either have just a getter (the default), or both
- // a getter and setter.
- switch( access )
- {
- case SLANG_RESOURCE_ACCESS_NONE:
- case SLANG_RESOURCE_ACCESS_READ:
- break;
- default:
- sb << i << "__intrinsic_op(" << int(kIROp_ImageSubscript) << ") ref;\n";
- break;
- }
-}
-
-static String cudaSampleIntrinsic(const bool isArray, const BaseTextureShapeInfo& base, bool sampleLevel)
-{
- StringBuilder cudaBuilder;
-
- TextureFlavor::Shape baseShape = base.baseShape;
- const int coordCount = base.coordCount;
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- cudaBuilder << "tex" << coordCount << "D";
- if (isArray)
- cudaBuilder << "Layered";
- if(sampleLevel)
- cudaBuilder << "Lod";
- cudaBuilder << "<$T0>($0";
- for (int i = 0; i < coordCount; ++i)
- {
- cudaBuilder << ", ($2)";
- cudaBuilder << '.' << "xyzw"[i];
- }
- if (isArray)
- cudaBuilder << ", int(($2)." << char(coordCount + 'x') << ")";
- if(sampleLevel)
- cudaBuilder << ", $3";
- cudaBuilder << ")";
- }
- else
- {
- cudaBuilder << "texCubemap";
- if (isArray)
- cudaBuilder << "Layered";
- if(sampleLevel)
- cudaBuilder << "Lod";
- cudaBuilder << "<$T0>($0, ($2).x, ($2).y, ($2).z";
- if (isArray)
- cudaBuilder << ", int(($2).w)";
- if(sampleLevel)
- cudaBuilder << ", $3";
- cudaBuilder << ")";
- }
-
- return cudaBuilder;
-}
-
-const char* noBias = nullptr;
-const char* noLodLevel = nullptr;
-const char* noGradX = nullptr;
-const char* noGradY = nullptr;
-const char* noConstOffset = nullptr;
-const char* noMinLod = nullptr;
-
-static String spirvSampleIntrinsic(
- const TextureTypePrefixInfo& prefixInfo,
- const char* bias = nullptr,
- const char* lodLevel = nullptr,
- const char* gradX = nullptr,
- const char* gradY = nullptr,
- const char* constOffset = nullptr,
- const char* minLod = nullptr)
-{
- StringBuilder spirvBuilder;
- const char* i = " ";
-
- SLANG_ASSERT(!(!gradX ^ !gradY));
-
- if(minLod)
- spirvBuilder << i << "OpCapability MinLod;\n";
-
- const char* sampledImage;
- if(prefixInfo.combined)
- {
- sampledImage = "$this";
- }
- else
- {
- const char* sampledImageType = "%sampledImageType";
- sampledImage = "%sampledImage";
- spirvBuilder << i << sampledImageType << " = OpTypeSampledImage $$This;\n";
- spirvBuilder << i << sampledImage << " : " << sampledImageType << " = OpSampledImage $this $s;\n";
- }
-
- const char* op = lodLevel || gradX ? "OpImageSampleExplicitLod" : "OpImageSampleImplicitLod";
- spirvBuilder << i << "%sampled : __sampledType(T) = " << op << " " << sampledImage << " $location";
- spirvBuilder << " None";
- if(bias)
- spirvBuilder << "|Bias";
- if(lodLevel)
- spirvBuilder << "|Lod";
- if(gradX)
- spirvBuilder << "|Grad";
- if(constOffset)
- spirvBuilder << "|ConstOffset";
- if(minLod)
- spirvBuilder << "|MinLod";
-
- if(bias)
- spirvBuilder << " $" << bias;
- if(lodLevel)
- spirvBuilder << " $" << lodLevel;
- if(gradX)
- spirvBuilder << " $" << gradX << " $" << gradY;
- if(constOffset)
- spirvBuilder << " $" << constOffset;
- if(minLod)
- spirvBuilder << " $" << minLod;
- spirvBuilder << ";\n";
- spirvBuilder << i << "__truncate $$T result __sampledType(T) %sampled;\n";
- return spirvBuilder;
-}
-
-void TextureTypeInfo::writeSampleFunctions()
-{
- TextureFlavor::Shape baseShape = base.baseShape;
- char const* samplerStateParam = prefixInfo.combined ? "" : "SamplerState s, ";
- char const* comparisonSamplerStateParam = prefixInfo.combined ? "" : "SamplerComparisonState s, ";
- // `Sample()`
-
- writeFunc(
- "T",
- "Sample",
- cat(samplerStateParam, "float", base.coordCount + isArray, " location"),
- "$ctexture($p, $2)$z",
- spirvSampleIntrinsic(prefixInfo),
- cudaSampleIntrinsic(isArray, base, false)
- );
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- writeFunc(
- "T",
- "Sample",
- cat(samplerStateParam, "float", base.coordCount + isArray, " location, ", "constexpr int", base.coordCount, " offset"),
- "$ctextureOffset($p, $2, $3)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, noLodLevel, noGradX, noGradY, "offset")
- );
- }
-
- writeFunc(
- "T",
- "Sample",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- baseShape == TextureFlavor::Shape::ShapeCube ? "" : cat("constexpr int", base.coordCount, " offset, "),
- "float clamp"
- ),
- "",
- spirvSampleIntrinsic(
- prefixInfo,
- noBias,
- noLodLevel,
- noGradX,
- noGradY,
- baseShape == TextureFlavor::Shape::ShapeCube ? nullptr : "offset",
- "clamp"
- )
- );
-
- // SPIR-V todo, use OpImageSparseSampleImplicitLod
- writeFunc(
- "T",
- "Sample",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- baseShape != TextureFlavor::Shape::ShapeCube ? cat("constexpr int", base.coordCount, " offset, ") : "",
- "float clamp, out uint status"
- )
- );
-
- writeFunc(
- "T",
- "SampleBias",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float bias"
- ),
- "$ctexture($p, $2, $3)$z",
- spirvSampleIntrinsic(prefixInfo, "bias")
- );
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- writeFunc(
- "T",
- "SampleBias",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float bias, ",
- "constexpr int", base.coordCount, " offset"
- ),
- "$ctextureOffset($p, $2, $3, $4)$z",
- spirvSampleIntrinsic(prefixInfo, "bias", noLodLevel, noGradX, noGradY, "offset")
- );
- }
- int baseCoordCount = base.coordCount;
- int arrCoordCount = baseCoordCount + isArray;
- if (arrCoordCount <= 3)
- {
- // `SampleCmp()` and `SampleCmpLevelZero`
-
- writeFunc(
- "float",
- "SampleCmp",
- cat(
- comparisonSamplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float compareValue"
- ),
- cat("texture($p, vec", arrCoordCount + 1, "($2, $3))")
- );
-
- sb << "__glsl_extension(GL_EXT_texture_shadow_lod)\n";
- writeFunc(
- "float",
- "SampleCmpLevelZero",
- cat(
- comparisonSamplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float compareValue"
- ),
- cat("textureLod($p, vec", arrCoordCount + 1, "($2, $3), 0)")
- );
- }
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- // Note(tfoley): MSDN seems confused, and claims that the `offset`
- // parameter for `SampleCmp` is available for everything but 3D
- // textures, while `Sample` and `SampleBias` are consistent in
- // saying they only exclude `offset` for cube maps (which makes
- // sense). I'm going to assume the documentation for `SampleCmp`
- // is just wrong.
- writeFunc(
- "float",
- "SampleCmp",
- cat(
- comparisonSamplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float compareValue, "
- "constexpr int", base.coordCount, " offset"
- ),
- cat("textureOffset($p, vec", arrCoordCount + 1, "($2, $3), $4)")
- );
-
- sb << "__glsl_extension(GL_EXT_texture_shadow_lod)\n";
- writeFunc(
- "float",
- "SampleCmpLevelZero",
- cat(
- comparisonSamplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float compareValue, "
- "constexpr int", base.coordCount, " offset"
- ),
- cat("textureLodOffset($p, vec", arrCoordCount + 1, "($2, $3), 0, $4)")
- );
- }
-
- // TODO(JS): Not clear how to map this to CUDA, because in HLSL, the gradient is a vector based on
- // the dimension. On CUDA there is texNDGrad, but it always just takes ddx, ddy.
- // I could just assume 0 for elements not supplied, and ignore z. For now will just leave
- writeFunc(
- "T",
- "SampleGrad",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float", base.coordCount, " gradX, ",
- "float", base.coordCount, " gradY, "
- ),
- "$ctextureGrad($p, $2, $3, $4)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, noLodLevel, "gradX", "gradY")
- );
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- writeFunc(
- "T",
- "SampleGrad",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float", base.coordCount, " gradX, ",
- "float", base.coordCount, " gradY, ",
- "constexpr int", base.coordCount, " offset "
- ),
- "$ctextureGradOffset($p, $2, $3, $4, $5)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, noLodLevel, "gradX", "gradY", "offset")
- );
-
- sb << i << "__glsl_extension(GL_ARB_sparse_texture_clamp)\n";
- writeFunc(
- "T",
- "SampleGrad",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float", base.coordCount, " gradX, ",
- "float", base.coordCount, " gradY, ",
- "constexpr int", base.coordCount, " offset, ",
- "float lodClamp"
- ),
- "$ctextureGradOffsetClampARB($p, $2, $3, $4, $5, $6)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, noLodLevel, "gradX", "gradY", "offset", "lodClamp")
- );
- }
-
- // `SampleLevel`
-
- writeFunc(
- "T",
- "SampleLevel",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float level"
- ),
- "$ctextureLod($p, $2, $3)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, "level"),
- cudaSampleIntrinsic(isArray, base, true)
- );
-
- if( baseShape != TextureFlavor::Shape::ShapeCube )
- {
- writeFunc(
- "T",
- "SampleLevel",
- cat(
- samplerStateParam,
- "float", base.coordCount + isArray, " location, ",
- "float level, ",
- "constexpr int", base.coordCount, " offset"
- ),
- "$ctextureLodOffset($p, $2, $3, $4)$z",
- spirvSampleIntrinsic(prefixInfo, noBias, "level", noGradX, noGradY, "offset")
- );
- }
-}
-
-void TextureTypeInfo::writeGatherExtensions()
-{
- char const* baseName = prefixInfo.name;
- char const* baseShapeName = base.shapeName;
-
- auto access = accessInfo.access;
-
- bool isReadOnly = (access == SLANG_RESOURCE_ACCESS_READ);
-
- char const* samplerStateParam = prefixInfo.combined ? "" : "SamplerState s, ";
-
- // `Gather*()` operations are handled via an `extension` declaration,
- // because this lets us capture the element type of the texture.
- //
- // TODO: longer-term there should be something like a `TextureElementType`
- // interface, that both scalars and vectors implement, that then exposes
- // a `Scalar` associated type, and `Gather` can return `vector<T.Scalar, 4>`.
- //
- static const struct {
- char const* genericPrefix;
- char const* elementType;
- char const* outputType;
- } kGatherExtensionCases[] = {
- { "__generic<T, let N : int>", "vector<T,N>", "vector<T, 4>" },
- { "", "float", "vector<float, 4>" },
- { "", "int" , "vector<int, 4>"},
- { "", "uint", "vector<uint, 4>"},
-
- // TODO: need a case here for scalars `T`, but also
- // need to ensure that case doesn't accidentally match
- // for `T = vector<...>`, which requires actual checking
- // of constraints on generic parameters.
- };
- for(auto cc : kGatherExtensionCases)
- {
- // TODO: this should really be an `if` around the entire `Gather` logic
- if (isMultisample) break;
-
- EMIT_LINE_DIRECTIVE();
- sb << cc.genericPrefix << " __extension ";
- sb << accessInfo.name;
- sb << baseName;
- sb << baseShapeName;
- if (isArray) sb << "Array";
- sb << "<" << cc.elementType << " >";
- sb << "\n{\n";
-
- // `Gather`
- // (tricky because it returns a 4-vector of the element type
- // of the texture components...)
- //
- // TODO: is it actually correct to restrict these so that, e.g.,
- // `GatherAlpha()` isn't allowed on `Texture2D<float3>` because
- // it nominally doesn't have an alpha component?
- static const struct {
- int componentIndex;
- char const* componentName;
- } kGatherComponets[] = {
- { 0, "" },
- { 0, "Red" },
- { 1, "Green" },
- { 2, "Blue" },
- { 3, "Alpha" },
- };
- enum Cmp
- { NotCmp,
- Cmp
- };
-
- for(auto cmp : {NotCmp, Cmp})
- for(auto kk : kGatherComponets)
- {
- auto samplerOrComparisonSampler = cmp == Cmp ? "SamplerComparisonState s, " : samplerStateParam;
-
- auto componentIndex = kk.componentIndex;
- auto componentName = kk.componentName;
-
- auto outputType = cc.outputType;
-
- const auto cmpName = cmp == Cmp ? "Cmp" : "";
- const auto cmpValueParam = cmp == Cmp ? "float compareValue, " : "";
- const auto cmpValueParamEnd = cmp == Cmp ? ", float compareValue" : "";
- const auto supportsGLSL = componentIndex == 0 || cmp == NotCmp;
-
- EMIT_LINE_DIRECTIVE();
-
- if(supportsGLSL)
- {
- if(cmp == Cmp)
- sb << "__target_intrinsic(glsl, \"textureGather($p, $2, $3)\")\n";
- else
- sb << "__target_intrinsic(glsl, \"textureGather($p, $2, " << componentIndex << ")\")\n";
- }
- if (base.coordCount == 2 && cmp == NotCmp)
- {
- // Gather only works on 2D in CUDA without comparison
- // "It is based on the base type of DataType except when readMode is equal to cudaReadModeNormalizedFloat (see Texture Reference API), in which case it is always float4."
- sb << "__target_intrinsic(cuda, \"tex2Dgather<$T0>($0, ($2).x, ($2).y, " << componentIndex << ")\")\n";
- }
- if (isReadOnly)
- sb << "[__readNone]\n";
- sb << outputType << " Gather" << cmpName << componentName << "(" << samplerOrComparisonSampler;
- sb << "float" << base.coordCount + isArray << " location" << cmpValueParamEnd << ");\n";
-
- if (isReadOnly)
- sb << "[__readNone]\n";
- EMIT_LINE_DIRECTIVE();
- if(supportsGLSL)
- {
- if(cmp == Cmp)
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $2, $3, $4)\")\n";
- else
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $2, $3, " << componentIndex << ")\")\n";
- }
- sb << outputType << " Gather" << cmpName << componentName << "(" << samplerOrComparisonSampler;
- sb << "float" << base.coordCount + isArray << " location, ";
- sb << cmpValueParam;
- sb << "constexpr int" << base.coordCount << " offset);\n";
-
- if (isReadOnly)
- sb << "[__readNone]\n";
- EMIT_LINE_DIRECTIVE();
- sb << outputType << " Gather" << cmpName << componentName << "(" << samplerOrComparisonSampler;
- sb << "float" << base.coordCount + isArray << " location, ";
- sb << cmpValueParam;
- sb << "constexpr int" << base.coordCount << " offset, ";
- sb << "out uint status);\n";
-
- if (isReadOnly)
- sb << "[__readNone]\n";
- EMIT_LINE_DIRECTIVE();
- if(supportsGLSL)
- {
- if(cmp == Cmp)
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $2, $3, ivec" << base.coordCount << "[]($4, $5, $6, $7))\")\n";
- else
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $2, ivec" << base.coordCount << "[]($3, $4, $5, $6), " << componentIndex << ")\")\n";
- }
- sb << outputType << " Gather" << cmpName << componentName << "(" << samplerOrComparisonSampler;
- sb << "float" << base.coordCount + isArray << " location, ";
- sb << cmpValueParam;
- sb << "int" << base.coordCount << " offset1, ";
- sb << "int" << base.coordCount << " offset2, ";
- sb << "int" << base.coordCount << " offset3, ";
- sb << "int" << base.coordCount << " offset4);\n";
-
- if (isReadOnly)
- sb << "[__readNone]\n";
- EMIT_LINE_DIRECTIVE();
- sb << outputType << " Gather" << cmpName << componentName << "(" << samplerOrComparisonSampler;
- sb << "float" << base.coordCount + isArray << " location, ";
- sb << cmpValueParam;
- sb << "int" << base.coordCount << " offset1, ";
- sb << "int" << base.coordCount << " offset2, ";
- sb << "int" << base.coordCount << " offset3, ";
- sb << "int" << base.coordCount << " offset4, ";
- sb << "out uint status);\n";
- }
-
- EMIT_LINE_DIRECTIVE();
- sb << "\n}\n";
- }
}
}
diff --git a/source/slang/slang-stdlib-textures.h b/source/slang/slang-stdlib-textures.h
index dc2f64a41..35aed3e27 100644
--- a/source/slang/slang-stdlib-textures.h
+++ b/source/slang/slang-stdlib-textures.h
@@ -9,65 +9,49 @@ namespace Slang
static const struct BaseTextureShapeInfo {
char const* shapeName;
- TextureFlavor::Shape baseShape;
+ SlangResourceShape baseShape;
int coordCount;
} kBaseTextureShapes[] = {
- { "1D", TextureFlavor::Shape::Shape1D, 1 },
- { "2D", TextureFlavor::Shape::Shape2D, 2 },
- { "3D", TextureFlavor::Shape::Shape3D, 3 },
- { "Cube", TextureFlavor::Shape::ShapeCube,3 },
+ { "1D", SLANG_TEXTURE_1D, 1 },
+ { "2D", SLANG_TEXTURE_2D, 2 },
+ { "3D", SLANG_TEXTURE_3D, 3 },
+ { "Cube", SLANG_TEXTURE_CUBE, 3 },
};
static const struct BaseTextureAccessInfo {
- char const* name;
+ char const* name;
SlangResourceAccess access;
} kBaseTextureAccessLevels[] = {
{ "", SLANG_RESOURCE_ACCESS_READ },
{ "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
{ "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
-};
-
-static const struct TextureTypePrefixInfo
-{
- char const* name;
- bool combined;
-} kTexturePrefixes[] =
-{
- { "Texture", false },
- { "Sampler", true },
+ { "Feedback", SLANG_RESOURCE_ACCESS_FEEDBACK },
};
struct TextureTypeInfo
{
TextureTypeInfo(
- TextureTypePrefixInfo const& prefixInfo,
BaseTextureShapeInfo const& base,
bool isArray,
bool isMultisample,
bool isShadow,
- BaseTextureAccessInfo const& accessInfo,
StringBuilder& inSB,
String const& inPath);
- TextureTypePrefixInfo const& prefixInfo;
BaseTextureShapeInfo const& base;
bool isArray;
bool isMultisample;
bool isShadow;
- BaseTextureAccessInfo const& accessInfo;
StringBuilder& sb;
String path;
void emitTypeDecl();
-private:
+public:
//
// Functions for writing specific parts of a definition
//
- void writeQueryFunctions();
- void writeSubscriptFunctions();
- void writeSampleFunctions();
- void writeGatherExtensions();
+ void writeGetDimensionFunctions();
//
// More general utilities
@@ -75,7 +59,6 @@ private:
enum class ReadNoneMode
{
Never,
- IfReadOnly,
Always
};
@@ -85,17 +68,13 @@ private:
const String& cuda,
const String& spirv
);
- void writeFuncDecorations(
- const String& glsl,
- const String& cuda
- );
void writeFuncWithSig(
const char* funcName,
const String& sig,
const String& glsl = String{},
const String& spirv = String{},
const String& cuda = String{},
- const ReadNoneMode readNoneMode = ReadNoneMode::IfReadOnly
+ const ReadNoneMode readNoneMode = ReadNoneMode::Never
);
void writeFunc(
const char* returnType,
@@ -104,7 +83,7 @@ private:
const String& glsl = String{},
const String& spirv = String{},
const String& cuda = String{},
- const ReadNoneMode readNoneMode = ReadNoneMode::IfReadOnly
+ const ReadNoneMode readNoneMode = ReadNoneMode::Never
);
// A pointer to a string representing the current level of indentation
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index 5a977694a..7fbd021b1 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -304,7 +304,6 @@ namespace Slang
coreLibraryCode = StringBlob::moveCreate(sb);
}
#endif
-
return coreLibraryCode;
}
@@ -316,6 +315,7 @@ namespace Slang
const String path = getStdlibPath();
StringBuilder sb;
#include "hlsl.meta.slang.h"
+ File::writeAllText("d:\\stdlib1.txt", sb.toString());
hlslLibraryCode = StringBlob::moveCreate(sb);
}
#endif
diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp
index ed2ce048b..53a02ed87 100644
--- a/source/slang/slang-syntax.cpp
+++ b/source/slang/slang-syntax.cpp
@@ -470,6 +470,12 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return astBuilder->getOrCreate<ThisType>(declRef.declRefBase);
}
+ else if (auto typedefDecl = as<TypeDefDecl>(declRef.getDecl()))
+ {
+ if (typedefDecl->type.type)
+ return as<Type>(typedefDecl->type.type->substitute(astBuilder, SubstitutionSet(declRef)));
+ return astBuilder->getErrorType();
+ }
else
{
declRef = createDefaultSubstitutionsIfNeeded(astBuilder, nullptr, declRef);
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index 8c1108870..691e5864c 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -3813,15 +3813,31 @@ static TypeLayoutResult _createTypeLayout(
// TODO: the logic here should really be defined by the rules,
// and not at this top level...
ShaderParameterKind kind;
- switch( textureType->getAccess() )
+ if (textureType->isCombined())
{
- default:
- kind = ShaderParameterKind::MutableTexture;
- break;
+ switch (textureType->getAccess())
+ {
+ default:
+ kind = ShaderParameterKind::MutableTextureSampler;
+ break;
- case SLANG_RESOURCE_ACCESS_READ:
- kind = ShaderParameterKind::Texture;
- break;
+ case SLANG_RESOURCE_ACCESS_READ:
+ kind = ShaderParameterKind::TextureSampler;
+ break;
+ }
+ }
+ else
+ {
+ switch( textureType->getAccess() )
+ {
+ default:
+ kind = ShaderParameterKind::MutableTexture;
+ break;
+
+ case SLANG_RESOURCE_ACCESS_READ:
+ kind = ShaderParameterKind::Texture;
+ break;
+ }
}
return createSimpleTypeLayout(
@@ -3850,27 +3866,6 @@ static TypeLayoutResult _createTypeLayout(
type,
rules);
}
- else if (auto textureSamplerType = as<TextureSamplerType>(type))
- {
- // TODO: the logic here should really be defined by the rules,
- // and not at this top level...
- ShaderParameterKind kind;
- switch( textureSamplerType->getAccess() )
- {
- default:
- kind = ShaderParameterKind::MutableTextureSampler;
- break;
-
- case SLANG_RESOURCE_ACCESS_READ:
- kind = ShaderParameterKind::TextureSampler;
- break;
- }
-
- return createSimpleTypeLayout(
- rules->GetObjectLayout(kind, context.objectLayoutOptions),
- type,
- rules);
- }
// TODO: need a better way to handle this stuff...
#define CASE(TYPE, KIND) \
diff --git a/source/slang/slang-type-system-shared.cpp b/source/slang/slang-type-system-shared.cpp
index a8265de20..54e06a792 100644
--- a/source/slang/slang-type-system-shared.cpp
+++ b/source/slang/slang-type-system-shared.cpp
@@ -4,18 +4,4 @@
namespace Slang
{
- TextureFlavor TextureFlavor::create(SlangResourceShape shape, SlangResourceAccess access)
- {
- TextureFlavor rs;
- rs.flavor = uint16_t(shape | (access << 8));
- return rs;
- }
-
- TextureFlavor TextureFlavor::create(SlangResourceShape shape, SlangResourceAccess access, int flags)
- {
- SLANG_ASSERT((flags & ~int(SLANG_RESOURCE_EXT_SHAPE_MASK)) == 0);
- TextureFlavor rs;
- rs.flavor = uint16_t(shape | (access << 8) | flags);
- return rs;
- }
}
diff --git a/source/slang/slang-type-system-shared.h b/source/slang/slang-type-system-shared.h
index 4fa48d23e..1c8dd56aa 100644
--- a/source/slang/slang-type-system-shared.h
+++ b/source/slang/slang-type-system-shared.h
@@ -33,80 +33,31 @@ FOREACH_BASE_TYPE(DEFINE_BASE_TYPE)
CountOf,
};
- struct TextureFlavor
- {
- typedef TextureFlavor ThisType;
- enum
- {
- // Mask for the overall "shape" of the texture
- BaseShapeMask = SLANG_RESOURCE_BASE_SHAPE_MASK,
-
- // Flag for whether the shape has "array-ness"
- ArrayFlag = SLANG_TEXTURE_ARRAY_FLAG,
-
- // Whether or not the texture stores multiple samples per pixel
- MultisampleFlag = SLANG_TEXTURE_MULTISAMPLE_FLAG,
-
- // Whether or not this is a shadow texture
- ShadowFlag = SLANG_TEXTURE_SHADOW_FLAG,
-
- // For feedback texture
- FeedbackFlag = SLANG_TEXTURE_FEEDBACK_FLAG,
- };
-
- enum Shape : uint8_t
- {
- Shape1D = SLANG_TEXTURE_1D,
- Shape2D = SLANG_TEXTURE_2D,
- Shape3D = SLANG_TEXTURE_3D,
- ShapeCube = SLANG_TEXTURE_CUBE,
- ShapeBuffer = SLANG_TEXTURE_BUFFER,
-
- Shape1DArray = Shape1D | ArrayFlag,
- Shape2DArray = Shape2D | ArrayFlag,
- // No Shape3DArray
- ShapeCubeArray = ShapeCube | ArrayFlag,
- };
-
- enum
- {
- // This the total number of expressible flavors,
- // which is *not* to say that every expressible
- // flavor is actual valid.
- Count = 0x10000,
- };
-
- uint16_t flavor;
-
- Shape getBaseShape() const { return Shape(flavor & BaseShapeMask); }
- bool isArray() const { return (flavor & ArrayFlag) != 0; }
- bool isMultisample() const { return (flavor & MultisampleFlag) != 0; }
- bool isFeedback() const { return (flavor & FeedbackFlag) != 0; }
- bool isShadow() const { return (flavor & ShadowFlag) != 0; }
-
- SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return flavor == rhs.flavor; }
- SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- SlangResourceShape getShape() const { return SlangResourceShape(flavor & 0xFF); }
- SlangResourceAccess getAccess() const { return SlangResourceAccess((flavor >> 8) & 0xFF); }
-
- TextureFlavor() = default;
- TextureFlavor(uint32_t tag) { flavor = (uint16_t)tag; }
-
- static TextureFlavor create(SlangResourceShape shape, SlangResourceAccess access);
- static TextureFlavor create(SlangResourceShape shape, SlangResourceAccess access, int flags);
-
- static TextureFlavor create(TextureFlavor::Shape shape, SlangResourceAccess access) { return create(SlangResourceShape(shape), access); }
- static TextureFlavor create(TextureFlavor::Shape shape, SlangResourceAccess access, int flags) { return create(SlangResourceShape(shape), access, flags); }
-
- };
-
enum class SamplerStateFlavor : uint8_t
{
SamplerState,
SamplerComparisonState,
};
+ const int kStdlibResourceAccessReadOnly = 0;
+ const int kStdlibResourceAccessReadWrite = 1;
+ const int kStdlibResourceAccessRasterizerOrdered = 2;
+ const int kStdlibResourceAccessFeedback = 3;
+
+ const int kStdlibShapeIndex1D = 0;
+ const int kStdlibShapeIndex2D = 1;
+ const int kStdlibShapeIndex3D = 2;
+ const int kStdlibShapeIndexCube = 3;
+ const int kStdlibShapeIndexBuffer = 4;
+
+ const int kStdlibTextureShapeParameterIndex = 1;
+ const int kStdlibTextureIsArrayParameterIndex = 2;
+ const int kStdlibTextureIsMultisampleParameterIndex = 3;
+ const int kStdlibTextureSampleCountParameterIndex = 4;
+ const int kStdlibTextureAccessParameterIndex = 5;
+ const int kStdlibTextureIsShadowParameterIndex = 6;
+ const int kStdlibTextureIsCombinedParameterIndex = 7;
+ const int kStdlibTextureFormatParameterIndex = 8;
}
#endif
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 619b76b85..b1b52bc5c 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -546,7 +546,7 @@
</Expand>
</Type>
<Type Name="Slang::ValNodeOperand">
- <DisplayString Condition="kind==Slang::ValNodeOperandKind::ConstantValue">Const({values.intOperand})</DisplayString>
+ <DisplayString Optional="true" Condition="kind==Slang::ValNodeOperandKind::ConstantValue">Const({values.intOperand})#{_debugUID}</DisplayString>
<DisplayString Condition="kind==Slang::ValNodeOperandKind::ValNode">{*(Val*)values.nodeOperand}</DisplayString>
<DisplayString>{values.nodeOperand}</DisplayString>
<Expand>
@@ -561,6 +561,8 @@
<DisplayString Condition="astNodeType == Slang::ASTNodeType::GenericAppDeclRef">{*(Slang::GenericAppDeclRef*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::ConstantIntVal">{*(Slang::ConstantIntVal*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntVal">{*(Slang::PolynomialIntVal*)this}</DisplayString>
+ <DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValTerm">{*(Slang::PolynomialIntValTerm*)this}</DisplayString>
+ <DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValFactor">{*(Slang::PolynomialIntValFactor*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::GenericParamIntVal">{*(Slang::GenericParamIntVal*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness">{*(Slang::DeclaredSubtypeWitness*)this}</DisplayString>
<DisplayString Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness">{*(Slang::TransitiveSubtypeWitness*)this}</DisplayString>
@@ -644,6 +646,8 @@
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericAppDeclRef">(Slang::GenericAppDeclRef*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantIntVal">(Slang::ConstantIntVal*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntVal">(Slang::PolynomialIntVal*)&amp;astNodeType</ExpandedItem>
+ <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValTerm">(Slang::PolynomialIntValTerm*)&amp;astNodeType</ExpandedItem>
+ <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValFactor">(Slang::PolynomialIntValFactor*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericParamIntVal">(Slang::GenericParamIntVal*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness">(Slang::DeclaredSubtypeWitness*)&amp;astNodeType</ExpandedItem>
<ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness">(Slang::TransitiveSubtypeWitness*)&amp;astNodeType</ExpandedItem>
@@ -794,11 +798,41 @@
</Type>
<Type Name="Slang::ConstantIntVal">
+ <DisplayString Optional="true">{astNodeType,en}#{_debugUID} ({m_operands.m_buffer[1].values.intOperand} : {*(Type*)m_operands.m_buffer[0].values.nodeOperand}) </DisplayString>
<DisplayString>ConstantIntVal ({m_operands.m_buffer[1].values.intOperand} : {*(Type*)m_operands.m_buffer[0].values.nodeOperand})</DisplayString>
</Type>
- <Type Name="Slang::GenericParamIntVal">
- <DisplayString>GenericParamIntVal ({*(DeclRefBase*)m_operands.m_buffer[1].values.nodeOperand})</DisplayString>
+ <Type Name="Slang::PolynomialIntVal">
+ <DisplayString Optional="true">{astNodeType,en}#{_debugUID} </DisplayString>
+ <DisplayString>{astNodeType,en}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>m_operands.m_count</Size>
+ <ValuePointer>m_operands.m_buffer</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="Slang::PolynomialIntValTerm">
+ <DisplayString Optional="true">{astNodeType,en}#{_debugUID} </DisplayString>
+ <DisplayString>{astNodeType,en}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>m_operands.m_count</Size>
+ <ValuePointer>m_operands.m_buffer</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="Slang::PolynomialIntValFactor">
+ <DisplayString Optional="true">{astNodeType,en}#{_debugUID} </DisplayString>
+ <DisplayString>{astNodeType,en}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>m_operands.m_count</Size>
+ <ValuePointer>m_operands.m_buffer</ValuePointer>
+ </ArrayItems>
+ </Expand>
</Type>
<Type Name="Slang::BasicExpressionType">