1277 lines
58 KiB
Plaintext
1277 lines
58 KiB
Plaintext
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2022 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef XENIA_UI_SHADERS_XESL_XESLI_
|
|
#define XENIA_UI_SHADERS_XESL_XESLI_
|
|
|
|
// XESL_LANGUAGE_GLSL / HLSL / MSL = 1 are expected to be defined via compiler
|
|
// arguments.
|
|
|
|
// Required GLSL extensions:
|
|
// - GL_EXT_control_flow_attributes
|
|
// - GL_EXT_samplerless_texture_functions
|
|
|
|
// For functions, it's preferable to take the identifiers here from an existing
|
|
// target language, such as GLSL or HLSL, prefixing them with xesl_, only
|
|
// modifying the names when altering (generalizing or specializing usually)
|
|
// their functionality compared to that of the original function. The preferred
|
|
// name choice from all the shading languages is the name that reflects the
|
|
// functionality the closest, especially if some languages have a narrower input
|
|
// domain (for instance, HLSL has asuint that can accept both float and int,
|
|
// while GLSL has floatBitsToUint that accepts only float - there are two
|
|
// options here, a xesl_floatBitsToUint alias, or xesl_asuint overloads, but the
|
|
// former is more precisely descriptive, so it's preferred; xesl_lerp is
|
|
// preferred over xesl_mix because the former describes how exactly the mixing
|
|
// will be performed), and / or that is the most visually consistent
|
|
// (xesl_float4 over xesl_vec4 considering it's a float vector).
|
|
|
|
#if XESL_LANGUAGE_MSL
|
|
#include <metal_stdlib>
|
|
using namespace metal;
|
|
#endif
|
|
|
|
// Vectors.
|
|
|
|
// Scalars for definition consistency.
|
|
#define xesl_bool bool
|
|
#define xesl_int int
|
|
#define xesl_uint uint
|
|
#define xesl_float float
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_bool2 bvec2
|
|
#define xesl_bool3 bvec3
|
|
#define xesl_bool4 bvec4
|
|
#define xesl_int2 ivec2
|
|
#define xesl_int3 ivec3
|
|
#define xesl_int4 ivec4
|
|
#define xesl_uint2 uvec2
|
|
#define xesl_uint3 uvec3
|
|
#define xesl_uint4 uvec4
|
|
#define xesl_float2 vec2
|
|
#define xesl_float3 vec3
|
|
#define xesl_float4 vec4
|
|
#else
|
|
#define xesl_bool2 bool2
|
|
#define xesl_bool3 bool3
|
|
#define xesl_bool4 bool4
|
|
#define xesl_int2 int2
|
|
#define xesl_int3 int3
|
|
#define xesl_int4 int4
|
|
#define xesl_uint2 uint2
|
|
#define xesl_uint3 uint3
|
|
#define xesl_uint4 uint4
|
|
#define xesl_float2 float2
|
|
#define xesl_float3 float3
|
|
#define xesl_float4 float4
|
|
#endif // XESL_LANGUAGE_GLSL
|
|
|
|
xesl_bool2 xesl_bool_x2(bool xesl_var_value) {
|
|
return xesl_bool2(xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_bool3 xesl_bool_x3(bool xesl_var_value) {
|
|
return xesl_bool3(xesl_var_value, xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_bool4 xesl_bool_x4(bool xesl_var_value) {
|
|
return xesl_bool4(xesl_var_value, xesl_var_value, xesl_var_value,
|
|
xesl_var_value);
|
|
}
|
|
xesl_int2 xesl_int_x2(int xesl_var_value) {
|
|
return xesl_int2(xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_int3 xesl_int_x3(int xesl_var_value) {
|
|
return xesl_int3(xesl_var_value, xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_int4 xesl_int_x4(int xesl_var_value) {
|
|
return xesl_int4(xesl_var_value, xesl_var_value, xesl_var_value,
|
|
xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_uint_x2(uint xesl_var_value) {
|
|
return xesl_uint2(xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_uint_x3(uint xesl_var_value) {
|
|
return xesl_uint3(xesl_var_value, xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_uint_x4(uint xesl_var_value) {
|
|
return xesl_uint4(xesl_var_value, xesl_var_value, xesl_var_value,
|
|
xesl_var_value);
|
|
}
|
|
xesl_float2 xesl_float_x2(float xesl_var_value) {
|
|
return xesl_float2(xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_float3 xesl_float_x3(float xesl_var_value) {
|
|
return xesl_float3(xesl_var_value, xesl_var_value, xesl_var_value);
|
|
}
|
|
xesl_float4 xesl_float_x4(float xesl_var_value) {
|
|
return xesl_float4(xesl_var_value, xesl_var_value, xesl_var_value,
|
|
xesl_var_value);
|
|
}
|
|
|
|
// Declarations.
|
|
//
|
|
// Resource binding is very different between shading languages, so any
|
|
// customizations are fine in it. All binding slots for all APIs, however,
|
|
// should be explicitly specified by the shader for ease of manual lookup and
|
|
// tweaking. They should be alphabetically ordered by the name of the target
|
|
// shading language in the argument lists (GLSL before HLSL). For readability,
|
|
// the `set=` and `binding=` specifiers, and register types and the `space`
|
|
// prefix in HLSL, are exposed to the shader, even though they're redundant.
|
|
//
|
|
// The `xesl_id_` prefix (with context-specific sub-prefixes) can be used to
|
|
// create internal derivative identifiers (such as buffer block names from
|
|
// instance names, or separate texture and sampler from a combined texture /
|
|
// sampler for languages not supporting the latter).
|
|
|
|
// Non-compute shader entry point must be declared as:
|
|
// xesl_entry_outputs_begin
|
|
// - Linked stage outputs.
|
|
// - Linked system stage outputs (like vertex position).
|
|
// - System stage outputs.
|
|
// xesl_entry_outputs_end_stageInputs_begin
|
|
// - Linked stage inputs (vertex attributes, interpolants).
|
|
// xesl_entry_stageInputs_end_bindings_begin_[stage] (vertex, pixel)
|
|
// Everything here must be separated with xesl_entry_binding_next, with no
|
|
// leading or trailing separators.
|
|
// - Buffer, texture, sampler bindings.
|
|
// xesl_entry_bindings_end_inputs_begin
|
|
// (or xesl_entry_bindings_empty_end_inputs_begin if there are no bindings).
|
|
// Everything here must be separated with xesl_entry_input_next, with no
|
|
// leading or trailing separators.
|
|
// - xesl_entry_input_stageInputs if any linked stage inputs are used.
|
|
// - Linked system inputs (like pixel position).
|
|
// - System inputs.
|
|
// xesl_entry_inputs_end_code_begin
|
|
// - Main function code.
|
|
// xesl_entry_code_end
|
|
//
|
|
// Compute shader entry point must be declared as:
|
|
// #define xesl_localSize_x, y, z
|
|
// xesl_entry_bindings_begin_compute
|
|
// Everything here must be separated with xesl_entry_binding_next, with no
|
|
// leading or trailing separators.
|
|
// - Buffer, texture, sampler bindings.
|
|
// xesl_entry_bindings_end_inputs_begin_compute
|
|
// Everything here must be separated with xesl_entry_input_next, with no
|
|
// leading or trailing separators.
|
|
// - System inputs.
|
|
// xesl_entry_inputs_end_code_begin_compute
|
|
// - Main function code.
|
|
// xesl_entry_code_end_compute
|
|
//
|
|
// Bindings are in the entry point because they are passed this way in MSL. For
|
|
// this reason, constant and storage buffer declarations are also split into the
|
|
// declaration itself and the binding (because blocks can't be passed as
|
|
// function arguments in GLSL, for instance, so they must be fully declared
|
|
// before functions referencing them in headers, for example - but in MSL, their
|
|
// structure has to be forward-declared for this purpose, and the reference to
|
|
// the binding should be passed to the function).
|
|
//
|
|
// Note that for the stage inputs / outputs, the order must be the same as in
|
|
// HLSL linkage. For this reason, the position and the fragment coordinate also
|
|
// must be after the stage inputs structure in the input list.
|
|
//
|
|
// Both input / output and binding names may be placed in the global scope in
|
|
// the target language, make sure they don't collide with anything there.
|
|
//
|
|
// In compute shaders, the total group size must not exceed 128 threads (unless
|
|
// the shader is used with the appropriate conditionals), as that's the minimum
|
|
// maxComputeWorkGroupInvocations requirement on Vulkan. 128 threads exactly is
|
|
// the recommended group size overall, especially for shaders not using the
|
|
// group functionality, as it's the maximum wave size supported by DXIL and
|
|
// SPIR-V wave operations, and there are PowerVR GPUs with 128-lane waves, so
|
|
// it provides balance between wave utilization and excess thread (and, on GPUs
|
|
// with smaller waves, wave) count if the size of the actual work domain is not
|
|
// aligned to the group size.
|
|
//
|
|
// System outputs and inputs (declared via the respective xesl_entry_output_*
|
|
// and xesl_entry_input_*):
|
|
// - Vertex shaders:
|
|
// - out xesl_float4 xesl_Position
|
|
// - in uint xesl_VertexID
|
|
// - Pixel shaders:
|
|
// - in xesl_float4 xesl_FragCoord
|
|
// xesl_FragCoord.w is 1/W if XESL_FRAG_COORD_W_IS_INVERSE, W otherwise.
|
|
// - Compute shaders:
|
|
// - in xesl_uint3 xesl_WorkGroupID
|
|
// - in xesl_uint3 xesl_LocalInvocationID
|
|
// - in xesl_uint3 xesl_GlobalInvocationID
|
|
// - in uint xesl_LocalInvocationIndex
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_entry_output(type, name, index, semantic) \
|
|
layout(location=index) out type name;
|
|
#define xesl_entry_output_target(type, name, index) \
|
|
layout(location=index) out type name;
|
|
#define xesl_Output(name) name
|
|
#define xesl_Position gl_Position
|
|
#define xesl_entry_stageInput(type, name, index, semantic) \
|
|
layout(location=index) in type name;
|
|
#define xesl_entry_bindings_end_inputs_begin_compute \
|
|
layout(local_size_x=(xesl_localSize_x), local_size_y=(xesl_localSize_y), \
|
|
local_size_z=(xesl_localSize_z)) in;
|
|
#define xesl_StageInput(name) name
|
|
#define xesl_VertexID (uint(gl_VertexIndex))
|
|
#define XESL_FRAG_COORD_W_IS_INVERSE 1
|
|
#define xesl_FragCoord gl_FragCoord
|
|
#define xesl_WorkGroupID gl_WorkGroupID
|
|
#define xesl_LocalInvocationID gl_LocalInvocationID
|
|
#define xesl_GlobalInvocationID gl_GlobalInvocationID
|
|
#define xesl_LocalInvocationIndex gl_LocalInvocationIndex
|
|
#define xesl_entry_inputs_end_code_begin void main() {
|
|
#define xesl_entry_inputs_end_code_begin_compute void main() {
|
|
#define xesl_entry_return return;
|
|
#elif XESL_LANGUAGE_HLSL
|
|
#define xesl_entry_outputs_begin struct xesl_entry_outputs_struct {
|
|
#define xesl_entry_output(type, name, index, semantic) type name : semantic;
|
|
#define xesl_entry_output_target(type, name, index) \
|
|
type name : SV_Target##index;
|
|
#define xesl_Output(name) xesl_entry_outputs.name
|
|
#define xesl_entry_output_position \
|
|
float4 xesl_id_output_position : SV_Position;
|
|
#define xesl_Position xesl_entry_outputs.xesl_id_output_position
|
|
#define xesl_entry_outputs_end_stageInputs_begin \
|
|
}; \
|
|
struct xesl_entry_stageInputs_struct {
|
|
#define xesl_entry_stageInput(type, name, index, semantic) \
|
|
type name : semantic;
|
|
#define xesl_entry_stageInputs_end_bindings_begin_vertex };
|
|
#define xesl_entry_stageInputs_end_bindings_begin_pixel };
|
|
#define xesl_entry_bindings_end_inputs_begin xesl_entry_outputs_struct main(
|
|
#define xesl_entry_bindings_empty_end_inputs_begin \
|
|
xesl_entry_outputs_struct main(
|
|
#define xesl_entry_bindings_end_inputs_begin_compute \
|
|
[numthreads(xesl_localSize_x, xesl_localSize_y, xesl_localSize_z)] \
|
|
void main(
|
|
#define xesl_entry_input_next ,
|
|
#define xesl_entry_input_stageInputs \
|
|
xesl_entry_stageInputs_struct xesl_entry_stageInputs
|
|
#define xesl_StageInput(name) xesl_entry_stageInputs.name
|
|
#define xesl_entry_input_vertexID uint xesl_VertexID : SV_VertexID
|
|
#define xesl_entry_input_fragCoord xesl_float4 xesl_FragCoord : SV_Position
|
|
#define xesl_entry_input_workGroupID xesl_uint3 xesl_WorkGroupID : SV_GroupID
|
|
#define xesl_entry_input_localInvocationID \
|
|
xesl_uint3 xesl_LocalInvocationID : SV_GroupThreadID
|
|
#define xesl_entry_input_globalInvocationID \
|
|
xesl_uint3 xesl_GlobalInvocationID : SV_DispatchThreadID
|
|
#define xesl_entry_input_localInvocationIndex \
|
|
uint xesl_LocalInvocationIndex : SV_GroupIndex
|
|
#define xesl_entry_inputs_end_code_begin \
|
|
) { \
|
|
xesl_entry_outputs_struct xesl_entry_outputs;
|
|
#define xesl_entry_inputs_end_code_begin_compute ) {
|
|
#define xesl_entry_return return xesl_entry_outputs;
|
|
#elif XESL_LANGUAGE_MSL
|
|
#define xesl_entry_outputs_begin struct xesl_entry_outputs_struct {
|
|
#define xesl_entry_output(type, name, index, semantic) \
|
|
type name [[user(semantic)]];
|
|
#define xesl_entry_output_target(type, name, index) \
|
|
type name [[color(index)]];
|
|
#define xesl_Output(name) xesl_entry_outputs.name
|
|
#define xesl_entry_output_position \
|
|
xesl_float4 xesl_id_output_position [[position]];
|
|
#define xesl_Position xesl_entry_outputs.xesl_id_output_position
|
|
#define xesl_entry_outputs_end_stageInputs_begin \
|
|
}; \
|
|
struct xesl_entry_stageInputs_struct {
|
|
#define xesl_entry_stageInput(type, name, index, semantic) \
|
|
type name [[user(semantic)]];
|
|
#define xesl_entry_stageInput_vertex(type, name, index, semantic) \
|
|
type name [[attribute(index)]];
|
|
#define xesl_entry_stageInputs_end_bindings_begin_vertex \
|
|
}; \
|
|
vertex xesl_entry_outputs_struct xesl_entry(
|
|
#define xesl_entry_stageInputs_end_bindings_begin_pixel \
|
|
}; \
|
|
fragment xesl_entry_outputs_struct xesl_entry(
|
|
#define xesl_entry_bindings_begin_compute kernel void xesl_entry(
|
|
#define xesl_entry_binding_next ,
|
|
#define xesl_entry_bindings_end_inputs_begin ,
|
|
#define xesl_entry_bindings_end_inputs_begin_compute ,
|
|
#define xesl_entry_input_next ,
|
|
#define xesl_entry_input_stageInputs \
|
|
xesl_entry_stageInputs_struct xesl_entry_stageInputs [[stage_in]]
|
|
#define xesl_StageInput(name) xesl_entry_stageInputs.name
|
|
#define xesl_entry_input_vertexID uint xesl_VertexID [[vertex_id]]
|
|
#define XESL_FRAG_COORD_W_IS_INVERSE 1
|
|
#define xesl_entry_input_fragCoord xesl_float4 xesl_FragCoord [[position]]
|
|
#define xesl_entry_input_workGroupID \
|
|
xesl_uint3 xesl_WorkGroupID [[threadgroup_position_in_grid]]
|
|
#define xesl_entry_input_localInvocationID \
|
|
xesl_uint3 xesl_LocalInvocationID [[thread_position_in_threadgroup]]
|
|
#define xesl_entry_input_globalInvocationID \
|
|
xesl_uint3 xesl_GlobalInvocationID [[thread_position_in_grid]]
|
|
#define xesl_entry_input_localInvocationIndex \
|
|
uint xesl_LocalInvocationIndex [[thread_index_in_threadgroup]]
|
|
#define xesl_entry_inputs_end_code_begin \
|
|
) { \
|
|
xesl_entry_outputs_struct xesl_entry_outputs;
|
|
#define xesl_entry_inputs_end_code_begin_compute ) {
|
|
#define xesl_entry_return return xesl_entry_outputs;
|
|
#else
|
|
#error xesl_entry not defined for the target language.
|
|
#endif // XE_LANGUAGE
|
|
#ifndef xesl_entry_outputs_begin
|
|
#define xesl_entry_outputs_begin
|
|
#endif // !xesl_entry_outputs_begin
|
|
#ifndef xesl_entry_output_position
|
|
#define xesl_entry_output_position
|
|
#endif // !xesl_entry_output_position
|
|
#ifndef xesl_entry_outputs_end_stageInputs_begin
|
|
#define xesl_entry_outputs_end_stageInputs_begin
|
|
#endif // !xesl_entry_outputs_end_stageInputs_begin
|
|
#ifndef xesl_entry_stageInput_vertex
|
|
#define xesl_entry_stageInput_vertex(type, name, index, semantic) \
|
|
xesl_entry_stageInput(type, name, index, semantic)
|
|
#endif // !xesl_entry_stageInput_vertex
|
|
#ifndef xesl_entry_stageInputs_end_bindings_begin_vertex
|
|
#define xesl_entry_stageInputs_end_bindings_begin_vertex
|
|
#endif // !xesl_entry_stageInputs_end_bindings_begin_vertex
|
|
#ifndef xesl_entry_stageInputs_end_bindings_begin_pixel
|
|
#define xesl_entry_stageInputs_end_bindings_begin_pixel
|
|
#endif // !xesl_entry_stageInputs_end_bindings_begin_pixel
|
|
#ifndef xesl_entry_bindings_begin_compute
|
|
#define xesl_entry_bindings_begin_compute
|
|
#endif // !xesl_entry_bindings_begin_compute
|
|
#ifndef xesl_entry_binding_next
|
|
#define xesl_entry_binding_next
|
|
#endif // !xesl_entry_binding_next
|
|
#ifndef xesl_entry_bindings_end_inputs_begin
|
|
#define xesl_entry_bindings_end_inputs_begin
|
|
#endif // !xesl_entry_bindings_end_inputs_begin
|
|
#ifndef xesl_entry_bindings_empty_end_inputs_begin
|
|
#define xesl_entry_bindings_empty_end_inputs_begin
|
|
#endif // !xesl_entry_bindings_empty_end_inputs_begin
|
|
#ifndef xesl_entry_bindings_end_inputs_begin_compute
|
|
#define xesl_entry_bindings_end_inputs_begin_compute
|
|
#endif // !xesl_entry_bindings_end_inputs_begin_compute
|
|
#ifndef xesl_entry_input_next
|
|
#define xesl_entry_input_next
|
|
#endif // !xesl_entry_input_next
|
|
#ifndef xesl_entry_input_stageInputs
|
|
#define xesl_entry_input_stageInputs
|
|
#endif // !xesl_entry_input_stageInputs
|
|
#ifndef xesl_entry_input_vertexID
|
|
#define xesl_entry_input_vertexID
|
|
#endif // !xesl_entry_input_vertexID
|
|
#ifndef xesl_entry_input_fragCoord
|
|
#define xesl_entry_input_fragCoord
|
|
#endif // !xesl_entry_input_fragCoord
|
|
#ifndef xesl_entry_input_workGroupID
|
|
#define xesl_entry_input_workGroupID
|
|
#endif // !xesl_entry_input_workGroupID
|
|
#ifndef xesl_entry_input_localInvocationID
|
|
#define xesl_entry_input_localInvocationID
|
|
#endif // !xesl_entry_input_localInvocationID
|
|
#ifndef xesl_entry_input_globalInvocationID
|
|
#define xesl_entry_input_globalInvocationID
|
|
#endif // !xesl_entry_input_globalInvocationID
|
|
#ifndef xesl_entry_input_localInvocationIndex
|
|
#define xesl_entry_input_localInvocationIndex
|
|
#endif // !xesl_entry_input_localInvocationIndex
|
|
#ifndef xesl_entry_code_end
|
|
#define xesl_entry_code_end \
|
|
xesl_entry_return \
|
|
}
|
|
#endif // !xesl_entry_code_end
|
|
#ifndef xesl_entry_code_end_compute
|
|
#define xesl_entry_code_end_compute }
|
|
#endif // !xesl_entry_code_end_compute
|
|
|
|
// XESL_Y_SCREEN_DIRECTION is 1.0 if with a positive viewport height,
|
|
// +xesl_Position.y is towards +xesl_FragCoord.y, -1.0 if +xesl_Position.y is
|
|
// towards -xesl_FragCoord.y.
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define XESL_Y_SCREEN_DIRECTION 1.0
|
|
#else
|
|
#define XESL_Y_SCREEN_DIRECTION -1.0
|
|
#endif // XESL_LANGUAGE_GLSL
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
// GLSL requires just const for declaring a constant in the global scope.
|
|
#define xesl_staticConst const
|
|
#elif XESL_LANGUAGE_HLSL
|
|
// HLSL requires static const for declaring a constant in the global scope so
|
|
// it doesn't go to $Globals instead.
|
|
#define xesl_staticConst static const
|
|
#elif XESL_LANGUAGE_MSL
|
|
#define xesl_staticConst constexpr constant
|
|
#else
|
|
#error xesl_staticConst not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_block_offset_member(glsl_offset_bytes, hlsl_packoffset, type, \
|
|
name_element_count) \
|
|
layout(offset=glsl_offset_bytes) type name_element_count;
|
|
#elif XESL_LANGUAGE_HLSL
|
|
#define xesl_block_offset_member(glsl_offset_bytes, hlsl_packoffset, type, \
|
|
name_element_count) \
|
|
type name_element_count : packoffset(hlsl_packoffset);
|
|
#elif XESL_LANGUAGE_MSL
|
|
// Explicit offset is not supported by MSL.
|
|
#define xesl_block_offset_member(glsl_offset_bytes, hlsl_packoffset, type, \
|
|
name_element_count) \
|
|
type name_element_count;
|
|
#else
|
|
#error xesl_block_offset_member not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
|
|
// Structures of constant and structured buffer bindings must be declared before
|
|
// the entry point declaration.
|
|
|
|
// Constant buffers and push constants must be manually packed as std140 (which
|
|
// is stricter than HLSL packing) due to the GLSL requirement. This means that
|
|
// 32x4 and 32x3 vectors must start at 16-byte alignment, 32x2 at 8-byte, and a
|
|
// single 32-bit value can be placed immediately after a 32x3 vector (the Vulkan
|
|
// definition of this behavior). Specifically, all alignment padding must be
|
|
// inserted explicitly (or xesl_block_offset_member must be used), as by default
|
|
// HLSL doesn't have the alignment requirement, only the rule that elements
|
|
// (array elements, or single non-array members) must not cross 32x4 vector
|
|
// boundaries, so something like float|float3 or float|float2|float will be
|
|
// packed differently in GLSL (float|pad3|float3 or float|pad|float2|float) and
|
|
// HLSL (float|float3 or float|float2|float).
|
|
|
|
// Constant buffer and push constant member names will be in the global scope in
|
|
// some target languages - they must not collide with anything else there. To
|
|
// access a constant, use xesl_constant or xesl_pushConstant.
|
|
|
|
// Push constants, even though may be spread across multiple constant buffers in
|
|
// the Direct3D 12 API, must be declared in a single structure in XeSL - the
|
|
// reason is that layout qualifiers in GLSL can't be used in regular structures,
|
|
// only in blocks, and sub-blocks can't be declared in a block, so there's no
|
|
// way to create separate identifiers for push constant ranges in GLSL. Though
|
|
// both GLSL and HLSL support anonymous push constants / cbuffers, MSL requires
|
|
// a name for the buffer binding.
|
|
// In GLSL, the offsets in the push constants are global across shader stages.
|
|
// In HLSL, they're local to the specific root constant buffer.
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_constantBuffer_begin(name, glsl_set, glsl_binding, hlsl_b, \
|
|
hlsl_b_space) \
|
|
layout(std140, glsl_set, glsl_binding) \
|
|
uniform xesl_id_constantBuffer_##name {
|
|
#define xesl_constantBuffer_end(name) \
|
|
} name;
|
|
#define xesl_constant(cbuffer_name, constant_name) cbuffer_name.constant_name
|
|
#define xesl_pushConstants_begin(hlsl_b, hlsl_b_space) \
|
|
layout(push_constant) uniform xesl_pushConstants_block {
|
|
#define xesl_pushConstants_end \
|
|
} xesl_pushConstants;
|
|
#define xesl_pushConstant(name) xesl_pushConstants.name
|
|
#elif XESL_LANGUAGE_HLSL
|
|
#define xesl_constantBuffer_begin(name, glsl_set, glsl_binding, hlsl_b, \
|
|
hlsl_b_space) \
|
|
cbuffer name : register(hlsl_b, hlsl_b_space) {
|
|
#define xesl_constantBuffer_end(name) \
|
|
};
|
|
#define xesl_constant(cbuffer_name, constant_name) constant_name
|
|
#define xesl_pushConstants_begin(hlsl_b, hlsl_b_space) \
|
|
cbuffer xesl_pushConstants : register(hlsl_b, hlsl_b_space) {
|
|
#define xesl_pushConstants_end \
|
|
};
|
|
#define xesl_pushConstant(name) name
|
|
#elif XESL_LANGUAGE_MSL
|
|
#define xesl_constantBuffer_begin(name, glsl_set, glsl_binding, hlsl_b, \
|
|
hlsl_b_space) \
|
|
struct xesl_id_constantBuffer_##name {
|
|
#define xesl_constantBuffer_end(name) \
|
|
};
|
|
#define xesl_constantBuffer_binding(name, msl_buffer) \
|
|
constant xesl_id_constantBuffer_##name& name [[msl_buffer]]
|
|
#define xesl_constant(cbuffer_name, constant_name) cbuffer_name.constant_name
|
|
#define xesl_pushConstants_begin(hlsl_b, hlsl_b_space) \
|
|
struct xesl_pushConstants_struct {
|
|
#define xesl_pushConstants_end \
|
|
};
|
|
#define xesl_pushConstants_binding(msl_buffer) \
|
|
constant xesl_pushConstants_struct& xesl_pushConstants [[msl_buffer]]
|
|
#define xesl_pushConstant(name) xesl_pushConstants.name
|
|
#else
|
|
#error Constant buffers not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
#ifndef xesl_constantBuffer_binding
|
|
#define xesl_constantBuffer_binding(name, msl_buffer)
|
|
#endif // !xesl_constantBuffer_binding
|
|
#ifndef xesl_pushConstants_binding
|
|
#define xesl_pushConstants_binding(msl_buffer)
|
|
#endif // !xesl_pushConstants_binding
|
|
|
|
// Declarations of typed storage buffers and dword buffers (_declare) must be
|
|
// outside the entry point, but their bindings (_binding) must also be specified
|
|
// in the entry point binding declarations.
|
|
//
|
|
// xesl_typedStorageBuffer is a buffer limited to 1/2/4-component vectors of
|
|
// 32-bit integers and floats, a typed buffer on Direct3D, but a storage buffer
|
|
// (as opposed to a texel buffer, which has a very small minimum requirement for
|
|
// the maximum size) on Vulkan.
|
|
//
|
|
// xesl_uintVectorBuffer is a buffer containing 32-bit values, but loading or
|
|
// storing may be done for 2, 3 or 4 consecutive values that are still
|
|
// 32-bit-aligned, and depending on the language and hardware support, access
|
|
// of multiple elements may or may not be compiled into a single hardware
|
|
// instruction instead of separate accesses of individual elements. Each index
|
|
// value corresponds to a 32-bit element. Implementations for languages without
|
|
// native support must use functions, not macros, for adding the component
|
|
// offset to the index to avoid evaluating the address multiple times.
|
|
#if XESL_LANGUAGE_GLSL
|
|
// Binding declarations.
|
|
#define xesl_typedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_t, hlsl_t_space) \
|
|
layout(std430, glsl_set, glsl_binding) \
|
|
readonly buffer xesl_id_buffer_##name { \
|
|
value_type xesl_id_data[]; \
|
|
} name;
|
|
#define xesl_writeTypedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_u, \
|
|
hlsl_u_space) \
|
|
layout(std430, glsl_set, glsl_binding) \
|
|
writeonly buffer xesl_id_buffer_##name { \
|
|
value_type xesl_id_data[]; \
|
|
} name;
|
|
#define xesl_uintVectorBuffer_declare(name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space) \
|
|
layout(std430, glsl_set, glsl_binding) \
|
|
readonly buffer xesl_id_buffer_##name { \
|
|
uint xesl_id_data[]; \
|
|
} name; \
|
|
xesl_uint2 xesl_id_uintVectorBuffer_load2_##name( \
|
|
uint xesl_var_position) { \
|
|
return xesl_uint2(name.xesl_id_data[xesl_var_position], \
|
|
name.xesl_id_data[xesl_var_position + 1u]); \
|
|
} \
|
|
xesl_uint3 xesl_id_uintVectorBuffer_load3_##name( \
|
|
uint xesl_var_position) { \
|
|
return xesl_uint3(name.xesl_id_data[xesl_var_position], \
|
|
name.xesl_id_data[xesl_var_position + 1u], \
|
|
name.xesl_id_data[xesl_var_position + 2u]); \
|
|
} \
|
|
xesl_uint4 xesl_id_uintVectorBuffer_load4_##name( \
|
|
uint xesl_var_position) { \
|
|
return xesl_uint4(name.xesl_id_data[xesl_var_position], \
|
|
name.xesl_id_data[xesl_var_position + 1u], \
|
|
name.xesl_id_data[xesl_var_position + 2u], \
|
|
name.xesl_id_data[xesl_var_position + 3u]); \
|
|
}
|
|
// Loading and storing.
|
|
#define xesl_typedStorageBufferLoad(name, position) \
|
|
((name).xesl_id_data[uint(position)])
|
|
#define xesl_writeTypedStorageBufferStore(name, position, value) \
|
|
((name).xesl_id_data[uint(position)] = (value))
|
|
#define xesl_uintVectorBufferLoad1(name, position) \
|
|
((name).xesl_id_data[uint(position)])
|
|
#define xesl_uintVectorBufferLoad2(name, position) \
|
|
xesl_id_uintVectorBuffer_load2_##name(uint(position))
|
|
#define xesl_uintVectorBufferLoad3(name, position) \
|
|
xesl_id_uintVectorBuffer_load3_##name(uint(position))
|
|
#define xesl_uintVectorBufferLoad4(name, position) \
|
|
xesl_id_uintVectorBuffer_load4_##name(uint(position))
|
|
#elif XESL_LANGUAGE_HLSL
|
|
// Binding declarations.
|
|
#define xesl_typedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_t, hlsl_t_space) \
|
|
Buffer<value_type> name : register(hlsl_t, hlsl_t_space);
|
|
#define xesl_writeTypedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_u, \
|
|
hlsl_u_space) \
|
|
RWBuffer<value_type> name : register(hlsl_u, hlsl_u_space);
|
|
#define xesl_uintVectorBuffer_declare(name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space) \
|
|
ByteAddressBuffer name : register(hlsl_t, hlsl_t_space);
|
|
// Loading and storing.
|
|
#define xesl_typedStorageBufferLoad(name, position) ((name)[uint(position)])
|
|
#define xesl_writeTypedStorageBufferStore(name, position, value) \
|
|
((name)[uint(position)] = (value))
|
|
#define xesl_uintVectorBufferLoad1(name, position) \
|
|
((name).Load(int(position) << 2))
|
|
#define xesl_uintVectorBufferLoad2(name, position) \
|
|
((name).Load2(int(position) << 2))
|
|
#define xesl_uintVectorBufferLoad3(name, position) \
|
|
((name).Load3(int(position) << 2))
|
|
#define xesl_uintVectorBufferLoad4(name, position) \
|
|
((name).Load4(int(position) << 2))
|
|
#elif XESL_LANGUAGE_MSL
|
|
// Binding declarations.
|
|
#define xesl_typedStorageBuffer_binding(value_type, name, msl_buffer) \
|
|
const device value_type* name [[msl_buffer]]
|
|
#define xesl_writeTypedStorageBuffer_binding(value_type, name, msl_buffer) \
|
|
device value_type* name [[msl_buffer]]
|
|
#define xesl_uintVectorBuffer_binding(name, msl_buffer) \
|
|
const device uint* name [[msl_buffer]]
|
|
// Loading and storing.
|
|
#define xesl_typedStorageBufferLoad(name, position) ((name)[size_t(position)])
|
|
#define xesl_writeTypedStorageBufferStore(name, position, value) \
|
|
((name)[size_t(position)] = (value))
|
|
#define xesl_uintVectorBufferLoad1(name, position) ((name)[size_t(position)])
|
|
#define xesl_uintVectorBufferLoad2(name, position) \
|
|
xesl_uint2(*reinterpret_cast<const device packed_uint2*>( \
|
|
&((name)[size_t(position)])))
|
|
#define xesl_uintVectorBufferLoad3(name, position) \
|
|
xesl_uint3(*reinterpret_cast<const device packed_uint3*>( \
|
|
&((name)[size_t(position)])))
|
|
#define xesl_uintVectorBufferLoad4(name, position) \
|
|
xesl_uint4(*reinterpret_cast<const device packed_uint4*>( \
|
|
&((name)[size_t(position)])))
|
|
#else
|
|
#error Storage buffers not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
#ifndef xesl_typedStorageBuffer_declare
|
|
#define xesl_typedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_t, hlsl_t_space)
|
|
#endif // !xesl_typedStorageBuffer_declare
|
|
#ifndef xesl_writeTypedStorageBuffer_declare
|
|
#define xesl_writeTypedStorageBuffer_declare(value_type, name, glsl_set, \
|
|
glsl_binding, hlsl_u, \
|
|
hlsl_u_space)
|
|
#endif // !xesl_writeTypedStorageBuffer_declare
|
|
#ifndef xesl_typedStorageBuffer_binding
|
|
#define xesl_typedStorageBuffer_binding(value_type, name, msl_buffer)
|
|
#endif // !xesl_typedStorageBuffer_binding
|
|
#ifndef xesl_writeTypedStorageBuffer_binding
|
|
#define xesl_writeTypedStorageBuffer_binding(value_type, name, msl_buffer)
|
|
#endif // !xesl_writeTypedStorageBuffer_binding
|
|
#ifndef xesl_uintVectorBuffer_declare
|
|
#define xesl_uintVectorBuffer_declare(name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space)
|
|
#endif // !xesl_uintVectorBuffer_declare
|
|
#ifndef xesl_uintVectorBuffer_binding
|
|
#define xesl_uintVectorBuffer_binding(name, msl_buffer)
|
|
#endif // !xesl_uintVectorBuffer_binding
|
|
|
|
// Buffer, texture, sampler and image bindings must be in the entry point
|
|
// bindings declaration.
|
|
// - xesl_texture is a separate texture.
|
|
// - xesl_samplerState is a separate sampler.
|
|
// - xesl_sampler is a combined texture / sampler where available, internally
|
|
// separate where not.
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define XESL_COMBINED_TEXTURE_SAMPLER 1
|
|
// Types.
|
|
#define xesl_textureBuffer textureBuffer
|
|
#define xesl_utextureBuffer utextureBuffer
|
|
#define xesl_texture2D texture2D
|
|
#define xesl_texture2DMS texture2DMS
|
|
#define xesl_samplerBuffer samplerBuffer
|
|
#define xesl_usamplerBuffer usamplerBuffer
|
|
#define xesl_sampler2D sampler2D
|
|
#define xesl_image2D image2D
|
|
#define xesl_imageFormat_rgb10_a2 rgb10_a2
|
|
#define xesl_imageFormat_rgba16f rgba16f
|
|
// Binding declarations.
|
|
#define xesl_texture(texture_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, msl_texture) \
|
|
layout(glsl_set, glsl_binding) uniform texture_type name;
|
|
#define xesl_samplerState(name, glsl_set, glsl_binding, hlsl_s, \
|
|
hlsl_s_space, msl_sampler) \
|
|
layout(glsl_set, glsl_binding) uniform sampler name;
|
|
#define xesl_sampler(sampler_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, hlsl_s, hlsl_s_space, msl_texture, \
|
|
msl_sampler) \
|
|
layout(glsl_set, glsl_binding) uniform sampler_type name;
|
|
#define xesl_writeImage(type, format, name, glsl_set, glsl_binding, hlsl_u, \
|
|
hlsl_u_space, msl_texture) \
|
|
layout(format, glsl_set, glsl_binding) uniform writeonly type name;
|
|
// Fetching and storing.
|
|
#define xesl_texelFetchBuffer(texture_name, position) \
|
|
texelFetch(texture_name, int(position))
|
|
#define xesl_texelFetch2D(texture_name, position, lod) \
|
|
texelFetch(texture_name, xesl_int2(position), int(lod))
|
|
#define xesl_texelFetch2DMS(texture_name, position, sample_index) \
|
|
texelFetch(texture_name, xesl_int2(position), int(sample_index))
|
|
#define xesl_textureSampleLod2D_sep(texture_name, sampler_name, position, \
|
|
lod) \
|
|
textureLod(sampler2D(texture_name, sampler_name), position, lod)
|
|
#define xesl_textureSampleLod2D_comb(texture_sampler_name, position, lod) \
|
|
textureLod(texture_sampler_name, position, lod)
|
|
#define xesl_textureGatherRed2D_sep(texture_name, sampler_name, position) \
|
|
textureGather(sampler2D(texture_name, sampler_name), position, 0)
|
|
#define xesl_textureGatherGreen2D_sep(texture_name, sampler_name, position) \
|
|
textureGather(sampler2D(texture_name, sampler_name), position, 1)
|
|
#define xesl_textureGatherBlue2D_sep(texture_name, sampler_name, position) \
|
|
textureGather(sampler2D(texture_name, sampler_name), position, 2)
|
|
#define xesl_textureGatherAlpha2D_sep(texture_name, sampler_name, position) \
|
|
textureGather(sampler2D(texture_name, sampler_name), position, 3)
|
|
#define xesl_textureGatherRed2D_comb(texture_sampler_name, position) \
|
|
textureGather(texture_sampler_name, position, 0)
|
|
#define xesl_textureGatherGreen2D_comb(texture_sampler_name, position) \
|
|
textureGather(texture_sampler_name, position, 1)
|
|
#define xesl_textureGatherBlue2D_comb(texture_sampler_name, position) \
|
|
textureGather(texture_sampler_name, position, 2)
|
|
#define xesl_textureGatherAlpha2D_comb(texture_sampler_name, position) \
|
|
textureGather(texture_sampler_name, position, 3)
|
|
#define xesl_imageStore2DRGBA(name, position, data) \
|
|
imageStore(name, xesl_int2(position), data)
|
|
#elif XESL_LANGUAGE_HLSL
|
|
// Types.
|
|
#define xesl_textureBuffer Buffer<xesl_float4>
|
|
#define xesl_utextureBuffer Buffer<xesl_uint4>
|
|
#define xesl_texture2D Texture2D<xesl_float4>
|
|
#define xesl_texture2DMS Texture2DMS<xesl_float4>
|
|
#define xesl_image2D RWTexture2D
|
|
#define xesl_imageFormat_rgb10_a2 unorm float4
|
|
#define xesl_imageFormat_rgba16f float4
|
|
// Binding declarations.
|
|
#define xesl_texture(texture_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, msl_texture) \
|
|
texture_type name : register(hlsl_t, hlsl_t_space);
|
|
#define xesl_samplerState(name, glsl_set, glsl_binding, hlsl_s, \
|
|
hlsl_s_space, msl_sampler) \
|
|
SamplerState name : register(hlsl_s, hlsl_s_space);
|
|
#define xesl_writeImage(type, format, name, glsl_set, glsl_binding, hlsl_u, \
|
|
hlsl_u_space, msl_texture) \
|
|
type<format> name : register(hlsl_u, hlsl_u_space);
|
|
// Fetching and storing.
|
|
#define xesl_texelFetchBuffer(texture_name, position) \
|
|
((texture_name).Load(int(position)))
|
|
#define xesl_texelFetch2D(texture_name, position, lod) \
|
|
((texture_name).Load(xesl_int3(position, lod)))
|
|
#define xesl_texelFetch2DMS(texture_name, position, sample_index) \
|
|
((texture_name).Load(xesl_int2(position), int(sample_index)))
|
|
#define xesl_textureSampleLod2D_sep(texture_name, sampler_name, position, \
|
|
lod) \
|
|
((texture_name).SampleLevel(sampler_name, position, lod))
|
|
#define xesl_textureGatherRed2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).GatherRed(sampler_name, position))
|
|
#define xesl_textureGatherGreen2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).GatherGreen(sampler_name, position))
|
|
#define xesl_textureGatherBlue2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).GatherBlue(sampler_name, position))
|
|
#define xesl_textureGatherAlpha2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).GatherAlpha(sampler_name, position))
|
|
#define xesl_imageStore2DRGBA(name, position, data) \
|
|
((name)[xesl_int2(position)] = (data))
|
|
#elif XESL_LANGUAGE_MSL
|
|
// Types.
|
|
#define xesl_textureBuffer texture_buffer<float>
|
|
#define xesl_utextureBuffer texture_buffer<uint>
|
|
#define xesl_texture2D texture2d<float>
|
|
#define xesl_texture2DMS texture2d_ms<float>
|
|
#define xesl_image2D texture2d
|
|
#define xesl_imageFormat_rgb10_a2 float
|
|
#define xesl_imageFormat_rgba16f float
|
|
// Binding declarations.
|
|
#define xesl_texture(texture_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, msl_texture) \
|
|
texture_type name [[msl_texture]]
|
|
#define xesl_samplerState(name, glsl_set, glsl_binding, hlsl_s, \
|
|
hlsl_s_space, msl_sampler) \
|
|
sampler name [[msl_sampler]]
|
|
#define xesl_writeImage(type, format, name, glsl_set, glsl_binding, hlsl_u, \
|
|
hlsl_u_space, msl_texture) \
|
|
type<format, access::write> name [[msl_texture]]
|
|
// Fetching and storing.
|
|
#define xesl_texelFetchBuffer(texture_name, position) \
|
|
((texture_name).read(uint(position)))
|
|
#define xesl_texelFetch2D(texture_name, position, lod) \
|
|
((texture_name).read(xesl_uint2(position), uint(lod)))
|
|
#define xesl_texelFetch2DMS(texture_name, position, sample_index) \
|
|
((texture_name).read(xesl_uint2(position), uint(sample_index)))
|
|
#define xesl_textureSampleLod2D_sep(texture_name, sampler_name, position, \
|
|
lod) \
|
|
((texture_name).sample(sampler_name, position, level(lod)))
|
|
#define xesl_textureGatherRed2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).gather(sampler_name, position, xesl_int2(0), \
|
|
component::x))
|
|
#define xesl_textureGatherGreen2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).gather(sampler_name, position, xesl_int2(0), \
|
|
component::y))
|
|
#define xesl_textureGatherBlue2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).gather(sampler_name, position, xesl_int2(0), \
|
|
component::z))
|
|
#define xesl_textureGatherAlpha2D_sep(texture_name, sampler_name, position) \
|
|
((texture_name).gather(sampler_name, position, xesl_int2(0), \
|
|
component::w))
|
|
#define xesl_imageStore2DRGBA(name, position, data) \
|
|
((name).write(data, xesl_uint2(position)))
|
|
#else
|
|
#error Buffers and textures not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
// If there's no language specialization doing this already, implement combined
|
|
// textures / samplers as separate, with the `xesl_id_sampler_` prefix for
|
|
// samplers. The sampler types become the texture types.
|
|
#if !XESL_COMBINED_TEXTURE_SAMPLER
|
|
#ifndef xesl_sampler2D
|
|
#define xesl_sampler2D xesl_texture2D
|
|
#endif // !xesl_sampler2D
|
|
#ifndef xesl_sampler
|
|
#define xesl_sampler(sampler_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, hlsl_s, hlsl_s_space, msl_texture, \
|
|
msl_sampler) \
|
|
xesl_texture(sampler_type, name, glsl_set, glsl_binding, hlsl_t, \
|
|
hlsl_t_space, msl_texture) \
|
|
xesl_entry_binding_next \
|
|
xesl_samplerState(xesl_id_sampler_##name, glsl_set, glsl_binding, \
|
|
hlsl_s, hlsl_s_space, msl_sampler)
|
|
#endif // !xesl_sampler
|
|
#ifndef xesl_textureSampleLod2D_comb
|
|
#define xesl_textureSampleLod2D_comb(texture_sampler_name, position, lod) \
|
|
xesl_textureSampleLod2D_sep(texture_sampler_name, \
|
|
xesl_id_sampler_##texture_sampler_name, \
|
|
position, lod)
|
|
#endif // !xesl_textureSampleLod2D_comb
|
|
#ifndef xesl_textureGatherRed2D_comb
|
|
#define xesl_textureGatherRed2D_comb(texture_sampler_name, position) \
|
|
xesl_textureGatherRed2D_sep(texture_sampler_name, \
|
|
xesl_id_sampler_##texture_sampler_name, \
|
|
position)
|
|
#endif // !xesl_textureGatherRed2D_comb
|
|
#ifndef xesl_textureGatherGreen2D_comb
|
|
#define xesl_textureGatherGreen2D_comb(texture_sampler_name, position) \
|
|
xesl_textureGatherGreen2D_sep(texture_sampler_name, \
|
|
xesl_id_sampler_##texture_sampler_name, \
|
|
position)
|
|
#endif // !xesl_textureGatherGreen2D_comb
|
|
#ifndef xesl_textureGatherBlue2D_comb
|
|
#define xesl_textureGatherBlue2D_comb(texture_sampler_name, position) \
|
|
xesl_textureGatherBlue2D_sep(texture_sampler_name, \
|
|
xesl_id_sampler_##texture_sampler_name, \
|
|
position)
|
|
#endif // !xesl_textureGatherBlue2D_comb
|
|
#ifndef xesl_textureGatherAlpha2D_comb
|
|
#define xesl_textureGatherAlpha2D_comb(texture_sampler_name, position) \
|
|
xesl_textureGatherAlpha2D_sep(texture_sampler_name, \
|
|
xesl_id_sampler_##texture_sampler_name, \
|
|
position)
|
|
#endif // !xesl_textureGatherAlpha2D_comb
|
|
#endif // !XESL_COMBINED_TEXTURE_SAMPLER
|
|
|
|
// Passing bindings to functions, and also output and input / output parameters.
|
|
|
|
#if XESL_LANGUAGE_MSL
|
|
#define xesl_function_param_out(type, name) thread type& name
|
|
#define xesl_function_param_inout(type, name) thread type& name
|
|
#else
|
|
#define xesl_function_param_out(type, name) out type name
|
|
#define xesl_function_param_inout(type, name) inout type name
|
|
#endif // XESL_LANGUAGE_MSL
|
|
|
|
#if XESL_LANGUAGE_MSL
|
|
// Prototype parameters.
|
|
#define xesl_function_param_constantBuffer(name) \
|
|
constant xesl_id_constantBuffer_##name& name
|
|
#define xesl_function_param_next_after_constantBuffer ,
|
|
#define xesl_function_param_pushConstants \
|
|
constant xesl_pushConstants_struct& xesl_pushConstants
|
|
#define xesl_function_param_next_after_pushConstants ,
|
|
#define xesl_function_param_uintVectorBuffer(name) const device uint* name
|
|
#define xesl_function_param_next_after_uintVectorBuffer ,
|
|
// Call arguments.
|
|
#define xesl_function_call_constantBuffer(name) (name)
|
|
#define xesl_function_call_next_after_constantBuffer ,
|
|
#define xesl_function_call_pushConstants xesl_pushConstants
|
|
#define xesl_function_call_next_after_pushConstants ,
|
|
#define xesl_function_call_uintVectorBuffer(name) (name)
|
|
#define xesl_function_call_next_after_uintVectorBuffer ,
|
|
#endif // XESL_LANGUAGE
|
|
|
|
// Prototype parameters.
|
|
#ifndef xesl_function_param_constantBuffer
|
|
#define xesl_function_param_constantBuffer(name)
|
|
#endif // !xesl_function_param_constantBuffer
|
|
#ifndef xesl_function_param_next_after_constantBuffer
|
|
#define xesl_function_param_next_after_constantBuffer
|
|
#endif // !xesl_function_param_next_after_constantBuffer
|
|
#ifndef xesl_function_param_pushConstants
|
|
#define xesl_function_param_pushConstants
|
|
#endif // !xesl_function_param_pushConstants
|
|
#ifndef xesl_function_param_next_after_pushConstants
|
|
#define xesl_function_param_next_after_pushConstants
|
|
#endif // !xesl_function_param_next_after_pushConstants
|
|
#ifndef xesl_function_param_uintVectorBuffer
|
|
#define xesl_function_param_uintVectorBuffer(name)
|
|
#endif // !xesl_function_param_uintVectorBuffer
|
|
#ifndef xesl_function_param_next_after_uintVectorBuffer
|
|
#define xesl_function_param_next_after_uintVectorBuffer
|
|
#endif // !xesl_function_param_next_after_uintVectorBuffer
|
|
// Call arguments.
|
|
#ifndef xesl_function_call_constantBuffer
|
|
#define xesl_function_call_constantBuffer(name)
|
|
#endif // !xesl_function_call_constantBuffer
|
|
#ifndef xesl_function_call_next_after_constantBuffer
|
|
#define xesl_function_call_next_after_constantBuffer
|
|
#endif // !xesl_function_call_next_after_constantBuffer
|
|
#ifndef xesl_function_call_pushConstants
|
|
#define xesl_function_call_pushConstants
|
|
#endif // !xesl_function_call_pushConstants
|
|
#ifndef xesl_function_call_next_after_pushConstants
|
|
#define xesl_function_call_next_after_pushConstants
|
|
#endif // !xesl_function_call_next_after_pushConstants
|
|
#ifndef xesl_function_call_uintVectorBuffer
|
|
#define xesl_function_call_uintVectorBuffer(name)
|
|
#endif // !xesl_function_call_uintVectorBuffer
|
|
#ifndef xesl_function_call_next_after_uintVectorBuffer
|
|
#define xesl_function_call_next_after_uintVectorBuffer
|
|
#endif // !xesl_function_call_next_after_uintVectorBuffer
|
|
|
|
// Attributes.
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_unroll [[unroll]]
|
|
#define xesl_dont_unroll [[dont_unroll]]
|
|
#define xesl_flatten [[flatten]]
|
|
#define xesl_dont_flatten [[dont_flatten]]
|
|
#elif XESL_LANGUAGE_HLSL
|
|
#define xesl_unroll [unroll]
|
|
#define xesl_dont_unroll [loop]
|
|
#define xesl_flatten [flatten]
|
|
#define xesl_dont_flatten [branch]
|
|
#endif // XESL_LANGUAGE
|
|
#ifndef xesl_unroll
|
|
#define xesl_unroll
|
|
#endif // !xesl_unroll
|
|
#ifndef xesl_dont_unroll
|
|
#define xesl_dont_unroll
|
|
#endif // !xesl_dont_unroll
|
|
#ifndef xesl_flatten
|
|
#define xesl_flatten
|
|
#endif // !xesl_flatten
|
|
#ifndef xesl_dont_flatten
|
|
#define xesl_dont_flatten
|
|
#endif // !xesl_dont_flatten
|
|
|
|
// Function aliases.
|
|
//
|
|
// Use the `xesl_var_` prefix for arguments of functions that are not macros and
|
|
// for local variables.
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_lessThan lessThan
|
|
#define xesl_lessThanEqual lessThanEqual
|
|
#define xesl_greaterThan greaterThan
|
|
#define xesl_greaterThanEqual greaterThanEqual
|
|
#define xesl_equal equal
|
|
#define xesl_notEqual notEqual
|
|
#define xesl_not not
|
|
#define xesl_select(condition, true_result, false_result) \
|
|
mix(false_result, true_result, condition)
|
|
#elif XESL_LANGUAGE_HLSL
|
|
#define xesl_lessThan(x, y) ((x) < (y))
|
|
#define xesl_lessThanEqual(x, y) ((x) <= (y))
|
|
#define xesl_greaterThan(x, y) ((x) > (y))
|
|
#define xesl_greaterThanEqual(x, y) ((x) >= (y))
|
|
#define xesl_equal(x, y) ((x) == (y))
|
|
#define xesl_notEqual(x, y) ((x) != (y))
|
|
#define xesl_not(x) (!(x))
|
|
#define xesl_select(condition, true_result, false_result) \
|
|
((condition) ? (true_result) : (false_result))
|
|
#elif XESL_LANGUAGE_MSL
|
|
#define xesl_lessThan(x, y) ((x) < (y))
|
|
#define xesl_lessThanEqual(x, y) ((x) <= (y))
|
|
#define xesl_greaterThan(x, y) ((x) > (y))
|
|
#define xesl_greaterThanEqual(x, y) ((x) >= (y))
|
|
#define xesl_equal(x, y) ((x) == (y))
|
|
#define xesl_notEqual(x, y) ((x) != (y))
|
|
#define xesl_not(x) (!(x))
|
|
#define xesl_select(condition, true_result, false_result) \
|
|
select(false_result, true_result, condition)
|
|
#else
|
|
#error Comparison operations not defined for the target language.
|
|
#endif
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_floatBitsToInt floatBitsToInt
|
|
#define xesl_floatBitsToUint floatBitsToUint
|
|
#define xesl_intBitsToFloat intBitsToFloat
|
|
#define xesl_uintBitsToFloat uintBitsToFloat
|
|
#elif XESL_LANGUAGE_HLSL
|
|
// Using functions instead of #define for implicit argument conversion.
|
|
int xesl_floatBitsToInt(float xesl_var_value) {
|
|
return asint(xesl_var_value);
|
|
}
|
|
xesl_int2 xesl_floatBitsToInt(xesl_float2 xesl_var_value) {
|
|
return asint(xesl_var_value);
|
|
}
|
|
xesl_int3 xesl_floatBitsToInt(xesl_float3 xesl_var_value) {
|
|
return asint(xesl_var_value);
|
|
}
|
|
xesl_int4 xesl_floatBitsToInt(xesl_float4 xesl_var_value) {
|
|
return asint(xesl_var_value);
|
|
}
|
|
uint xesl_floatBitsToUint(float xesl_var_value) {
|
|
return asuint(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_floatBitsToUint(xesl_float2 xesl_var_value) {
|
|
return asuint(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_floatBitsToUint(xesl_float3 xesl_var_value) {
|
|
return asuint(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_floatBitsToUint(xesl_float4 xesl_var_value) {
|
|
return asuint(xesl_var_value);
|
|
}
|
|
float xesl_intBitsToFloat(int xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float2 xesl_intBitsToFloat(xesl_int2 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float3 xesl_intBitsToFloat(xesl_int3 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float4 xesl_intBitsToFloat(xesl_int4 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
float xesl_uintBitsToFloat(uint xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float2 xesl_uintBitsToFloat(xesl_uint2 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float3 xesl_uintBitsToFloat(xesl_uint3 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
xesl_float4 xesl_uintBitsToFloat(xesl_uint4 xesl_var_value) {
|
|
return asfloat(xesl_var_value);
|
|
}
|
|
#elif XESL_LANGUAGE_MSL
|
|
// Using functions instead of #define for implicit argument conversion.
|
|
int xesl_floatBitsToInt(float xesl_var_value) {
|
|
return as_type<int>(xesl_var_value);
|
|
}
|
|
xesl_int2 xesl_floatBitsToInt(xesl_float2 xesl_var_value) {
|
|
return as_type<xesl_int2>(xesl_var_value);
|
|
}
|
|
xesl_int3 xesl_floatBitsToInt(xesl_float3 xesl_var_value) {
|
|
return as_type<xesl_int3>(xesl_var_value);
|
|
}
|
|
xesl_int4 xesl_floatBitsToInt(xesl_float4 xesl_var_value) {
|
|
return as_type<xesl_int4>(xesl_var_value);
|
|
}
|
|
uint xesl_floatBitsToUint(float xesl_var_value) {
|
|
return as_type<uint>(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_floatBitsToUint(xesl_float2 xesl_var_value) {
|
|
return as_type<xesl_uint2>(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_floatBitsToUint(xesl_float3 xesl_var_value) {
|
|
return as_type<xesl_uint3>(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_floatBitsToUint(xesl_float4 xesl_var_value) {
|
|
return as_type<xesl_uint4>(xesl_var_value);
|
|
}
|
|
float xesl_intBitsToFloat(int xesl_var_value) {
|
|
return as_type<float>(xesl_var_value);
|
|
}
|
|
xesl_float2 xesl_intBitsToFloat(xesl_int2 xesl_var_value) {
|
|
return as_type<xesl_float2>(xesl_var_value);
|
|
}
|
|
xesl_float3 xesl_intBitsToFloat(xesl_int3 xesl_var_value) {
|
|
return as_type<xesl_float3>(xesl_var_value);
|
|
}
|
|
xesl_float4 xesl_intBitsToFloat(xesl_int4 xesl_var_value) {
|
|
return as_type<xesl_float4>(xesl_var_value);
|
|
}
|
|
float xesl_uintBitsToFloat(uint xesl_var_value) {
|
|
return as_type<float>(xesl_var_value);
|
|
}
|
|
xesl_float2 xesl_uintBitsToFloat(xesl_uint2 xesl_var_value) {
|
|
return as_type<xesl_float2>(xesl_var_value);
|
|
}
|
|
xesl_float3 xesl_uintBitsToFloat(xesl_uint3 xesl_var_value) {
|
|
return as_type<xesl_float3>(xesl_var_value);
|
|
}
|
|
xesl_float4 xesl_uintBitsToFloat(xesl_uint4 xesl_var_value) {
|
|
return as_type<xesl_float4>(xesl_var_value);
|
|
}
|
|
#else
|
|
#error Float bit casting not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
float xesl_saturate(float xesl_var_value) {
|
|
return clamp(xesl_var_value, 0.0, 1.0);
|
|
}
|
|
xesl_float2 xesl_saturate(xesl_float2 xesl_var_value) {
|
|
return clamp(xesl_var_value, xesl_float_x2(0.0), xesl_float_x2(1.0));
|
|
}
|
|
xesl_float3 xesl_saturate(xesl_float3 xesl_var_value) {
|
|
return clamp(xesl_var_value, xesl_float_x3(0.0), xesl_float_x3(1.0));
|
|
}
|
|
xesl_float4 xesl_saturate(xesl_float4 xesl_var_value) {
|
|
return clamp(xesl_var_value, xesl_float_x4(0.0), xesl_float_x4(1.0));
|
|
}
|
|
#else
|
|
#define xesl_saturate saturate
|
|
#endif // XESL_LANGUAGE_GLSL
|
|
|
|
// Returning a unsigned integer vector. The result is undefined for zero.
|
|
#if XESL_LANGUAGE_GLSL
|
|
uint xesl_firstOneBitLow(int xesl_var_value) {
|
|
return uint(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_int2 xesl_var_value) {
|
|
return xesl_uint2(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_int3 xesl_var_value) {
|
|
return xesl_uint3(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_int4 xesl_var_value) {
|
|
return xesl_uint4(findLSB(xesl_var_value));
|
|
}
|
|
uint xesl_firstOneBitLow(uint xesl_var_value) {
|
|
return uint(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_uint2 xesl_var_value) {
|
|
return xesl_uint2(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_uint3 xesl_var_value) {
|
|
return xesl_uint3(findLSB(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_uint4 xesl_var_value) {
|
|
return xesl_uint4(findLSB(xesl_var_value));
|
|
}
|
|
// GLSL findMSB finds the highest 0 for a negative value.
|
|
uint xesl_firstOneBitHigh(int xesl_var_value) {
|
|
return uint(findMSB(uint(xesl_var_value)));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_int2 xesl_var_value) {
|
|
return xesl_uint2(findMSB(xesl_uint2(xesl_var_value)));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_int3 xesl_var_value) {
|
|
return xesl_uint3(findMSB(xesl_uint3(xesl_var_value)));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_int4 xesl_var_value) {
|
|
return xesl_uint4(findMSB(xesl_uint4(xesl_var_value)));
|
|
}
|
|
uint xesl_firstOneBitHigh(uint xesl_var_value) {
|
|
return uint(findMSB(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_uint2 xesl_var_value) {
|
|
return xesl_uint2(findMSB(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_uint3 xesl_var_value) {
|
|
return xesl_uint3(findMSB(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_uint4 xesl_var_value) {
|
|
return xesl_uint4(findMSB(xesl_var_value));
|
|
}
|
|
#elif XESL_LANGUAGE_HLSL
|
|
uint xesl_firstOneBitLow(int xesl_var_value) {
|
|
return uint(firstbitlow(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_int2 xesl_var_value) {
|
|
return xesl_uint2(firstbitlow(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_int3 xesl_var_value) {
|
|
return xesl_uint3(firstbitlow(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_int4 xesl_var_value) {
|
|
return xesl_uint4(firstbitlow(xesl_var_value));
|
|
}
|
|
uint xesl_firstOneBitLow(uint xesl_var_value) {
|
|
return firstbitlow(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_uint2 xesl_var_value) {
|
|
return firstbitlow(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_uint3 xesl_var_value) {
|
|
return firstbitlow(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_uint4 xesl_var_value) {
|
|
return firstbitlow(xesl_var_value);
|
|
}
|
|
// HLSL firstbithigh finds the highest 0 for a negative value.
|
|
uint xesl_firstOneBitHigh(int xesl_var_value) {
|
|
return uint(firstbithigh(uint(xesl_var_value)));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_int2 xesl_var_value) {
|
|
return xesl_uint2(firstbithigh(xesl_uint2(xesl_var_value)));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_int3 xesl_var_value) {
|
|
return xesl_uint3(firstbithigh(xesl_uint3(xesl_var_value)));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_int4 xesl_var_value) {
|
|
return xesl_uint4(firstbithigh(xesl_uint4(xesl_var_value)));
|
|
}
|
|
uint xesl_firstOneBitHigh(uint xesl_var_value) {
|
|
return firstbithigh(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_uint2 xesl_var_value) {
|
|
return firstbithigh(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_uint3 xesl_var_value) {
|
|
return firstbithigh(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_uint4 xesl_var_value) {
|
|
return firstbithigh(xesl_var_value);
|
|
}
|
|
#elif XESL_LANGUAGE_MSL
|
|
uint xesl_firstOneBitLow(int xesl_var_value) {
|
|
return uint(ctz(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_int2 xesl_var_value) {
|
|
return xesl_uint2(ctz(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_int3 xesl_var_value) {
|
|
return xesl_uint3(ctz(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_int4 xesl_var_value) {
|
|
return xesl_uint4(ctz(xesl_var_value));
|
|
}
|
|
uint xesl_firstOneBitLow(uint xesl_var_value) {
|
|
return ctz(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_firstOneBitLow(xesl_uint2 xesl_var_value) {
|
|
return ctz(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_firstOneBitLow(xesl_uint3 xesl_var_value) {
|
|
return ctz(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_firstOneBitLow(xesl_uint4 xesl_var_value) {
|
|
return ctz(xesl_var_value);
|
|
}
|
|
uint xesl_firstOneBitHigh(int xesl_var_value) {
|
|
return 32u - uint(clz(xesl_var_value));
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_int2 xesl_var_value) {
|
|
return xesl_uint_x2(32u) - xesl_uint2(clz(xesl_var_value));
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_int3 xesl_var_value) {
|
|
return xesl_uint_x3(32u) - xesl_uint3(clz(xesl_var_value));
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_int4 xesl_var_value) {
|
|
return xesl_uint_x4(32u) - xesl_uint4(clz(xesl_var_value));
|
|
}
|
|
uint xesl_firstOneBitHigh(uint xesl_var_value) {
|
|
return 32u - clz(xesl_var_value);
|
|
}
|
|
xesl_uint2 xesl_firstOneBitHigh(xesl_uint2 xesl_var_value) {
|
|
return xesl_uint_x2(32u) - clz(xesl_var_value);
|
|
}
|
|
xesl_uint3 xesl_firstOneBitHigh(xesl_uint3 xesl_var_value) {
|
|
return xesl_uint_x3(32u) - clz(xesl_var_value);
|
|
}
|
|
xesl_uint4 xesl_firstOneBitHigh(xesl_uint4 xesl_var_value) {
|
|
return xesl_uint_x4(32u) - clz(xesl_var_value);
|
|
}
|
|
#else
|
|
#error Bit count operations not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
|
|
#if XESL_LANGUAGE_GLSL
|
|
#define xesl_packHalf2x16 packHalf2x16
|
|
#define xesl_unpackHalf2x16 unpackHalf2x16
|
|
#elif XESL_LANGUAGE_HLSL
|
|
uint xesl_packHalf2x16(xesl_float2 xesl_var_value) {
|
|
return f32tof16(xesl_var_value.x) | (f32tof16(xesl_var_value.y) << 16u);
|
|
}
|
|
xesl_float2 xesl_unpackHalf2x16(uint xesl_var_value) {
|
|
return f16tof32(xesl_uint_x2(xesl_var_value) >> xesl_uint2(0u, 16u));
|
|
}
|
|
#elif XESL_LANGUAGE_MSL
|
|
uint xesl_packHalf2x16(xesl_float2 xesl_var_value) {
|
|
return uint(as_type<ushort>(half(xesl_var_value.x))) |
|
|
(uint(as_type<ushort>(half(xesl_var_value.y))) << 16u);
|
|
}
|
|
xesl_float2 xesl_unpackHalf2x16(uint xesl_var_value) {
|
|
return xesl_float2(as_type<half2>(ushort2(
|
|
xesl_uint_x2(xesl_var_value) >> xesl_uint2(0u, 16u))));
|
|
}
|
|
#else
|
|
#error xesl_packHalf2x16 not defined for the target language.
|
|
#endif // XESL_LANGUAGE
|
|
|
|
#endif // XENIA_UI_SHADERS_XESL_XESLI_
|