summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-11-14 17:46:05 -0800
committerGitHub <noreply@github.com>2023-11-14 17:46:05 -0800
commit12f7237e4060388494c549623f4a640327b7ca08 (patch)
tree407c0f8d20b4ccd49ae5df57f84c8f9a310f7055 /source
parentc71b12775c8b13ea2b181e42c04b8db55b10fb2f (diff)
Add GLSL Compatibility. (#3321)
* Parse glsl buffer blocks to GLSLInterfaceBlockDecl * Parse glsl local size layout declarations * Parse (and ignore) glsl version directives * spelling * Better l-value interpretation for glsl interface blocks * Better l-value interpretation for glsl interface blocks * Add compile flag for enabling glsl * Parse and ignore precision modifiers. * Automatically import `glsl` module for compatiblity. * Complete vector and matrix types for glsl * Remove generated file from repo * Bump .gitignore * do not mark out globals as params * Synthesize entrypoint layout from global inout vars. * update test result. * Allow HLSL semantic on global variables. * Fix. * Fix test. * Fix win32 compile error. * Add more builtin input/output and texture intrinsics. * Add struct/array constructor syntax. * Skip `#extension` lines. * overide operator * for matrix/vector multiplication. * Add `matrixCompMult`. * Parse modifiers in for loop init var declr. * Add more glsl intrinsics, add stage into to var layout. * Allow `int[3] x` syntax. * Fix array type syntax. --------- Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com> Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang7
-rw-r--r--source/slang/glsl.meta.slang449
-rw-r--r--source/slang/hlsl.meta.slang2
-rw-r--r--source/slang/slang-ast-decl.h4
-rw-r--r--source/slang/slang-ast-modifier.h8
-rw-r--r--source/slang/slang-check-decl.cpp21
-rw-r--r--source/slang/slang-check-expr.cpp24
-rw-r--r--source/slang/slang-check-overload.cpp24
-rwxr-xr-xsource/slang/slang-compiler.h13
-rw-r--r--source/slang/slang-diagnostic-defs.h6
-rw-r--r--source/slang/slang-emit-glsl.cpp4
-rw-r--r--source/slang/slang-emit.cpp4
-rw-r--r--source/slang/slang-ir-inst-defs.h4
-rw-r--r--source/slang/slang-ir-insts.h8
-rw-r--r--source/slang/slang-ir-translate-glsl-global-var.cpp211
-rw-r--r--source/slang/slang-ir-translate-glsl-global-var.h17
-rw-r--r--source/slang/slang-ir.h1
-rw-r--r--source/slang/slang-lower-to-ir.cpp23
-rw-r--r--source/slang/slang-options.cpp11
-rw-r--r--source/slang/slang-parser.cpp205
-rw-r--r--source/slang/slang-preprocessor.cpp28
-rw-r--r--source/slang/slang-stdlib-textures.cpp16
-rw-r--r--source/slang/slang-stdlib-textures.h2
-rw-r--r--source/slang/slang-stdlib.cpp12
-rw-r--r--source/slang/slang-type-system-shared.h6
-rw-r--r--source/slang/slang.cpp47
26 files changed, 1092 insertions, 65 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 4dff9888d..b1437670e 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1482,9 +1482,14 @@ 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)
{
- TextureTypeInfo info(prefixInfo, shapeInfo, isArray, isMultisample, accessInfo, sb, path);
+ // 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();
}
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
new file mode 100644
index 000000000..a9518f914
--- /dev/null
+++ b/source/slang/glsl.meta.slang
@@ -0,0 +1,449 @@
+//
+// From the GLSL spec, section 4.1. 'asic Types'
+//
+
+typealias vec2 = vector<float, 2>;
+typealias vec3 = vector<float, 3>;
+typealias vec4 = vector<float, 4>;
+
+typealias dvec2 = vector<double, 2>;
+typealias dvec3 = vector<double, 3>;
+typealias dvec4 = vector<double, 4>;
+
+typealias bvec2 = vector<bool, 2>;
+typealias bvec3 = vector<bool, 3>;
+typealias bvec4 = vector<bool, 4>;
+
+typealias ivec2 = vector<int, 2>;
+typealias ivec3 = vector<int, 3>;
+typealias ivec4 = vector<int, 4>;
+
+typealias uvec2 = vector<uint, 2>;
+typealias uvec3 = vector<uint, 3>;
+typealias uvec4 = vector<uint, 4>;
+
+typealias i8vec2 = vector<int8_t, 2>;
+typealias i8vec3 = vector<int8_t, 3>;
+typealias i8vec4 = vector<int8_t, 4>;
+
+typealias u8vec2 = vector<uint8_t, 2>;
+typealias u8vec3 = vector<uint8_t, 3>;
+typealias u8vec4 = vector<uint8_t, 4>;
+
+typealias i16vec2 = vector<int16_t, 2>;
+typealias i16vec3 = vector<int16_t, 3>;
+typealias i16vec4 = vector<int16_t, 4>;
+
+typealias u16vec2 = vector<uint16_t, 2>;
+typealias u16vec3 = vector<uint16_t, 3>;
+typealias u16vec4 = vector<uint16_t, 4>;
+
+typealias i64vec2 = vector<int64_t, 2>;
+typealias i64vec3 = vector<int64_t, 3>;
+typealias i64vec4 = vector<int64_t, 4>;
+
+typealias u64vec2 = vector<uint64_t, 2>;
+typealias u64vec3 = vector<uint64_t, 3>;
+typealias u64vec4 = vector<uint64_t, 4>;
+
+typealias mat2 = matrix<float, 2, 2>;
+typealias mat3 = matrix<float, 3, 3>;
+typealias mat4 = matrix<float, 4, 4>;
+
+typealias mat2x2 = matrix<float, 2, 2>;
+typealias mat2x3 = matrix<float, 3, 2>;
+typealias mat2x4 = matrix<float, 4, 2>;
+
+typealias mat3x2 = matrix<float, 2, 3>;
+typealias mat3x3 = matrix<float, 3, 3>;
+typealias mat3x4 = matrix<float, 4, 3>;
+
+typealias mat4x2 = matrix<float, 2, 4>;
+typealias mat4x3 = matrix<float, 3, 4>;
+typealias mat4x4 = matrix<float, 4, 4>;
+
+typealias dmat2 = matrix<double, 2, 2>;
+typealias dmat3 = matrix<double, 3, 3>;
+typealias dmat4 = matrix<double, 4, 4>;
+
+typealias dmat2x2 = matrix<double, 2, 2>;
+typealias dmat2x3 = matrix<double, 3, 2>;
+typealias dmat2x4 = matrix<double, 4, 2>;
+
+typealias dmat3x2 = matrix<double, 2, 3>;
+typealias dmat3x3 = matrix<double, 3, 3>;
+typealias dmat3x4 = matrix<double, 4, 3>;
+
+typealias dmat4x2 = matrix<double, 2, 4>;
+typealias dmat4x3 = matrix<double, 3, 4>;
+typealias dmat4x4 = matrix<double, 4, 4>;
+
+typealias usampler1D = Sampler1D<uint4>;
+typealias isampler1D = Sampler1D<int4>;
+typealias sampler1D = Sampler1D<float4>;
+
+typealias usampler2D = Sampler2D<uint4>;
+typealias isampler2D = Sampler2D<int4>;
+typealias sampler2D = Sampler2D<float4>;
+
+typealias usampler3D = Sampler3D<uint4>;
+typealias isampler3D = Sampler3D<int4>;
+typealias sampler3D = Sampler3D<float4>;
+
+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 usampler2DShadow = Sampler2DShadow<uint4>;
+typealias isampler2DShadow = Sampler2DShadow<int4>;
+typealias sampler2DShadow = Sampler2DShadow<float4>;
+
+typealias usamplerCubeShadow = SamplerCubeShadow<uint4>;
+typealias isamplerCubeShadow = SamplerCubeShadow<int4>;
+typealias samplerCubeShadow = SamplerCubeShadow<float4>;
+
+typealias usampler1DArray = Sampler1DArray<uint4>;
+typealias isampler1DArray = Sampler1DArray<int4>;
+typealias sampler1DArray = Sampler1DArray<float4>;
+
+typealias usampler2DArray = Sampler2DArray<uint4>;
+typealias isampler2DArray = Sampler2DArray<int4>;
+typealias sampler2DArray = Sampler2DArray<float4>;
+
+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 usampler2DArrayShadow = Sampler2DArrayShadow<uint4>;
+typealias isampler2DArrayShadow = Sampler2DArrayShadow<int4>;
+typealias sampler2DArrayShadow = Sampler2DArrayShadow<float4>;
+
+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);
+
+[ForceInline]
+vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, int p, int lod)
+{
+ return __vectorReshape<4>(sampler.Load(int2(p, lod)));
+}
+
+[ForceInline]
+vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, ivec2 p, int lod)
+{
+ return __vectorReshape<4>(sampler.Load(int3(p, lod)));
+}
+
+[ForceInline]
+vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, ivec3 p, int lod)
+{
+ return __vectorReshape<4>(sampler.Load(int4(p, lod)));
+}
+
+[ForceInline]
+vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, ivec2 p, int lod)
+{
+ return __vectorReshape<4>(sampler.Load(int3(p, lod)));
+}
+
+[ForceInline]
+vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, ivec3 p, int lod)
+{
+ return __vectorReshape<4>(sampler.Load(int4(p, lod)));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, float p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, float2 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, float3 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCube<vector<T,N>> sampler, float3 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DShadow<vector<T,N>> sampler, float2 p)
+{
+ return sampler.SampleCmp(p.x, p.y);
+}
+
+[ForceInline]
+float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DShadow<vector<T,N>> sampler, float3 p)
+{
+ return sampler.SampleCmp(p.xy, p.z);
+}
+
+[ForceInline]
+float texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeShadow<vector<T,N>> sampler, float4 p)
+{
+ return sampler.SampleCmp(p.xyz, p.w);
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, float2 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, float3 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeArray<vector<T,N>> sampler, float4 p, float bias = 0.0)
+{
+ return __vectorReshape<4>(sampler.SampleBias(p, bias));
+}
+
+[ForceInline]
+float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArrayShadow<vector<T,N>> sampler, float3 p)
+{
+ return sampler.SampleCmp(p.xy, p.z);
+}
+
+[ForceInline]
+float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArrayShadow<vector<T,N>> sampler, float4 p)
+{
+ 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)
+{
+ 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;
+out float gl_FragDepth : SV_Depth;
+out int gl_FragStencilRef : SV_StencilRef;
+
+in uvec3 gl_GlobalInvocationID : SV_DispatchThreadID;
+in uvec3 gl_WorkGroupID : SV_GroupID;
+in uvec3 gl_LocalInvocationIndex : SV_GroupIndex;
+in uvec3 gl_LocalInvocationID : SV_GroupThreadID;
+
+// TODO: define overload for tessellation control stage.
+in int gl_InvocationID : SV_GSInstanceID;
+
+in int gl_InstanceIndex : SV_InstanceID;
+in bool gl_FrontFacing : SV_IsFrontFace;
+
+// TODO: define overload for geometry stage.
+in int gl_Layer : SV_RenderTargetArrayIndex;
+
+in int gl_SampleID : SV_SampleIndex;
+in int gl_VertexIndex : SV_VertexID;
+in int gl_ViewIndex : SV_ViewID;
+in int gl_ViewportIndex : SV_ViewportArrayIndex;
+
+
+// Override operator* behavior to compute algebric product of matrices and vectors.
+
+[OverloadRank(15)]
+[ForceInline]
+matrix<float, N, N> operator*<let N : int>(matrix<float, N, N> m1, matrix<float, N, N> m2)
+{
+ return mul(m2, m1);
+}
+
+[OverloadRank(15)]
+[ForceInline]
+matrix<half, N, N> operator*<let N : int>(matrix<half, N, N> m1, matrix<half, N, N> m2)
+{
+ return mul(m2, m1);
+}
+
+[OverloadRank(15)]
+[ForceInline]
+matrix<double, N, N> operator*<let N : int>(matrix<double, N, N> m1, matrix<double, N, N> m2)
+{
+ return mul(m2, m1);
+}
+
+[ForceInline]
+[OverloadRank(15)]
+matrix<T, R, L> operator*<T:__BuiltinFloatingPointType, let L : int, let C : int, let R : int>(matrix<T, C, L> m1, matrix<T, R, C> m2)
+{
+ return mul(m2, m1);
+}
+
+[ForceInline]
+[OverloadRank(15)]
+vector<T, R> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(vector<T, C> v, matrix<T, R, C> m)
+{
+ return mul(m, v);
+}
+
+[ForceInline]
+[OverloadRank(15)]
+vector<T, C> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(matrix<T, R, C> m, vector<T, R> v)
+{
+ return mul(v, m);
+}
+
+__intrinsic_op(mul)
+matrix<T, N, M> matrixCompMult<T:__BuiltinFloatingPointType, let N : int, let M : int>(matrix<T,N,M> left, matrix<T,N,M> right);
+
+__intrinsic_op(cmpLE)
+vector<bool, N> lessThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+__intrinsic_op(cmpLT)
+vector<bool, N> lessThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
+__intrinsic_op(cmpGT)
+vector<bool, N> greaterThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
+__intrinsic_op(cmpGE)
+vector<bool, N> greaterThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+__intrinsic_op(cmpEQ)
+vector<bool, N> equal<T, let N:int>(vector<T, N> x, vector<T, N> y);
+__intrinsic_op(cmpNE)
+vector<bool, N> notEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+
+__generic<T>
+extension vector<T, 2>
+{
+ [ForceInline] __init(vector<T, 3> bigger) { this = bigger.xy; }
+ [ForceInline] __init(vector<T, 4> bigger) { this = bigger.xy; }
+}
+
+__generic<T>
+extension vector<T, 3>
+{
+ [ForceInline] __init(vector<T, 4> bigger) { this = bigger.xyz; }
+}
+
+[ForceInline]
+[OverloadRank(15)]
+bool operator==<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return all(equal(left, right));
+}
+
+[ForceInline]
+[OverloadRank(15)]
+bool operator!=<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return any(notEqual(left, right));
+}
+
+[ForceInline]
+[OverloadRank(14)]
+bool operator==<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return all(equal(left, right));
+}
+
+[ForceInline]
+[OverloadRank(14)]
+bool operator!=<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return any(notEqual(left, right));
+}
+
+[ForceInline]
+[OverloadRank(14)]
+bool operator==<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return all(equal(left, right));
+}
+
+[ForceInline]
+[OverloadRank(14)]
+bool operator!=<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
+{
+ return any(notEqual(left, right));
+}
+
+${{{{
+for (auto type : kBaseTypes) {
+ char const* typeName = type.name;
+ if (!type.flags) continue;
+}}}}
+[ForceInline]
+[OverloadRank(15)]
+bool operator==<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
+{
+ return all(equal(left, right));
+}
+
+[ForceInline]
+[OverloadRank(15)]
+bool operator!=<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
+{
+ return any(notEqual(left, right));
+}
+${{{{
+}
+}}}}
+
+[ForceInline] int findLSB(int v) { return firstbitlow(v); }
+[ForceInline] uint findLSB(uint v) { return firstbitlow(v); }
+[ForceInline] vector<int,N> findLSB<let N:int>(vector<int,N> value)
+{
+ return firstbitlow(value);
+}
+[ForceInline] vector<uint,N> findLSB<let N:int>(vector<uint,N> value)
+{
+ return firstbitlow(value);
+}
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index e29e0c3cc..6520ab1fa 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -2457,7 +2457,7 @@ T dot(vector<T, N> x, vector<T, N> y)
__generic<T : __BuiltinFloatingPointType> vector<T,4> dst(vector<T,4> x, vector<T,4> y);
-// Given a RWByteAddressBuffer allow it to be interpretted as a RWStructuredBuffer
+// Given a RWByteAddressBuffer allow it to be interpreted as a RWStructuredBuffer
__intrinsic_op($(kIROp_GetEquivalentStructuredBuffer))
RWStructuredBuffer<T> __getEquivalentStructuredBuffer<T>(RWByteAddressBuffer b);
diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h
index 553a5c26f..e43141cad 100644
--- a/source/slang/slang-ast-decl.h
+++ b/source/slang/slang-ast-decl.h
@@ -151,6 +151,10 @@ class ClassDecl : public AggTypeDecl
SLANG_AST_CLASS(ClassDecl)
};
+class GLSLInterfaceBlockDecl : public AggTypeDecl
+{
+ SLANG_AST_CLASS(GLSLInterfaceBlockDecl);
+};
// TODO: Is it appropriate to treat an `enum` as an aggregate type?
// Most code that looks for, e.g., conformances assumes user-defined
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
index 4288017fa..9ee3fea86 100644
--- a/source/slang/slang-ast-modifier.h
+++ b/source/slang/slang-ast-modifier.h
@@ -30,7 +30,7 @@ class ExportedModifier : public Modifier { SLANG_AST_CLASS(ExportedModifier)};
class ConstExprModifier : public Modifier { SLANG_AST_CLASS(ConstExprModifier)};
class GloballyCoherentModifier : public Modifier { SLANG_AST_CLASS(GloballyCoherentModifier)};
class ExternCppModifier : public Modifier { SLANG_AST_CLASS(ExternCppModifier)};
-
+class GLSLPrecisionModifier : public Modifier { SLANG_AST_CLASS(GLSLPrecisionModifier)};
// Marks that the definition of a decl is not yet synthesized.
class ToBeSynthesizedModifier : public Modifier {SLANG_AST_CLASS(ToBeSynthesizedModifier)};
@@ -765,6 +765,12 @@ class DisableArrayFlatteningAttribute : public Attribute
SLANG_AST_CLASS(DisableArrayFlatteningAttribute);
};
+// A GLSL layout(local_size_x = 64, ... attribute)
+class GLSLLayoutLocalSizeAttribute : public Attribute
+{
+ SLANG_AST_CLASS(GLSLLayoutLocalSizeAttribute)
+};
+
// TODO: for attributes that take arguments, the syntax node
// classes should provide accessors for the values of those arguments.
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 8d7337318..c31c94a85 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -389,6 +389,11 @@ namespace Slang
//
if(decl->hasModifier<HLSLStaticModifier>()) return false;
+ // While not normally allowed, out variables are not constant
+ // parameters, this can happen for example in GLSL mode
+ if(decl->hasModifier<OutModifier>()) return false;
+ if(decl->hasModifier<InModifier>()) return false;
+
// The `groupshared` modifier indicates that a variable cannot
// be a shader parameters, but is instead transient storage
// allocated for the duration of a thread-group's execution.
@@ -1219,6 +1224,22 @@ namespace Slang
varDecl->type.type = m_astBuilder->getConstantBufferType(varDecl->type);
}
}
+
+ if (getLinkage()->getAllowGLSLInput())
+ {
+ // If we are in GLSL compatiblity mode, we want to treat all global variables
+ // without any `uniform` modifiers as true global variables by default.
+ if (!varDecl->findModifier<HLSLUniformModifier>() &&
+ !varDecl->findModifier<InModifier>() &&
+ !varDecl->findModifier<OutModifier>())
+ {
+ if (!as<ResourceType>(varDecl->type) && !as<PointerLikeType>(varDecl->type))
+ {
+ auto staticModifier = m_astBuilder->create<HLSLStaticModifier>();
+ addModifier(varDecl, staticModifier);
+ }
+ }
+ }
}
}
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 2f8b28afc..e130275bb 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -269,6 +269,25 @@ namespace Slang
}
}
+ static bool isMutableGLSLBufferBlockVarExpr(Expr* expr)
+ {
+ if(const auto varExpr = as<VarExpr>(expr))
+ {
+ if(const auto declRefType = as<DeclRefType>(varExpr->type->getCanonicalType()))
+ {
+ if(declRefType->getDeclRef().getDecl()->isDerivedFrom(ASTNodeType::GLSLInterfaceBlockDecl))
+ {
+ const auto d = varExpr->declRef.getDecl();
+ if(d->hasModifier<GLSLBufferModifier>() && !d->hasModifier<GLSLReadOnlyModifier>())
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
DeclRefExpr* SemanticsVisitor::ConstructDeclRefExpr(
DeclRef<Decl> declRef,
Expr* baseExpr,
@@ -370,7 +389,10 @@ namespace Slang
// l-value status of the base expression into account now.
if(!baseExpr->type.isLeftValue)
{
- expr->type.isLeftValue = false;
+ // One exception to this is if we're reading the contents
+ // of a GLSL buffer interface block which isn't marked as
+ // read_only
+ expr->type.isLeftValue = isMutableGLSLBufferBlockVarExpr(baseExpr);
}
else
{
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp
index 27062fc0c..2d7315cd2 100644
--- a/source/slang/slang-check-overload.cpp
+++ b/source/slang/slang-check-overload.cpp
@@ -2005,13 +2005,25 @@ namespace Slang
typeCheckingCache->resolvedOperatorOverloadCache[key] = *context.bestCandidate;
return CompleteOverloadCandidate(context, *context.bestCandidate);
}
- else
+ else if (auto typetype = as<TypeType>(funcExprType))
{
- // Nothing at all was found that we could even consider invoking
- getSink()->diagnose(expr->functionExpr, Diagnostics::expectedFunction, funcExprType);
- expr->type = QualType(m_astBuilder->getErrorType());
- return expr;
- }
+ // We allow a special case when `funcExpr` represents a composite type,
+ // in which case we will try to construct the type via memberwise assignment from the arguments.
+ //
+ auto initListExpr = m_astBuilder->create<InitializerListExpr>();
+ initListExpr->loc = expr->loc;
+ initListExpr->args.addRange(expr->arguments);
+ initListExpr->type = m_astBuilder->getInitializerListType();
+ Expr* outExpr = nullptr;
+ if (_coerceInitializerList(typetype->getType(), &outExpr, initListExpr))
+ return outExpr;
+ }
+
+ // Nothing at all was found that we could even consider invoking.
+ // In all other cases, this is an error.
+ getSink()->diagnose(expr->functionExpr, Diagnostics::expectedFunction, funcExprType);
+ expr->type = QualType(m_astBuilder->getErrorType());
+ return expr;
}
void SemanticsVisitor::AddGenericOverloadCandidate(
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index c3f2d8e70..e8c624b01 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1812,6 +1812,14 @@ namespace Slang
{
m_enableEffectAnnotations = value;
}
+ bool getAllowGLSLInput()
+ {
+ return m_allowGLSLInput;
+ }
+ void setAllowGLSLInput(bool value)
+ {
+ m_allowGLSLInput = value;
+ }
// Information on the targets we are being asked to
// generate code for.
@@ -1972,6 +1980,7 @@ namespace Slang
bool m_requireCacheFileSystem = false;
bool m_useFalcorCustomSharedKeywordSemantics = false;
bool m_enableEffectAnnotations = false;
+ bool m_allowGLSLInput = false;
// Modules that have been read in with the -r option
List<ComPtr<IArtifact>> m_libModules;
@@ -2641,6 +2650,7 @@ namespace Slang
virtual SLANG_NO_THROW SlangResult SLANG_MCALL setGlobalGenericArgs(int genericArgCount, char const** genericArgs) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForGlobalExistentialTypeParam(int slotIndex, char const* typeName) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForEntryPointExistentialTypeParam(int entryPointIndex, int slotIndex, char const* typeName) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW void SLANG_MCALL setAllowGLSLInput(bool value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile() SLANG_OVERRIDE;
virtual SLANG_NO_THROW char const* SLANG_MCALL getDiagnosticOutput() SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getDiagnosticOutputBlob(ISlangBlob** outBlob) SLANG_OVERRIDE;
@@ -3055,7 +3065,7 @@ namespace Slang
ComPtr<ISlangBlob> coreLibraryCode;
//ComPtr<ISlangBlob> slangLibraryCode;
ComPtr<ISlangBlob> hlslLibraryCode;
- //ComPtr<ISlangBlob> glslLibraryCode;
+ ComPtr<ISlangBlob> glslLibraryCode;
ComPtr<ISlangBlob> autodiffLibraryCode;
String getStdlibPath();
@@ -3063,6 +3073,7 @@ namespace Slang
ComPtr<ISlangBlob> getCoreLibraryCode();
ComPtr<ISlangBlob> getHLSLLibraryCode();
ComPtr<ISlangBlob> getAutodiffLibraryCode();
+ ComPtr<ISlangBlob> getGLSLLibraryCode();
RefPtr<SharedASTBuilder> m_sharedASTBuilder;
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 58a2fbf4a..75308c829 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -66,7 +66,7 @@ DIAGNOSTIC( 8, Error, outputPathsImplyDifferentFormats,
"the output paths '$0' and '$1' require different code-generation targets")
DIAGNOSTIC( 10, Error, explicitOutputPathsAndMultipleTargets, "canot use both explicit output paths ('-o') and multiple targets ('-target')")
-DIAGNOSTIC( 11, Error, glslIsNotSupported, "the Slang compiler does not support GLSL as a source language")
+DIAGNOSTIC( 11, Error, glslIsNotSupported, "the Slang compiler does not support GLSL as a source language by default, please use -allow-glsl")
DIAGNOSTIC( 12, Error, cannotDeduceSourceLanguage, "can't deduce language for input file '$0'")
DIAGNOSTIC( 13, Error, unknownCodeGenerationTarget, "unknown code generation target '$0'")
DIAGNOSTIC( 14, Error, unknownProfile, "unknown profile '$0'")
@@ -173,6 +173,7 @@ DIAGNOSTIC(15202, Error, divideByZeroInPreprocessorExpression, "division by zero
DIAGNOSTIC(15203, Error, expectedTokenInDefinedExpression, "expected '$0' in 'defined' expression")
DIAGNOSTIC(15204, Warning, directiveExpectsExpression, "'$0' directive requires an expression")
DIAGNOSTIC(15205, Warning, undefinedIdentifierInPreprocessorExpression, "undefined identifier '$0' in preprocessor expression will evaluate to zero")
+DIAGNOSTIC(15206, Error, expectedIntegralVersionNumber, "Expected integer for #version number")
DIAGNOSTIC(-1, Note, seeOpeningToken, "see opening '$0'")
@@ -741,6 +742,9 @@ DIAGNOSTIC(55102, Error, invalidTorchKernelParamType, "'$0' is not a valid param
DIAGNOSTIC(56001, Error, unableToAutoMapCUDATypeToHostType, "Could not automatically map '$0' to a host type. Automatic binding generation failed for '$1'")
DIAGNOSTIC(57001, Warning, spirvOptFailed, "spirv-opt failed. $0")
+
+// GLSL Compatibility
+DIAGNOSTIC(58001, Error, entryPointMustReturnVoidWhenGlobalOutputPresent, "entry point must return 'void' when global output variables are present.")
//
// 8xxxx - Issues specific to a particular library/technology/platform/etc.
//
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index ccb296e84..4a75e84a0 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -732,6 +732,10 @@ void GLSLSourceEmitter::_emitGLSLTextureOrTextureSamplerType(IRTextureTypeBase*
{
m_writer->emit("Array");
}
+ if (type->isShadow())
+ {
+ m_writer->emit("Shadow");
+ }
}
void GLSLSourceEmitter::_emitGLSLTypePrefix(IRType* type, bool promoteHalfToFloat)
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index ce982a58c..1ee5ba67c 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -64,6 +64,7 @@
#include "slang-ir-wrap-structured-buffers.h"
#include "slang-ir-liveness.h"
#include "slang-ir-glsl-liveness.h"
+#include "slang-ir-translate-glsl-global-var.h"
#include "slang-ir-legalize-uniform-buffer-load.h"
#include "slang-ir-lower-buffer-element-type.h"
#include "slang-ir-string-hash.h"
@@ -231,6 +232,7 @@ Result linkAndOptimizeIR(
dumpIRIfEnabled(codeGenContext, irModule, "LINKED");
#endif
+
validateIRModuleIfEnabled(codeGenContext, irModule);
// If the user specified the flag that they want us to dump
@@ -238,6 +240,8 @@ Result linkAndOptimizeIR(
// un-specialized IR.
dumpIRIfEnabled(codeGenContext, irModule);
+ translateGLSLGlobalVar(codeGenContext, irModule);
+
// Replace any global constants with their values.
//
replaceGlobalConstants(irModule);
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index e32f0d084..8f87d23e7 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -823,6 +823,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
/// A call to the decorated function should always be folded into its use site.
INST(AlwaysFoldIntoUseSiteDecoration, alwaysFold, 0, 0)
+ INST(GlobalOutputDecoration, output, 0, 0)
+ INST(GlobalInputDecoration, output, 0, 0)
+ INST(GLSLLocationDecoration, glslLocation, 1, 0)
INST(PayloadDecoration, payload, 0, 0)
/* Mesh Shader outputs */
@@ -832,7 +835,6 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST_RANGE(MeshOutputDecoration, VerticesDecoration, PrimitivesDecoration)
INST(HLSLMeshPayloadDecoration, payload, 0, 0)
INST(GLSLPrimitivesRateDecoration, perprimitive, 0, 0)
-
// Marks an inst that represents the gl_Position output.
INST(GLPositionOutputDecoration, PositionOutput, 0, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index a2662d53f..2869f7058 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -361,6 +361,14 @@ IR_SIMPLE_DECORATION(AlwaysFoldIntoUseSiteDecoration)
IR_SIMPLE_DECORATION(StaticRequirementDecoration)
IR_SIMPLE_DECORATION(NonCopyableTypeDecoration)
IR_SIMPLE_DECORATION(HLSLMeshPayloadDecoration)
+IR_SIMPLE_DECORATION(GlobalInputDecoration)
+IR_SIMPLE_DECORATION(GlobalOutputDecoration)
+
+struct IRGLSLLocationDecoration : IRDecoration
+{
+ IR_LEAF_ISA(GLSLLocationDecoration)
+ IRIntLit* getLocation() { return cast<IRIntLit>(getOperand(0)); }
+};
struct IRNVAPIMagicDecoration : IRDecoration
{
diff --git a/source/slang/slang-ir-translate-glsl-global-var.cpp b/source/slang/slang-ir-translate-glsl-global-var.cpp
new file mode 100644
index 000000000..41005e9d4
--- /dev/null
+++ b/source/slang/slang-ir-translate-glsl-global-var.cpp
@@ -0,0 +1,211 @@
+#include "slang-ir-translate-glsl-global-var.h"
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
+
+namespace Slang
+{
+ struct GlobalVarTranslationContext
+ {
+ CodeGenContext* context;
+
+ void processModule(IRModule* module)
+ {
+ List<IRInst*> outputVars;
+ List<IRInst*> inputVars;
+ List<IRInst*> entryPoints;
+ for (auto inst : module->getGlobalInsts())
+ {
+ if (inst->findDecoration<IRGlobalOutputDecoration>())
+ outputVars.add(inst);
+ if (inst->findDecoration<IRGlobalInputDecoration>())
+ inputVars.add(inst);
+ if (inst->findDecoration<IREntryPointDecoration>())
+ entryPoints.add(inst);
+ }
+
+ IRBuilder builder(module);
+
+ bool hasInput = inputVars.getCount() != 0;
+ bool hasOutput = outputVars.getCount() != 0;
+
+ if (!hasInput && !hasOutput)
+ return;
+
+ for (auto entryPoint : entryPoints)
+ {
+ auto entryPointFunc = as<IRFunc>(entryPoint);
+ if (!entryPointFunc)
+ continue;
+
+ auto entryPointDecor = entryPointFunc->findDecoration<IREntryPointDecoration>();
+
+ IRVarLayout* resultVarLayout = nullptr;
+ IRVarLayout* paramLayout = nullptr;
+ IRType* resultType = entryPointFunc->getResultType();
+
+ // Create a struct type to receive all inputs.
+ builder.setInsertBefore(entryPointFunc);
+ auto inputStructType = builder.createStructType();
+ IRStructTypeLayout::Builder inputStructTypeLayoutBuilder(&builder);
+ UInt inputVarIndex = 0;
+ List<IRStructKey*> inputKeys;
+ for (auto input : inputVars)
+ {
+ auto inputType = cast<IRPtrTypeBase>(input->getDataType())->getValueType();
+ auto key = builder.createStructKey();
+ inputKeys.add(key);
+ if (auto nameHint = input->findDecoration<IRNameHintDecoration>())
+ {
+ builder.addNameHintDecoration(key, nameHint->getName());
+ }
+ builder.createStructField(inputStructType, key, inputType);
+ IRTypeLayout::Builder fieldTypeLayout(&builder);
+ fieldTypeLayout.addResourceUsage(LayoutResourceKind::VaryingInput, LayoutSize(1));
+ IRVarLayout::Builder varLayoutBuilder(&builder, fieldTypeLayout.build());
+ varLayoutBuilder.setStage(entryPointDecor->getProfile().getStage());
+ if (auto locationDecoration = input->findDecoration<IRGLSLLocationDecoration>())
+ {
+ varLayoutBuilder.findOrAddResourceInfo(LayoutResourceKind::VaryingInput)->offset = (UInt)getIntVal(locationDecoration->getLocation());
+ }
+ if (auto semanticDecor = input->findDecoration<IRSemanticDecoration>())
+ {
+ varLayoutBuilder.setSystemValueSemantic(semanticDecor->getSemanticName(), semanticDecor->getSemanticIndex());
+ }
+ else
+ {
+ if (entryPointDecor->getProfile().getStage() == Stage::Fragment)
+ {
+ varLayoutBuilder.setUserSemantic("COLOR", inputVarIndex);
+ }
+ else if (entryPointDecor->getProfile().getStage() == Stage::Vertex)
+ {
+ varLayoutBuilder.setUserSemantic("VERTEX_IN_", inputVarIndex);
+ }
+ inputVarIndex++;
+ }
+ inputStructTypeLayoutBuilder.addField(key, varLayoutBuilder.build());
+ }
+ auto paramTypeLayout = inputStructTypeLayoutBuilder.build();
+ IRVarLayout::Builder paramVarLayoutBuilder(&builder, paramTypeLayout);
+ paramLayout = paramVarLayoutBuilder.build();
+
+ // Add an entry point parameter for all the inputs.
+ auto firstBlock = entryPointFunc->getFirstBlock();
+ builder.setInsertInto(firstBlock);
+ auto inputParam = builder.emitParam(inputStructType);
+ builder.addLayoutDecoration(inputParam, paramLayout);
+
+ // Initialize all global variables.
+ for (Index i = 0; i < inputVars.getCount(); i++)
+ {
+ auto input = inputVars[i];
+ setInsertBeforeOrdinaryInst(&builder, firstBlock->getFirstOrdinaryInst());
+ auto inputType = cast<IRPtrTypeBase>(input->getDataType())->getValueType();
+ builder.emitStore(input,
+ builder.emitFieldExtract(inputType, inputParam, inputKeys[i]));
+ }
+
+ // For each entry point, introduce a new parameter to represent each input parameter,
+ // and return all outputs via a struct value.
+ if (hasOutput)
+ {
+ // If we have global outputs, the entry-point must not return anything itself.
+ if (as<IRFuncType>(entryPoint->getDataType())->getResultType()->getOp() != kIROp_VoidType)
+ {
+ context->getSink()->diagnose(entryPointFunc, Diagnostics::entryPointMustReturnVoidWhenGlobalOutputPresent);
+ continue;
+ }
+ builder.setInsertBefore(entryPointFunc);
+ resultType = builder.createStructType();
+ IRStructTypeLayout::Builder typeLayoutBuilder(&builder);
+ UInt outputVarIndex = 0;
+ for (auto output : outputVars)
+ {
+ auto key = builder.createStructKey();
+ if (auto nameHint = output->findDecoration<IRNameHintDecoration>())
+ {
+ builder.addNameHintDecoration(key, nameHint->getName());
+ }
+ auto ptrType = as<IRPtrTypeBase>(output->getDataType());
+ builder.createStructField(resultType, key, ptrType->getValueType());
+ IRTypeLayout::Builder fieldTypeLayout(&builder);
+ fieldTypeLayout.addResourceUsage(LayoutResourceKind::VaryingOutput, LayoutSize(1));
+ IRVarLayout::Builder varLayoutBuilder(&builder, fieldTypeLayout.build());
+ varLayoutBuilder.setStage(entryPointDecor->getProfile().getStage());
+ if (auto semanticDecor = output->findDecoration<IRSemanticDecoration>())
+ {
+ varLayoutBuilder.setSystemValueSemantic(semanticDecor->getSemanticName(), semanticDecor->getSemanticIndex());
+ }
+ else
+ {
+ if (auto locationDecoration = output->findDecoration<IRGLSLLocationDecoration>())
+ {
+ varLayoutBuilder.findOrAddResourceInfo(LayoutResourceKind::VaryingOutput)->offset = (UInt)getIntVal(locationDecoration->getLocation());
+ }
+ if (entryPointDecor->getProfile().getStage() == Stage::Fragment)
+ {
+ varLayoutBuilder.setSystemValueSemantic("SV_TARGET", outputVarIndex);
+ }
+ else if (entryPointDecor->getProfile().getStage() == Stage::Vertex)
+ {
+ varLayoutBuilder.setUserSemantic("COLOR", outputVarIndex);
+ }
+ outputVarIndex++;
+ }
+ typeLayoutBuilder.addField(key, varLayoutBuilder.build());
+ }
+ auto resultTypeLayout = typeLayoutBuilder.build();
+ IRVarLayout::Builder resultVarLayoutBuilder(&builder, resultTypeLayout);
+ resultVarLayout = resultVarLayoutBuilder.build();
+
+ for (auto block : entryPointFunc->getBlocks())
+ {
+ if (auto returnInst = as<IRReturn>(block->getTerminator()))
+ {
+ // Return the struct value.
+ builder.setInsertBefore(returnInst);
+ List<IRInst*> fieldVals;
+ for (auto outputVar : outputVars)
+ {
+ auto load = builder.emitLoad(outputVar);
+ fieldVals.add(load);
+ }
+ auto resultVal = builder.emitMakeStruct(resultType, (UInt)fieldVals.getCount(), fieldVals.getBuffer());
+ builder.emitReturn(resultVal);
+ returnInst->removeAndDeallocate();
+ }
+ }
+ }
+ if (auto entryPointLayoutDecor = entryPointFunc->findDecoration<IRLayoutDecoration>())
+ {
+ if (auto entryPointLayout = as<IREntryPointLayout>(entryPointLayoutDecor->getLayout()))
+ {
+ if (paramLayout)
+ builder.replaceOperand(entryPointLayout->getOperands(), paramLayout);
+ if (resultVarLayout)
+ builder.replaceOperand(entryPointLayout->getOperands() + 1, resultVarLayout);
+ }
+
+ }
+ // Update func type for the entry point.
+ List<IRType*> paramTypes;
+ for (auto param : entryPointFunc->getParams())
+ {
+ paramTypes.add(param->getDataType());
+ }
+ IRType* newFuncType = builder.getFuncType(paramTypes, resultType);
+ entryPointFunc->setFullType(newFuncType);
+ }
+ }
+ };
+
+ void translateGLSLGlobalVar(CodeGenContext* context, IRModule* module)
+ {
+
+ GlobalVarTranslationContext ctx;
+ ctx.context = context;
+ ctx.processModule(module);
+ }
+}
diff --git a/source/slang/slang-ir-translate-glsl-global-var.h b/source/slang/slang-ir-translate-glsl-global-var.h
new file mode 100644
index 000000000..f22b6c028
--- /dev/null
+++ b/source/slang/slang-ir-translate-glsl-global-var.h
@@ -0,0 +1,17 @@
+// slang-ir-translate-glsl-global-var.h
+#ifndef SLANG_IR_TRANSLATE_GLSL_GLOBAL_VAR_H
+#define SLANG_IR_TRANSLATE_GLSL_GLOBAL_VAR_H
+
+namespace Slang
+{
+
+ struct IRModule;
+ struct CodeGenContext;
+
+ /// Translate global in/out variables defined in GLSL-flavored code
+ /// into entry point parameters with system value semantics.
+ void translateGLSLGlobalVar(CodeGenContext* context, IRModule* module);
+
+}
+
+#endif // SLANG_IR_TRANSLATE_GLSL_GLOBAL_VAR_H
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 8d7cad0b4..f0be72248 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -1378,6 +1378,7 @@ struct IRResourceTypeBase : IRType
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(); }
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index b2c0dbb18..38651c5a4 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -30,7 +30,6 @@
#include "slang-ir-obfuscate-loc.h"
#include "slang-ir-use-uninitialized-out-param.h"
#include "slang-ir-peephole.h"
-
#include "slang-mangle.h"
#include "slang-type-layout.h"
#include "slang-visitor.h"
@@ -2155,7 +2154,23 @@ void addVarDecorations(
{
builder->addSimpleDecoration<IRHLSLMeshPayloadDecoration>(inst);
}
-
+ else if (as<OutModifier>(mod))
+ {
+ builder->addSimpleDecoration<IRGlobalOutputDecoration>(inst);
+ }
+ else if (as<InModifier>(mod))
+ {
+ builder->addSimpleDecoration<IRGlobalInputDecoration>(inst);
+ }
+ else if (auto glslLocationMod = as<GLSLLocationLayoutModifier>(mod))
+ {
+ builder->addDecoration(inst, kIROp_GLSLLocationDecoration,
+ builder->getIntValue(builder->getIntType(), stringToInt(glslLocationMod->valToken.getContent())));
+ }
+ else if (auto hlslSemantic = as< HLSLSimpleSemantic>(mod))
+ {
+ builder->addSemanticDecoration(inst, hlslSemantic->name.getContent());
+ }
// TODO: what are other modifiers we need to propagate through?
}
if(auto t = composeGetters<IRMeshOutputType>(inst->getFullType(), &IROutTypeBase::getValueType))
@@ -8024,6 +8039,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
irAggType = subBuilder->createClassType();
}
+ else if (as<GLSLInterfaceBlockDecl>(decl))
+ {
+ return LoweredValInfo();
+ }
else
{
getSink()->diagnose(decl->loc, Diagnostics::unimplemented, "lower unknown AggType to IR");
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 67f95df1e..1c1ad8f1c 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -141,6 +141,7 @@ enum class OptionKind
FileSystem,
Heterogeneous,
NoMangle,
+ AllowGLSL,
// Internal
@@ -621,7 +622,8 @@ void initCommandOptions(CommandOptions& options)
{ OptionKind::FileSystem, "-file-system", "-file-system <file-system-type>",
"Set the filesystem hook to use for a compile request."},
{ OptionKind::Heterogeneous, "-heterogeneous", nullptr, "Output heterogeneity-related code." },
- { OptionKind::NoMangle, "-no-mangle", nullptr, "Do as little mangling of names as possible." }
+ { OptionKind::NoMangle, "-no-mangle", nullptr, "Do as little mangling of names as possible." },
+ { OptionKind::AllowGLSL, "-allow-glsl", nullptr, "Enable GLSL as an input language." },
};
_addOptions(makeConstArrayView(experimentalOpts), options);
@@ -912,6 +914,8 @@ struct OptionsParser
String m_spirvCoreGrammarJSONPath;
+ bool m_allowGLSLInput = false;
+
CommandLineReader m_reader;
CommandOptionsWriter::Style m_helpStyle = CommandOptionsWriter::Style::Text;
@@ -1812,6 +1816,7 @@ SlangResult OptionsParser::_parse(
switch (optionKind)
{
case OptionKind::NoMangle: m_flags |= SLANG_COMPILE_FLAG_NO_MANGLING; break;
+ case OptionKind::AllowGLSL: m_allowGLSLInput = true; break;
case OptionKind::EmitIr: m_requestImpl->m_emitIr = true; break;
case OptionKind::LoadStdLib:
{
@@ -2152,7 +2157,7 @@ SlangResult OptionsParser::_parse(
m_compileRequest->setEnableEffectAnnotations(true);
break;
}
-
+
case OptionKind::EntryPointName:
{
CommandLineArg name;
@@ -2482,6 +2487,8 @@ SlangResult OptionsParser::_parse(
m_compileRequest->setCompileFlags(m_flags);
+ m_compileRequest->setAllowGLSLInput(m_allowGLSLInput);
+
// As a compatability feature, if the user didn't list any explicit entry
// point names, *and* they are compiling a single translation unit, *and* they
// have either specified a stage, or we can assume one from the naming
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 8c9604df6..0a2076fd0 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -82,6 +82,7 @@ namespace Slang
struct ParserOptions
{
bool enableEffectAnnotations = false;
+ bool allowGLSLInput = false;
};
// TODO: implement two pass parsing for file reference and struct type recognition
@@ -186,6 +187,7 @@ namespace Slang
void parseSourceFile(ModuleDecl* program);
Decl* ParseStruct();
ClassDecl* ParseClass();
+ GLSLInterfaceBlockDecl* ParseGLSLInterfaceBlock();
Stmt* ParseStatement(Stmt* parentStmt = nullptr);
Stmt* parseBlockStatement();
Stmt* parseLabelStatement();
@@ -1161,7 +1163,17 @@ namespace Slang
AddModifier(&modifierLink, parsedModifier);
continue;
}
-
+ else if (parser->options.allowGLSLInput)
+ {
+ if (AdvanceIf(parser, "flat"))
+ {
+ parsedModifier = parser->astBuilder->create<HLSLNoInterpolationModifier>();
+ parsedModifier->keywordName = nameToken.getName();
+ parsedModifier->loc = nameToken.loc;
+ AddModifier(&modifierLink, parsedModifier);
+ continue;
+ }
+ }
// If there was no match for a modifier keyword, then we
// must be at the end of the modifier sequence
return modifiers;
@@ -2135,8 +2147,34 @@ namespace Slang
memberExpr->name = expectIdentifier(parser).name;
return memberExpr;
}
+
+ // Parse optional `[]` braces after a type expression, that indicate an array type
+ static Expr* parseBracketTypeSuffix(Parser* parser, Expr* inTypeExpr)
+ {
+ auto typeExpr = inTypeExpr;
+ for (;;)
+ {
+ Token token;
+ if (parser->LookAheadToken(TokenType::LBracket))
+ {
+ IndexExpr* arrType = parser->astBuilder->create<IndexExpr>();
+ arrType->loc = typeExpr->loc;
+ arrType->baseExpression = typeExpr;
+ parser->ReadToken(TokenType::LBracket);
+ if (!parser->LookAheadToken(TokenType::RBracket))
+ {
+ arrType->indexExprs.add(parser->ParseExpression());
+ }
+ parser->ReadToken(TokenType::RBracket);
+ typeExpr = arrType;
+ }
+ else
+ break;
+ }
+ return typeExpr;
+ }
- // Parse option `[]` braces after a type expression, that indicate an array type
+ // Parse option `[]` or `*` braces after a type expression, that indicate an array or pointer type
static Expr* parsePostfixTypeSuffix(
Parser* parser,
Expr* inTypeExpr)
@@ -2400,7 +2438,7 @@ namespace Slang
}
/// Parse a type specifier, without dealing with modifiers.
- static TypeSpec _parseSimpleTypeSpec(Parser* parser)
+ static TypeSpec _parseSimpleTypeSpec(Parser* parser, bool mightBeGLSLInterfaceBlock)
{
TypeSpec typeSpec;
@@ -2436,6 +2474,15 @@ namespace Slang
typeSpec.expr = createDeclRefType(parser, decl);
return typeSpec;
}
+ else if( mightBeGLSLInterfaceBlock
+ && parser->LookAheadToken(TokenType::Identifier)
+ && parser->LookAheadToken(TokenType::LBrace,1) )
+ {
+ auto decl = parser->ParseGLSLInterfaceBlock();
+ typeSpec.decl = decl;
+ typeSpec.expr = createDeclRefType(parser, decl);
+ return typeSpec;
+ }
else if(parser->LookAheadToken("enum"))
{
auto decl = parseEnumDecl(parser);
@@ -2493,6 +2540,19 @@ namespace Slang
return typeSpec;
}
+ static bool hasPotentialGLSLInterfaceBlockModifier(Parser* parser, Modifiers& mods)
+ {
+ if (!parser->options.allowGLSLInput)
+ return false;
+
+ for (auto mod : mods)
+ {
+ if (as<GLSLBufferModifier>(mod) || as<InModifier>(mod) || as<OutModifier>(mod))
+ return true;
+ }
+ return false;
+ }
+
/// Parse a type specifier, following the given list of modifiers.
///
/// If there are any modifiers in `ioModifiers`, this function may modify it
@@ -2501,7 +2561,7 @@ namespace Slang
///
static TypeSpec _parseTypeSpec(Parser* parser, Modifiers& ioModifiers)
{
- TypeSpec typeSpec = _parseSimpleTypeSpec(parser);
+ TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, ioModifiers));
// We don't know whether `ioModifiers` has any modifiers in it,
// or which of them might be type modifiers, so we will delegate
@@ -2526,7 +2586,7 @@ namespace Slang
static TypeSpec _parseTypeSpec(Parser* parser)
{
Modifiers modifiers = ParseModifiers(parser);
- TypeSpec typeSpec = _parseSimpleTypeSpec(parser);
+ TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, modifiers));
typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers);
@@ -2549,6 +2609,7 @@ namespace Slang
return nullptr;
}
+
// We may need to build up multiple declarations in a group,
// but the common case will be when we have just a single
// declaration
@@ -2560,6 +2621,11 @@ namespace Slang
// it might declare a `struct` type.
if(typeSpec.decl)
declGroupBuilder.addDecl(typeSpec.decl);
+ else
+ {
+ // Allow using brackets directly after type name to declare an array typed variable.
+ typeSpec.expr = parseBracketTypeSuffix(parser, typeSpec.expr);
+ }
if( AdvanceIf(parser, TokenType::Semicolon) )
{
@@ -2960,12 +3026,9 @@ namespace Slang
reflectionNameModifier->nameAndLoc = NameLoc(reflectionNameToken);
addModifier(bufferVarDecl, reflectionNameModifier);
- // Both the buffer variable and its type need to have names generated
- bufferVarDecl->nameAndLoc.name = generateName(parser, "parameterGroup_" + String(reflectionNameToken.getContent()));
+ // The parameter group type need to have its name generated.
bufferDataTypeDecl->nameAndLoc.name = generateName(parser, "ParameterGroup_" + String(reflectionNameToken.getContent()));
- addModifier(bufferDataTypeDecl, parser->astBuilder->create<ImplicitParameterGroupElementTypeModifier>());
- addModifier(bufferVarDecl, parser->astBuilder->create<ImplicitParameterGroupVariableModifier>());
// TODO(tfoley): We end up constructing unchecked syntax here that
// is expected to type check into the right form, but it might be
@@ -3003,12 +3066,28 @@ namespace Slang
// The declarations in the body belong to the data type.
parseDeclBody(parser, bufferDataTypeDecl);
- // All HLSL buffer declarations are "transparent" in that their
- // members are implicitly made visible in the parent scope.
- // We achieve this by applying the transparent modifier to the variable.
- auto transparentModifier = parser->astBuilder->create<TransparentModifier>();
- transparentModifier->next = bufferVarDecl->modifiers.first;
- bufferVarDecl->modifiers.first = transparentModifier;
+ if (parser->LookAheadToken(TokenType::Identifier) &&
+ parser->LookAheadToken(TokenType::Semicolon, 1))
+ {
+ // If the user specified an explicit name of the buffer var, use it.
+ bufferVarDecl->nameAndLoc = ParseDeclName(parser);
+ parser->ReadToken(TokenType::Semicolon);
+ }
+ else
+ {
+ // Otherwise, we need to generate a name for the buffer variable.
+ bufferVarDecl->nameAndLoc.name = generateName(parser, "parameterGroup_" + String(reflectionNameToken.getContent()));
+
+ // We also need to make the declaration "transparent" so that their
+ // members are implicitly made visible in the parent scope.
+ // We achieve this by applying the transparent modifier to the variable.
+ auto transparentModifier = parser->astBuilder->create<TransparentModifier>();
+ transparentModifier->next = bufferVarDecl->modifiers.first;
+ bufferVarDecl->modifiers.first = transparentModifier;
+
+ addModifier(bufferVarDecl, parser->astBuilder->create<ImplicitParameterGroupVariableModifier>());
+ addModifier(bufferDataTypeDecl, parser->astBuilder->create<ImplicitParameterGroupElementTypeModifier>());
+ }
// Because we are constructing two declarations, we have a thorny
// issue that were are only supposed to return one.
@@ -4026,6 +4105,48 @@ namespace Slang
return nullptr;
}
+ static bool parseGLSLGlobalDecl(Parser* parser, ContainerDecl* containerDecl)
+ {
+ SLANG_UNUSED(containerDecl);
+
+ if (AdvanceIf(parser, "precision"))
+ {
+ // skip global precision declarations.
+ parser->ReadToken();
+ parser->ReadToken();
+ parser->ReadToken(TokenType::Semicolon);
+ return true;
+ }
+
+ Modifier* layoutModifier = nullptr;
+ if (parser->LookAheadToken("layout"))
+ {
+ tryParseUsingSyntaxDecl<Modifier>(parser, &layoutModifier);
+ }
+
+ DeclBase* decl = nullptr;
+ if (parser->LookAheadToken("uniform", 0) &&
+ (parser->LookAheadToken(TokenType::LBrace, 1) ||
+ parser->LookAheadToken(TokenType::Identifier, 1) &&
+ parser->LookAheadToken(TokenType::LBrace, 2)))
+ {
+ parser->ReadToken();
+ decl = as<Decl>(parseHLSLCBufferDecl(parser, containerDecl));
+ if (decl)
+ AddMember(parser->currentScope, (Decl*)decl);
+ }
+ else if (layoutModifier)
+ {
+ decl = ParseDecl(parser, containerDecl);
+ }
+
+ if (decl)
+ {
+ addModifier(decl, layoutModifier);
+ return true;
+ }
+ return false;
+ }
static void parseDecls(
Parser* parser,
@@ -4035,6 +4156,11 @@ namespace Slang
Token closingBraceToken;
while (!AdvanceIfMatch(parser, matchType, &closingBraceToken))
{
+ if (parser->options.allowGLSLInput)
+ {
+ if (parseGLSLGlobalDecl(parser, containerDecl))
+ continue;
+ }
ParseDecl(parser, containerDecl);
}
containerDecl->closingSourceLoc = closingBraceToken.loc;
@@ -4081,6 +4207,18 @@ namespace Slang
program->loc = tokenReader.peekLoc();
}
+ if (options.allowGLSLInput)
+ {
+ auto glslName = getName(this, "glsl");
+ if (program->nameAndLoc.name != glslName)
+ {
+ auto importDecl = astBuilder->create<ImportDecl>();
+ importDecl->moduleNameAndLoc.name = glslName;
+ importDecl->scope = currentScope;
+ AddMember(currentScope, importDecl);
+ }
+ }
+
parseDecls(this, program, MatchedTokenType::File);
PopScope();
@@ -4140,6 +4278,23 @@ namespace Slang
return rs;
}
+ GLSLInterfaceBlockDecl* Parser::ParseGLSLInterfaceBlock()
+ {
+ //
+ // MyBlockName { float myData[]; } myBufferName;
+ //
+
+ auto* rs = astBuilder->create<GLSLInterfaceBlockDecl>();
+ FillPosition(rs);
+
+ // As for struct, skip completion request token to prevent producing a
+ // block named completion request.
+ AdvanceIf(this, TokenType::CompletionRequest);
+ rs->nameAndLoc = expectIdentifier(this);
+ parseDeclBody(this, rs);
+ return rs;
+ }
+
static EnumCaseDecl* parseEnumCaseDecl(Parser* parser)
{
EnumCaseDecl* decl = parser->astBuilder->create<EnumCaseDecl>();
@@ -4841,9 +4996,10 @@ namespace Slang
FillPosition(stmt);
ReadToken("for");
ReadToken(TokenType::LParent);
- if (peekTypeName(this))
+ auto modifiers = ParseModifiers(this);
+ if (peekTypeName(this) || !modifiers.isEmpty())
{
- stmt->initialStatement = parseVarDeclrStatement(Modifiers());
+ stmt->initialStatement = parseVarDeclrStatement(modifiers);
}
else
{
@@ -6703,7 +6859,7 @@ namespace Slang
// If there are any modifiers, then we know that we are actually
// in the type case.
//
- auto typeSpec = _parseSimpleTypeSpec(parser);
+ auto typeSpec = _parseSimpleTypeSpec(parser, false);
typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers);
auto typeExpr = typeSpec.expr;
@@ -6742,6 +6898,7 @@ namespace Slang
{
ParserOptions options = {};
options.enableEffectAnnotations = translationUnit->compileRequest->getLinkage()->getEnableEffectAnnotations();
+ options.allowGLSLInput = translationUnit->compileRequest->getLinkage()->getAllowGLSLInput();
Parser parser(astBuilder, tokens, sink, outerScope, options);
parser.namePool = translationUnit->getNamePool();
@@ -6924,7 +7081,6 @@ namespace Slang
return modifier;
}
-
static SlangResult parseSemanticVersion(Parser* parser, Token& outToken, SemanticVersion& outVersion)
{
parser->ReadToken(TokenType::LParent);
@@ -6981,12 +7137,12 @@ namespace Slang
parser->sink->diagnose(token, Diagnostics::invalidCUDASMVersion);
return nullptr;
}
-
+
static NodeBase* parseLayoutModifier(Parser* parser, void* /*userData*/)
{
ModifierListBuilder listBuilder;
- UncheckedAttribute* numThreadsAttrib = nullptr;
+ GLSLLayoutLocalSizeAttribute* numThreadsAttrib = nullptr;
listBuilder.add(parser->astBuilder->create<GLSLLayoutModifierGroupBegin>());
@@ -7009,13 +7165,12 @@ namespace Slang
{
if (!numThreadsAttrib)
{
- numThreadsAttrib = parser->astBuilder->create<UncheckedAttribute>();
+ numThreadsAttrib = parser->astBuilder->create<GLSLLayoutLocalSizeAttribute>();
numThreadsAttrib->args.setCount(3);
// Just mark the loc and name from the first in the list
numThreadsAttrib->keywordName = getName(parser, "numthreads");
numThreadsAttrib->loc = nameAndLoc.loc;
- numThreadsAttrib->scope = parser->currentScope;
}
if (AdvanceIf(parser, TokenType::OpAssign))
@@ -7272,6 +7427,9 @@ namespace Slang
_makeParseModifier("const", ConstModifier::kReflectClassInfo),
_makeParseModifier("instance", InstanceModifier::kReflectClassInfo),
_makeParseModifier("__builtin", BuiltinModifier::kReflectClassInfo),
+ _makeParseModifier("highp", GLSLPrecisionModifier::kReflectClassInfo),
+ _makeParseModifier("lowp", GLSLPrecisionModifier::kReflectClassInfo),
+ _makeParseModifier("mediump", GLSLPrecisionModifier::kReflectClassInfo),
_makeParseModifier("__global", ActualGlobalModifier::kReflectClassInfo),
@@ -7296,6 +7454,7 @@ namespace Slang
_makeParseModifier("uniform", HLSLUniformModifier::kReflectClassInfo),
_makeParseModifier("volatile", HLSLVolatileModifier::kReflectClassInfo),
_makeParseModifier("export", HLSLExportModifier::kReflectClassInfo),
+ _makeParseModifier("buffer", GLSLBufferModifier::kReflectClassInfo),
// Modifiers for geometry shader input
_makeParseModifier("point", HLSLPointModifier::kReflectClassInfo),
diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp
index aefbf7619..02f46103b 100644
--- a/source/slang/slang-preprocessor.cpp
+++ b/source/slang/slang-preprocessor.cpp
@@ -3635,6 +3635,29 @@ static void HandlePragmaDirective(PreprocessorDirectiveContext* context)
(subDirective->callback)(context, subDirectiveToken);
}
+static void HandleExtensionDirective(PreprocessorDirectiveContext* context)
+{
+ SkipToEndOfLine(context);
+}
+
+static void HandleVersionDirective(PreprocessorDirectiveContext* context)
+{
+ [[maybe_unused]]
+ int version;
+ switch(PeekTokenType(context))
+ {
+ case TokenType::IntegerLiteral:
+ version = stringToInt(AdvanceToken(context).getContent());
+ break;
+ default:
+ GetSink(context)->diagnose(GetDirectiveLoc(context), Diagnostics::expectedIntegralVersionNumber);
+ break;
+ }
+
+ SkipToEndOfLine(context);
+ // TODO, just skip the version for now
+}
+
// Handle an invalid directive
static void HandleInvalidDirective(PreprocessorDirectiveContext* context)
{
@@ -3689,6 +3712,11 @@ static const PreprocessorDirective kDirectives[] =
{ "line", &HandleLineDirective, 0 },
{ "pragma", &HandlePragmaDirective, 0 },
+ // GLSL
+ { "version", &HandleVersionDirective, 0 },
+ { "extension", &HandleExtensionDirective, 0 },
+
+
{ nullptr, nullptr, 0 },
};
diff --git a/source/slang/slang-stdlib-textures.cpp b/source/slang/slang-stdlib-textures.cpp
index 9254bf966..98380033c 100644
--- a/source/slang/slang-stdlib-textures.cpp
+++ b/source/slang/slang-stdlib-textures.cpp
@@ -50,6 +50,7 @@ TextureTypeInfo::TextureTypeInfo(
BaseTextureShapeInfo const& base,
bool isArray,
bool isMultisample,
+ bool isShadow,
BaseTextureAccessInfo const& accessInfo,
StringBuilder& inSB,
String const& inPath)
@@ -57,6 +58,7 @@ TextureTypeInfo::TextureTypeInfo(
, base(base)
, isArray(isArray)
, isMultisample(isMultisample)
+ , isShadow(isShadow)
, accessInfo(accessInfo)
, sb(inSB)
, path(inPath)
@@ -177,7 +179,7 @@ void TextureTypeInfo::emitTypeDecl()
unsigned flavor = baseShape;
if (isArray) flavor |= TextureFlavor::ArrayFlag;
if (isMultisample) flavor |= TextureFlavor::MultisampleFlag;
- // if (isShadow) flavor |= TextureFlavor::ShadowFlag;
+ if (isShadow) flavor |= TextureFlavor::ShadowFlag;
flavor |= (access << 8);
@@ -204,7 +206,7 @@ void TextureTypeInfo::emitTypeDecl()
sb << baseShapeName;
if (isMultisample) sb << "MS";
if (isArray) sb << "Array";
- // if (isShadow) sb << "Shadow";
+ if (isShadow) sb << "Shadow";
sb << "\n";
// The struct body
@@ -988,7 +990,7 @@ void TextureTypeInfo::writeSampleFunctions()
{
TextureFlavor::Shape baseShape = base.baseShape;
char const* samplerStateParam = prefixInfo.combined ? "" : "SamplerState s, ";
-
+ char const* comparisonSamplerStateParam = prefixInfo.combined ? "" : "SamplerComparisonState s, ";
// `Sample()`
writeFunc(
@@ -1081,7 +1083,7 @@ void TextureTypeInfo::writeSampleFunctions()
"float",
"SampleCmp",
cat(
- "SamplerComparisonState s, ",
+ comparisonSamplerStateParam,
"float", base.coordCount + isArray, " location, ",
"float compareValue"
),
@@ -1093,7 +1095,7 @@ void TextureTypeInfo::writeSampleFunctions()
"float",
"SampleCmpLevelZero",
cat(
- "SamplerComparisonState s, ",
+ comparisonSamplerStateParam,
"float", base.coordCount + isArray, " location, ",
"float compareValue"
),
@@ -1113,7 +1115,7 @@ void TextureTypeInfo::writeSampleFunctions()
"float",
"SampleCmp",
cat(
- "SamplerComparisonState s, ",
+ comparisonSamplerStateParam,
"float", base.coordCount + isArray, " location, ",
"float compareValue, "
"constexpr int", base.coordCount, " offset"
@@ -1126,7 +1128,7 @@ void TextureTypeInfo::writeSampleFunctions()
"float",
"SampleCmpLevelZero",
cat(
- "SamplerComparisonState s, ",
+ comparisonSamplerStateParam,
"float", base.coordCount + isArray, " location, ",
"float compareValue, "
"constexpr int", base.coordCount, " offset"
diff --git a/source/slang/slang-stdlib-textures.h b/source/slang/slang-stdlib-textures.h
index 19008a3f0..dc2f64a41 100644
--- a/source/slang/slang-stdlib-textures.h
+++ b/source/slang/slang-stdlib-textures.h
@@ -44,6 +44,7 @@ struct TextureTypeInfo
BaseTextureShapeInfo const& base,
bool isArray,
bool isMultisample,
+ bool isShadow,
BaseTextureAccessInfo const& accessInfo,
StringBuilder& inSB,
String const& inPath);
@@ -52,6 +53,7 @@ struct TextureTypeInfo
BaseTextureShapeInfo const& base;
bool isArray;
bool isMultisample;
+ bool isShadow;
BaseTextureAccessInfo const& accessInfo;
StringBuilder& sb;
String path;
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index 5fec05c80..5a977694a 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -335,4 +335,16 @@ namespace Slang
#endif
return autodiffLibraryCode;
}
+
+ ComPtr<ISlangBlob> Session::getGLSLLibraryCode()
+ {
+ if (!glslLibraryCode)
+ {
+ const String path = getStdlibPath();
+ StringBuilder sb;
+#include "glsl.meta.slang.h"
+ glslLibraryCode = StringBlob::moveCreate(sb);
+ }
+ return glslLibraryCode;
+ }
}
diff --git a/source/slang/slang-type-system-shared.h b/source/slang/slang-type-system-shared.h
index 2e824e0a0..4fa48d23e 100644
--- a/source/slang/slang-type-system-shared.h
+++ b/source/slang/slang-type-system-shared.h
@@ -48,9 +48,7 @@ FOREACH_BASE_TYPE(DEFINE_BASE_TYPE)
MultisampleFlag = SLANG_TEXTURE_MULTISAMPLE_FLAG,
// Whether or not this is a shadow texture
- //
- // TODO(tfoley): is this even meaningful/used?
- // ShadowFlag = 0x80,
+ ShadowFlag = SLANG_TEXTURE_SHADOW_FLAG,
// For feedback texture
FeedbackFlag = SLANG_TEXTURE_FEEDBACK_FLAG,
@@ -84,7 +82,7 @@ FOREACH_BASE_TYPE(DEFINE_BASE_TYPE)
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; }
+ 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); }
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index af853102a..0331a5f8e 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -2534,22 +2534,26 @@ SlangResult FrontEndCompileRequest::executeActionsInner()
{
SLANG_AST_BUILDER_RAII(getLinkage()->getASTBuilder());
- // We currently allow GlSL files on the command line so that we can
- // drive our "pass-through" mode, but we really want to issue an error
- // message if the user is seriously asking us to compile them.
for (TranslationUnitRequest* translationUnit : translationUnits)
{
// Make sure SourceFile representation is available for all translationUnits
SLANG_RETURN_ON_FAIL(translationUnit->requireSourceFiles());
- switch(translationUnit->sourceLanguage)
+ if(!getLinkage()->getAllowGLSLInput())
{
- default:
- break;
+ // We currently allow GlSL files on the command line so that we can
+ // drive our "pass-through" mode, but we really want to issue an error
+ // message if the user is seriously asking us to compile them and
+ // doesn't explicitly opt into the glsl frontend
+ switch(translationUnit->sourceLanguage)
+ {
+ default:
+ break;
- case SourceLanguage::GLSL:
- getSink()->diagnose(SourceLoc(), Diagnostics::glslIsNotSupported);
- return SLANG_FAIL;
+ case SourceLanguage::GLSL:
+ getSink()->diagnose(SourceLoc(), Diagnostics::glslIsNotSupported);
+ return SLANG_FAIL;
+ }
}
}
@@ -3230,12 +3234,23 @@ RefPtr<Module> Linkage::findOrImportModule(
PathInfo pathIncludedFromInfo = getSourceManager()->getPathInfo(loc, SourceLocType::Actual);
PathInfo filePathInfo;
+ ComPtr<ISlangBlob> fileContents;
+
// We have to load via the found path - as that is how file was originally loaded
if (SLANG_FAILED(includeSystem.findFile(fileName, pathIncludedFromInfo.foundPath, filePathInfo)))
{
- sink->diagnose(loc, Diagnostics::cannotFindFile, fileName);
- mapNameToLoadedModules[name] = nullptr;
- return nullptr;
+ if (name && name->text == "glsl")
+ {
+ // This is a builtin glsl module, just load it from embedded definition.
+ fileContents = getSessionImpl()->getGLSLLibraryCode();
+ filePathInfo = PathInfo::makeFromString("glsl");
+ }
+ else
+ {
+ sink->diagnose(loc, Diagnostics::cannotFindFile, fileName);
+ mapNameToLoadedModules[name] = nullptr;
+ return nullptr;
+ }
}
// Maybe this was loaded previously at a different relative name?
@@ -3243,8 +3258,7 @@ RefPtr<Module> Linkage::findOrImportModule(
return loadedModule;
// Try to load it
- ComPtr<ISlangBlob> fileContents;
- if(SLANG_FAILED(includeSystem.loadFile(filePathInfo, fileContents)))
+ if( !fileContents && SLANG_FAILED(includeSystem.loadFile(filePathInfo, fileContents)))
{
sink->diagnose(loc, Diagnostics::cannotOpenFile, fileName);
mapNameToLoadedModules[name] = nullptr;
@@ -5267,6 +5281,11 @@ SlangResult EndToEndCompileRequest::setTypeNameForEntryPointExistentialTypeParam
return SLANG_OK;
}
+void EndToEndCompileRequest::setAllowGLSLInput(bool value)
+{
+ getLinkage()->setAllowGLSLInput(value);
+}
+
SlangResult EndToEndCompileRequest::EndToEndCompileRequest::compile()
{
SlangResult res = SLANG_FAIL;