summaryrefslogtreecommitdiff
path: root/source/slang/glsl.meta.slang
diff options
context:
space:
mode:
authorArielG-NV <159081215+ArielG-NV@users.noreply.github.com>2024-04-03 09:30:46 -0400
committerGitHub <noreply@github.com>2024-04-03 09:30:46 -0400
commita697b2c6707ee699cb734a03fa529dd214ac66cc (patch)
tree1b68f4267159828092b512361faff4729510ea39 /source/slang/glsl.meta.slang
parentc0482ec12d683e53aca56543b620a4ec02082e29 (diff)
Implement 8.14-8.19 of OpenGL-GLSL specification
The following PR implements 8.14-8.19 of the [OpenGL-GLSL specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). Fully implements all functions and built-in type's, resolves https://github.com/shader-slang/slang/issues/3692 for GLSL & SPRI-V targets. _Notes:_ Testing Tools: * Fragment shaders cannot test computational results. Only OpCodes are checked for proper emitting. Implementation Notes: * SubpassInput requires an unknown image format. * SubpassInput is disjoint from TextureType: __SubpassImpl (.slang) & SubpassInputType (Compiler) to reduce code generation required. * SubpassInput required an additional input layout modifier, input_attachment_index, this was added as a new parameter binding attribute. Since the following qualifiers can overlap with different resources (`layout(input_attachment_index = 0, binding = 0, set = 0)`) input_attachment_index is checked for overlapping resource bindings separately from other qualifiers with `LayoutResourceKind::InputAttachmentIndex`. * `GLSLInputAttachmentIndexLayoutModifier` was added to enforce function parameters only accepting `in` decorated variables. * `in` decorated variables needed to have emitting modified to allow directly emitting the variable into function calls if used as a parameter, normally Slang has a "global variable" shadow as a "global parameter" through a copy. This does not work and is solved using `GlobalVariableShadowingGlobalParameterDecoration` to build a relationship of "global variable" to "global parameter", we then resolve this relationship and replace "global variable" uses later in compile. * `AtomicCounterMemory` memory-constraint requires `OpCapability AtomicStorage`, `AtomicStorage` is invalid for Vulkan targets. glslang outputs for `barrier`, `memoryBarrier`, and `groupMemoryBarrier` `AtomicCounterMemory` as a memory constraint. This compiles as valid SPIR-V for Vulkan since `OpCapability AtomicStorage` is not declared. This behavior of glslang is undefined as per [3.31.Capability of the SPIR-V specification](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_capability). We will omit `AtomicCounterMemory` from our barrier calls.
Diffstat (limited to 'source/slang/glsl.meta.slang')
-rw-r--r--source/slang/glsl.meta.slang640
1 files changed, 640 insertions, 0 deletions
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
index d7b646810..e915442c7 100644
--- a/source/slang/glsl.meta.slang
+++ b/source/slang/glsl.meta.slang
@@ -7263,3 +7263,643 @@ __glsl_version(430) [require(glsl)]
}
}
}
+
+/// Section 8.14. Fragment Processing Functions
+
+[require(any_gfx_target, fragmentprocessing)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdx(float p)
+{
+ return ddx(p);
+}
+[require(any_gfx_target, fragmentprocessing)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdx(vector<float, N> p)
+{
+ return ddx(p);
+}
+
+[require(any_gfx_target, fragmentprocessing)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdy(float p)
+{
+ return ddy(p);
+}
+[require(any_gfx_target, fragmentprocessing)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdy(vector<float, N> p)
+{
+ return ddy(p);
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdxFine(float p)
+{
+ return ddx_fine(p);
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdxFine(vector<float, N> p)
+{
+ return ddx_fine(p);
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdyFine(float p)
+{
+ return ddy_fine(p);
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdyFine(vector<float, N> p)
+{
+ return ddy_fine(p);
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdxCoarse(float p)
+{
+ return ddx_coarse(p);
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdxCoarse(vector<float, N> p)
+{
+ return ddx_coarse(p);
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float dFdyCoarse(float p)
+{
+ return ddy_coarse(p);
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> dFdyCoarse(vector<float, N> p)
+{
+ return ddy_coarse(p);
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float fwidthFine(float p)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return abs(ddx_fine(p)) + abs(ddy_fine(p));
+ }
+ case glsl: __intrinsic_asm "fwidthFine($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability DerivativeControl;
+ OpFwidthFine $$float result $p;
+ };
+ }
+ }
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> fwidthFine(vector<float, N> p)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return abs(ddx_fine(p)) + abs(ddy_fine(p));
+ }
+ case glsl: __intrinsic_asm "fwidthFine($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability DerivativeControl;
+ OpFwidthFine $$vector<float, N> result $p;
+ };
+ }
+ }
+}
+
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+[__NoSideEffect]
+[ForceInline]
+public float fwidthCoarse(float p)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return abs(ddx_coarse(p)) + abs(ddy_coarse(p));
+ }
+ case glsl: __intrinsic_asm "fwidthCoarse($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability DerivativeControl;
+ OpFwidthCoarse $$float result $p;
+ };
+ }
+ }
+}
+[require(any_gfx_target, fragmentprocessing_derivativecontrol)]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vector<float, N> fwidthCoarse(vector<float, N> p)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return abs(ddx_coarse(p)) + abs(ddy_coarse(p));
+ }
+ case glsl: __intrinsic_asm "fwidthCoarse($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability DerivativeControl;
+ OpFwidthCoarse $$vector<float, N> result $p;
+ };
+ }
+ }
+}
+
+[require(any_gfx_target, fragmentprocessing)]
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public float interpolateAtCentroid(__ref float interpolant)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return EvaluateAttributeAtCentroid(interpolant);
+ }
+ case glsl: __intrinsic_asm "interpolateAtCentroid($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$float result glsl450 InterpolateAtCentroid &interpolant
+ };
+ }
+ }
+}
+[require(any_gfx_target, fragmentprocessing)]
+__generic<let N : int>
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public vector<float, N> interpolateAtCentroid(__ref vector<float, N> interpolant)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return EvaluateAttributeAtCentroid(interpolant);
+ }
+ case glsl: __intrinsic_asm "interpolateAtCentroid($0)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$vector<float, N> result glsl450 InterpolateAtCentroid &interpolant
+ };
+ }
+ }
+}
+
+[require(any_gfx_target, fragmentprocessing)]
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public float interpolateAtSample(__ref float interpolant, int sample)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return EvaluateAttributeAtSample(interpolant, sample);
+ }
+ case glsl: __intrinsic_asm "interpolateAtSample($0,$1)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$float result glsl450 InterpolateAtSample &interpolant $sample
+ };
+ }
+ }
+}
+[require(any_gfx_target, fragmentprocessing)]
+__generic<let N : int>
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public vector<float, N> interpolateAtSample(__ref vector<float, N> interpolant, int sample)
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ return EvaluateAttributeAtSample(interpolant, sample);
+ }
+ case glsl: __intrinsic_asm "interpolateAtSample($0,$1)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$vector<float, N> result glsl450 InterpolateAtSample &interpolant $sample
+ };
+ }
+ }
+}
+
+[require(glsl_spirv, fragmentprocessing)]
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public float interpolateAtOffset(__ref float interpolant, vec2 offset)
+{
+ __target_switch
+ {
+ case glsl: __intrinsic_asm "interpolateAtOffset($0,$1)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$float result glsl450 InterpolateAtOffset &interpolant $offset
+ };
+ }
+ }
+}
+[require(glsl_spirv, fragmentprocessing)]
+__generic<let N : int>
+[__NoSideEffect]
+[__GLSLRequireShaderInputParameter(0)]
+public vector<float, N> interpolateAtOffset(__ref vector<float, N> interpolant, vec2 offset)
+{
+ __target_switch
+ {
+ case glsl: __intrinsic_asm "interpolateAtOffset($0,$1)";
+ case spirv:
+ {
+ return spirv_asm
+ {
+ OpCapability InterpolationFunction;
+ OpExtInst $$vector<float, N> result glsl450 InterpolateAtOffset &interpolant $offset
+ };
+ }
+ }
+}
+
+/// Section 8.15. Noise Functions (deprecated)
+
+[deprecated("Always returns 0")]
+[__NoSideEffect]
+[ForceInline]
+public float noise1(float x)
+{
+ return 0.0f;
+}
+[deprecated("Always returns 0")]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public float noise1(vector<float, N> x)
+{
+ return 0.0f;
+}
+
+[deprecated("Always returns 0")]
+[__NoSideEffect]
+[ForceInline]
+public vec2 noise2(float x)
+{
+ return vec2(0.0f);
+}
+[deprecated("Always returns 0")]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vec2 noise2(vector<float, N> x)
+{
+ return vec2(0.0f);
+}
+
+[deprecated("Always returns 0")]
+[__NoSideEffect]
+[ForceInline]
+public vec3 noise3(float x)
+{
+ return vec3(0.0f);
+}
+[deprecated("Always returns 0")]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vec3 noise3(vector<float, N> x)
+{
+ return vec3(0.0f);
+}
+
+[deprecated("Always returns 0")]
+[__NoSideEffect]
+[ForceInline]
+public vec4 noise4(float x)
+{
+ return vec4(0.0f);
+}
+[deprecated("Always returns 0")]
+__generic<let N : int>
+[__NoSideEffect]
+[ForceInline]
+public vec4 noise4(vector<float, N> x)
+{
+ return vec4(0.0f);
+}
+
+/// Section 8.16. Shader Invocation Control Functions
+
+// TODO: for tessellation control shader: barrier() function may only
+// be placed inside the main() of the shader and may not be called within
+// control flow.
+// TODO: if called after a return, error.
+
+[require(any_gfx_target, compute_tess_gfx)]
+[ForceInline]
+public void barrier()
+{
+ __target_switch
+ {
+ case hlsl:
+ {
+ GroupMemoryBarrier();
+ }
+ case glsl: __intrinsic_asm "barrier()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpControlBarrier Workgroup Workgroup AcquireRelease|WorkgroupMemory
+ };
+ }
+ }
+}
+
+/// Section 8.17. Shader Memory Control Functions
+
+[require(shadermemorycontrol)]
+[ForceInline]
+public void memoryBarrier()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "AllMemoryBarrier()";
+ case glsl: __intrinsic_asm "memoryBarrier()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpCapability Shader;
+ OpMemoryBarrier Device AcquireRelease|WorkgroupMemory|ImageMemory|UniformMemory
+ };
+ }
+ }
+}
+
+// Does not exist in vulkan. The equivlent is now `memoryBarrierBuffer`
+// for vulkan since GL_EXT_vulkan_glsl_relaxed states that a atomic_counter
+// is a storage buffer object in implementation.
+
+// glslang will compile with `AtomicCounterMemory` since it does not use
+// the `AtomicStorage` OpCapability which is required for `AtomicCounterMemory`.
+// this is invalid/undefined spir-v for vulkan targets and should not be followed
+[require(any_gfx_target, shadermemorycontrol_compute)]
+[ForceInline]
+public void memoryBarrierAtomicCounter()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "AllMemoryBarrier()";
+ case glsl: __intrinsic_asm "memoryBarrierBuffer()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpCapability Shader;
+ OpMemoryBarrier Device AcquireRelease|UniformMemory
+ };
+ }
+ }
+}
+[require(shadermemorycontrol)]
+[ForceInline]
+public void memoryBarrierBuffer()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "DeviceMemoryBarrier()";
+ case glsl: __intrinsic_asm "memoryBarrierBuffer()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpCapability Shader;
+ OpMemoryBarrier Device AcquireRelease|UniformMemory
+ };
+ }
+ }
+}
+
+[require(any_gfx_target, shadermemorycontrol_compute)]
+[ForceInline]
+public void memoryBarrierShared()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "GroupMemoryBarrier()";
+ case glsl: __intrinsic_asm "memoryBarrierShared()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpCapability Shader;
+ OpMemoryBarrier Device AcquireRelease|WorkgroupMemory
+ };
+ }
+ }
+}
+[require(shadermemorycontrol)]
+[ForceInline]
+public void memoryBarrierImage()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "DeviceMemoryBarrier()";
+ case glsl: __intrinsic_asm "memoryBarrierImage()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpMemoryBarrier Device AcquireRelease|ImageMemory
+ };
+ }
+ }
+}
+[require(any_gfx_target, shadermemorycontrol_compute)]
+[ForceInline]
+public void groupMemoryBarrier()
+{
+ __target_switch
+ {
+ case hlsl: __intrinsic_asm "GroupMemoryBarrier()";
+ case glsl: __intrinsic_asm "groupMemoryBarrier()";
+ case spirv:
+ {
+ spirv_asm
+ {
+ OpMemoryBarrier Workgroup AcquireRelease|WorkgroupMemory|ImageMemory|UniformMemory
+ };
+ }
+ }
+}
+
+/// Section 8.18. Subpass-Input Functions
+
+${{{{
+struct SubpassLoadEntriesType
+{
+ const char* typeName;
+ const char* prefix;
+};
+static const SubpassLoadEntriesType kSubpassLoadEntries[] =
+ {
+ { "vec4", "" },
+ { "uvec4", "u" },
+ { "ivec4", "i" },
+ };
+for (const auto& subpassLoadEntry : kSubpassLoadEntries)
+{
+}}}}
+ [require(glsl_spirv, subpass)]
+ public typealias $(subpassLoadEntry.prefix)subpassInput = __SubpassImpl<
+ $(subpassLoadEntry.typeName),
+ 0 // isMS
+ >;
+
+ [require(glsl_spirv, subpass)]
+ public typealias $(subpassLoadEntry.prefix)subpassInputMS = __SubpassImpl<
+ $(subpassLoadEntry.typeName),
+ 1 // isMS
+ >;
+${{{{
+}
+}}}}
+
+ __generic<T>
+ [require(glsl_spirv, subpass)]
+ [__NoSideEffect]
+ [ForceInline]
+ public T subpassLoad(__SubpassImpl<T,0> subpass)
+ {
+ __target_switch
+ {
+ case hlsl: return subpass.SubpassLoad();
+ case glsl: __intrinsic_asm "subpassLoad($0)";
+ case spirv:
+ {
+ let zeroVec = ivec2(0);
+ return spirv_asm
+ {
+ OpCapability StorageImageReadWithoutFormat;
+ result:$$T = OpImageRead $subpass $zeroVec
+ };
+ }
+ }
+ }
+ __generic<T>
+ [require(glsl_spirv, subpass)]
+ [__NoSideEffect]
+ [ForceInline]
+ public T subpassLoad(__SubpassImpl<T,1> subpass, int sample)
+ {
+ __target_switch
+ {
+ case hlsl: return subpass.SubpassLoad(sample);
+ case glsl: __intrinsic_asm "subpassLoad($0, $1)";
+ case spirv:
+ {
+ let zeroVec = ivec2(0);
+ return spirv_asm
+ {
+ OpCapability StorageImageReadWithoutFormat;
+ result:$$T = OpImageRead $subpass $zeroVec Sample $sample
+ };
+ }
+ }
+ }
+
+/// Section 8.19. Shader Invocation Group Functions
+
+// Invocation functions compiles into SubgroupVoteKHR operations.
+// Instead of using these, we directly emit the non deprecated
+// alternatives
+__glsl_version(460)
+__spirv_version(1.3)
+[require(shaderinvocationgroup)]
+[NonUniformReturn]
+[ForceInline]
+public bool anyInvocation(bool value)
+{
+ return WaveActiveAnyTrue(value);
+}
+__glsl_version(460)
+__spirv_version(1.3)
+[require(shaderinvocationgroup)]
+[NonUniformReturn]
+[ForceInline]
+public bool allInvocations(bool value)
+{
+ return WaveActiveAllTrue(value);
+}
+__glsl_version(460)
+__spirv_version(1.3)
+[require(shaderinvocationgroup)]
+[NonUniformReturn]
+[ForceInline]
+public bool allInvocationsEqual(bool value)
+{
+ return WaveActiveAllEqual(value);
+} \ No newline at end of file