Runtime reference

shdr 1.0.0 API reference

A C++11 header for CPU and GPU compute pipelines. The build helper turns native GLSL into CPU adapters and embeds GPU source. Applications create kernels, bind resources and run dispatches. Read or download the single-file runtime header.

Start with the walkthrough. Read about resources and bindings, supported shader features, asynchronous execution, imaging, event-camera processing, neural models, signal processing and public data. The example catalog connects each complete program to its kernels.

BackendMinimum requirement
CPUC++11 compiler and host resources.
OpenGL ESES 3.1 with GLSL ES 3.10, or ES 3.2 with GLSL ES 3.20.
Desktop OpenGLGL 4.3 with GLSL 4.30, or a newer supported profile.

Enable SHDR_ENABLE_EGL=1 and link EGL to create a headless GPU device. An existing application context can supply its own function resolver. GPU calls and final resource release use the context thread. The runtime handles transfers, dispatches, fence polling and bounded CPU work queues.

175 documented declarations.

Build integration and shader exports

#define SHDR_VERSION_MINOR

Minor version within the current major release.

shdr.h, line 1705
#define SHDR_VERSION_PATCH

Patch version within the current minor release.

shdr.h, line 1707
struct error : std::runtime_error

A shader, resource, context or dispatch validation failure.

shdr.h, line 1732
struct extent

Three unsigned dimensions. dispatch dimensions count work groups.

shdr.h, line 1738
explicit extent(unsigned x_ = 1, unsigned y_ = 1, unsigned z_ = 1) : x(x_), y(y_), z(z_)

Construct three workgroup counts, defaulting each dimension to one.

shdr.h, line 1741
enum class profile { es31, es32, gl43, gl45, gl46 };

Minimum shader language selected independently of the context's actual version.

shdr.h, line 1745
explicit device(const std::function<void*(const char*)>& resolver, profile p = profile::es31)
        : state_(std::make_shared<detail::device_state>(resolver, p))

Load GL entry points and validate the current context against a profile.
Parameter resolver: Callable returning the address of a named GL function, or null.
Parameter p: Minimum GLSL and GL/ES profile. defaults to ES 3.1.
Throws: error If function resolution or current-context validation fails.

shdr.h, line 2542
virtual ~device() noexcept

Release deferred completion handles through context-thread cleanup.
Destroy devices on their context thread after CPU workers have stopped.

shdr.h, line 2550
profile shader_profile() const

Return the shader language profile selected for this device.

shdr.h, line 2563
unsigned gl_handle(device& d)

Obtain the synchronized GL SSBO handle for application interop.

shdr.h, line 2665
unsigned gl_handle(device& d)

Obtain the synchronized level-zero GL texture handle for application interop.

shdr.h, line 2745
void mark_gpu_modified(device& d)

Notify shdr after the application writes the GL texture. its context must be current.

shdr.h, line 2750
extent local_size() const

Return the fixed local workgroup dimensions declared by SHDR_BEGIN.

shdr.h, line 2868
std::string glsl(profile p) const

Export this shader's automatically embedded source for compiler diagnostics or tooling.

shdr.h, line 2872
void prepare(device& d);

Compile and allocate GPU resources before entering a latency-sensitive dispatch loop.

shdr.h, line 2907
void run() const

Run automatic and CPU stages on the CPU. explicit GPU stages need a device.

shdr.h, line 3351
void run(device& d) const

Run automatic and GPU stages on the device, respecting explicit CPU stages.
Host readback completes queued GPU writes when resource data is requested.

shdr.h, line 3355
submission submit(device& d) const;

Enqueue GPU stages and return a fence for zero-timeout completion polls.

shdr.h, line 3367

Resources and synchronization

template <class T, std::size_t N> class array

A fixed-size array for GLSL local variables and function arguments.
The size must be positive. Default construction initializes every element to
its zero/default value. component construction requires exactly N elements.
Copy construction and assignment copy all elements. Use length() to query
the element count and operator[] to select an element with a valid index.
Resource ports define buffer and uniform memory layouts separately.

shdr.h, line 196
enum class access { readonly, writeonly, readwrite };

Resource access qualifiers. readonly also prevents CPU writes at compile time.

shdr.h, line 1749
template <class T> class buffer

Shared typed std430 storage, owned or borrowed, with automatic CPU/GPU synchronization.
Copying a buffer shares its storage. Mutable data() marks host data authoritative.
Obtain a fresh data() pointer after a GPU dispatch before accessing host values.
GPU handles belong to one device.

shdr.h, line 2591
explicit buffer(std::size_t n = 0) : state_(std::make_shared<detail::buffer_state<T>>(n))

Allocate a zero-initialized host buffer containing n elements.
GPU storage is allocated lazily. Zero-length buffers are valid on the CPU.
GPU storage-buffer bindings require at least one element.

shdr.h, line 2604
buffer(T* p, std::size_t n) : state_(std::make_shared<detail::buffer_state<T>>(p, n))

Borrow n elements stored in application-owned host memory.
Keep the memory alive while any resource copy or shader port retains it.
Call mark_host_modified() after writing through the original pointer.

shdr.h, line 2613
buffer(std::initializer_list<T> values) : buffer(values.size())

Allocate owned host storage and copy an initializer list into it.

shdr.h, line 2622
void upload(device& d)

Ensure this device has the latest contents, allocating or uploading as needed.

shdr.h, line 2655
void download(device& d)

Download newer GPU contents. reject a different owning device.

shdr.h, line 2659
void mark_gpu_modified(device& d)

Notify shdr after the application writes the GL buffer. its context must be current.

shdr.h, line 2670
static buffer from_gl(device& d, unsigned handle, std::size_t count)

Borrow an existing SSBO. Its contents initially belong to the GPU. caller retains ownership.

shdr.h, line 2682
template <class T, unsigned C = 1> class image2d

Interleaved 32-bit scalar or RGBA image shared between CPU and GPU.
C is 1 or 4. T is float, int, or unsigned. Use matching r32f/r32i/r32ui or
rgba32f/rgba32i/rgba32ui GLSL declarations. Copies and bound ports alias storage.

shdr.h, line 2699
image2d(unsigned w, unsigned h) : state_(std::make_shared<detail::image_state<T>>(w, h, C))

Allocate a zero-initialized image with positive width and height in pixels.

shdr.h, line 2710
void upload(device& d)

Ensure this device has the latest pixels, allocating or uploading as needed.

shdr.h, line 2735
void download(device& d)

Download newer GPU pixels through a portable compute-to-buffer copy.

shdr.h, line 2739
static image2d from_gl(device& d, unsigned handle, unsigned w, unsigned h)

Borrow a matching immutable-format, level-zero 2D GL texture. caller retains ownership.

shdr.h, line 2760
template <class T, access A = access::readwrite> class buffer_port : public detail::port_base

Typed shader SSBO declaration. assign a buffer to bind or rebind it.

shdr.h, line 2918
buffer_port& operator=(const buffer<T>& b)

Bind or rebind this port to the buffer's retained shared storage.

shdr.h, line 2928
unsigned length() const

Return the bound buffer's element count, matching GLSL array length().

shdr.h, line 2939
typename std::conditional<A == access::readonly, const T&, T&>::type operator[](std::size_t i)

Access an element during CPU execution, checking bounds and declared access.
Readonly ports return const references. Pipeline execution synchronizes host contents.

shdr.h, line 2944
template <class T, unsigned C, access A> class image_port : public detail::port_base

A typed image declaration with format/access matching its shared shader.

shdr.h, line 3066
image_port& operator=(const image2d<T, C>& image)

Bind or rebind this port to the image's retained shared storage.

shdr.h, line 3075
template <class T, unsigned C, access A>
inline glsl::ivec2 imageSize(const image_port<T, C, A>& image)

GLSL image dimensions in pixels.

shdr.h, line 3113
template <class T, unsigned C, access A>
inline glsl::vec<T, 4> imageLoad(const image_port<T, C, A>& image, glsl::ivec2 pos)

Load one texel. Missing RGB components are zero and missing alpha is one.
Out-of-range coordinates return zero. loading a writeonly image is a compile error.

shdr.h, line 3118
template <class T, unsigned C, access A>
inline void imageStore(image_port<T, C, A>& image, glsl::ivec2 pos, const glsl::vec<T, 4>& value)

Store a texel, ignoring out-of-range coordinates. Readonly stores are a compile error.

shdr.h, line 3136
void prepare(device& d) const

Compile GPU programs and upload resources before steady-state submission.

shdr.h, line 3361

Kernels and dispatch

enum class backend { automatic, cpu, gpu };

Automatic uses CPU execution for run() and GPU execution for run(device).

shdr.h, line 1747
class kernel

Base for compiled shader objects, owning resource declarations and invocation builtins.
Shader objects are neither copyable nor movable because their ports refer to their instance.
CMake-generated adapters embed their native GLSL source automatically.

shdr.h, line 2802
kernel(const std::string& name, extent local)
        : name_(name), local_(local), gl_LocalInvocationIndex(0)

Construct a kernel identity and positive local workgroup dimensions.
SHDR_BEGIN emits this constructor for shared shader classes.

shdr.h, line 2822
virtual std::unique_ptr<kernel> clone() const

Make an independent shader instance with a snapshot of its resource bindings and uniforms.

shdr.h, line 2839
template <class T> kernel& bind(const std::string& name, const buffer<T>& resource);

Bind by name, for runtime-selected shader modules. Type mismatches throw error.

shdr.h, line 2889
template <class T, unsigned C>
    kernel& bind(const std::string& name, const image2d<T, C>& resource);

Bind an image by name. scalar type and component count must match its port.

shdr.h, line 2891
template <class T> kernel& set(const std::string& name, const T& value);

Assign a uniform by name. T must exactly match its declared shader type.

shdr.h, line 2894
buffer_port(kernel& p, unsigned b, const char* n, unsigned fixed = 0)
        : port_base(p, n, b, A, detail::port_kind::buffer), fixed_length_(fixed)

Declare a typed buffer port on a kernel, usually through SHDR_BUFFER.

shdr.h, line 2924
uniform_port(kernel& p, const char* n)
        : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(),
          value_(&owned_)

Declare a zero-initialized uniform backed by this port's own value.

shdr.h, line 3030
uniform_port(kernel& p, const char* n, T& value)
        : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(),
          value_(&value)

Register an existing typed kernel field as a uniform. emitted by SHDR_UNIFORM.

shdr.h, line 3035
image_port(kernel& p, unsigned b, const char* n)
        : port_base(p, n, b, A, detail::port_kind::image)

Declare an image port, usually through SHDR_IMAGE2D.

shdr.h, line 3071
struct stage

One dispatch retaining a reference to its shader. Keep that shader alive during execution.

shdr.h, line 3284
stage(kernel& k, extent g, backend b) : shader(&k), groups(g), target(b)

Retain a kernel reference with workgroup counts and a backend override.

shdr.h, line 3290
inline stage dispatch(kernel& shader, extent groups, backend b = backend::automatic)

Build a dispatch using work group counts, with an optional per-stage backend override.

shdr.h, line 3299
inline stage
dispatch(std::shared_ptr<kernel> shader, extent groups, backend b = backend::automatic)

Build a dispatch that also retains ownership of its shader.

shdr.h, line 3303

Pipelines and dynamic libraries

virtual void main() = 0;

Execute one CPU invocation. SHDR_MAIN supplies the override.
Dispatch through a stage or pipeline to initialize builtins and synchronize resources.

shdr.h, line 2835
void run(extent groups, device* d);

Execute one dispatch with workgroup counts on a device, or on the CPU if null.
Normally called by pipeline.run(). GPU work uses the embedded shader and a current context.

shdr.h, line 2903
class pipeline

An ordered pipeline, composed with >> or +=. Resources link stages by shared storage.
GPU stages issue memory barriers. CPU/GPU transitions transfer authoritative resource contents.
Running again observes updated uniforms and resource bindings. CPU execution
completes each stage before returning. GPU execution queues stages in order.
Request host data or use an explicit wait to observe GPU completion.

shdr.h, line 3311
pipeline()

Construct an empty pipeline. append dispatches with operator+=.

shdr.h, line 3329
pipeline& operator+=(stage s)

Append a dispatch in execution order and return this pipeline.

shdr.h, line 3336
pipeline& operator+=(const pipeline& other)

Append every dispatch from another pipeline, including a safe copy of this pipeline.

shdr.h, line 3341
pipeline snapshot() const

Snapshot shader instances, uniforms and bindings for deferred CPU execution.

shdr.h, line 3373
inline pipeline operator>>(stage a, stage b)

Compose ordered stages into a reusable pipeline.

shdr.h, line 3399
inline pipeline operator>>(pipeline p, stage b)

Append a stage to a pipeline value, retaining references to the same kernels.

shdr.h, line 3405
inline pipeline operator>>(stage a, const pipeline& b)

Prepend a stage to a pipeline while retaining the same linked shader resources.

shdr.h, line 3410
inline pipeline operator>>(pipeline a, const pipeline& b)

Join two complete processing pipelines in execution order.

shdr.h, line 3416
inline std::unique_ptr<kernel> make_kernel(const std::string& name)

Create a shader compiled and embedded by shdr_target_shaders during the CMake build.
A file named scale.cpp registers scale_kernel. The returned instance owns its CPU/GPU program
and exposes resource binding through bind() and set(). Both programs are part of the binary.
Unknown or ambiguous names throw error. Call from one application thread after startup.

shdr.h, line 3453

Asynchronous execution

enum class wait_status { ready, timeout };

Result of a completion query: completed work or an expired timeout.

shdr.h, line 3501
class submission

A movable handle for one queued GPU pipeline.
ready() performs a zero-timeout fence query. wait(timeout) bounds the requested
driver wait. wait() explicitly waits for completion. Destroying a handle
schedules pending fence and resource cleanup on the device context thread.
Device garbage collection releases those retained resources after completion.
Keep the GL context alive until retained work and resources have been retired.

shdr.h, line 3566
bool valid() const

Return whether this handle represents submitted GPU commands.

shdr.h, line 3588
bool ready()

Query completion with a zero timeout on the device context thread.

shdr.h, line 3592
wait_status wait(std::chrono::nanoseconds timeout)

Request a driver wait with a nonnegative timeout in nanoseconds.

shdr.h, line 3596
wait_status wait()

Explicitly wait until submitted commands complete.

shdr.h, line 3604
inline submission pipeline::submit(device& d) const

Enqueue all GPU stages and return a fence for polling or explicit waits.
Each stage must support GPU execution. Call prepare()
before entering a latency-sensitive loop to compile shaders and allocate/upload
resources in advance. Subsequent host edits can still require an upload.
Uniform and binding changes after return affect subsequent submissions.

shdr.h, line 3615
class executor

A bounded CPU executor for independent pipeline jobs.
Each submit() snapshots kernels, uniforms and resource bindings. Snapshots
have independent invocation state, while buffers and images retain shared
storage. Give concurrent jobs distinct writable resources, such as ring slots.
Queue saturation throws immediately. Futures report results or exceptions.
Destroying a future releases its result handle, while the executor retains
the job until completion. shutdown() drains accepted jobs and joins workers.
Executor destruction also drains and joins them.

shdr.h, line 3657
explicit executor(std::size_t workers = 1, std::size_t capacity = 64)
        : state_(std::make_shared<queue_state>(capacity))

Start workers with room for at most capacity pending jobs.
Capacity counts jobs waiting for a worker. Both arguments must be positive.

shdr.h, line 3738
std::future<void> submit(const pipeline& source)

Snapshot a host-ready CPU pipeline, enqueue it and return a future.
Each stage must support CPU execution and have current host data.

shdr.h, line 3765
template <class Function> std::future<void> enqueue(Function function)

Enqueue an application CPU function on the same bounded queue.
Run host operations in the callback and keep device operations on their context thread.

shdr.h, line 3781
std::size_t pending() const

Return the count of queued or currently being constructed jobs.

shdr.h, line 3793
std::size_t capacity() const

Return the maximum number of pending jobs.

shdr.h, line 3798
void shutdown()

Drain accepted jobs and join all workers. later submissions fail.
Call from an application thread so it can join every worker.

shdr.h, line 3806

Headless EGL backend

class device

An application's current GL context, accessed through its function resolver.
The context must remain current on this thread during operations and destruction of GL objects.
The default header uses standard C++11 declarations. The optional
headless_device supplies EGL context creation when SHDR_ENABLE_EGL is enabled.

shdr.h, line 2533
class backend_unavailable : public error

The requested graphics backend or context is unavailable.
This exception identifies display, configuration, context and GL entry-point
failures. Shader compilation and dispatch errors remain ordinary shdr::error.

shdr.h, line 3839
explicit backend_unavailable(const std::string& message) : error(message)

Describe the unavailable graphics infrastructure.

shdr.h, line 3845
class headless_context

An optional, headless EGL pbuffer context for a selected compute profile.
Define SHDR_ENABLE_EGL=1 before including shdr.h and link EGL to use this class.
It prefers a surfaceless display and otherwise uses EGL's default display.
Create, use and finally release the context on its creating thread. Displays
are shared among living shdr contexts. Let shdr manage their display lifetime.

shdr.h, line 4019
explicit headless_context(profile p = profile::es31) : context_(detail::make_egl_context(p))

Create a 1-by-1 pbuffer and make its context current.
Parameter p: Minimum GL or GLES version. defaults to OpenGL ES 3.1.
Throws: backend_unavailable If backend initialization fails.

shdr.h, line 4029
void make_current() const

Make this context current on its creating thread.

shdr.h, line 4035
static void* resolve(const char* name)

Resolve a GL entry point through EGL, for shdr::device or external GL calls.

shdr.h, line 4039
class headless_device : public device

A compute device that creates and retains its own headless EGL context.
Define SHDR_ENABLE_EGL=1 and link EGL. Construct this device on the thread that
performs its GPU operations. Its context remains alive while GPU resources,
programs and submissions retain the device state. release those objects on
that thread before shutdown. CPU execution uses host resources.

shdr.h, line 4052
explicit headless_device(profile p = profile::es31)
        : headless_device(detail::make_egl_context(p), p)

Create a headless context and initialize its compute device.
Parameter p: Minimum shader and context profile. defaults to OpenGL ES 3.1.
Throws: backend_unavailable If context creation or entry-point loading fails.

shdr.h, line 4073
void make_current() const

Make the owned context current for external GL interoperability.

shdr.h, line 4080

GLSL math

typedef std::uint32_t uint;

GLSL's portable 32-bit unsigned scalar spelling.

shdr.h, line 34
static constexpr std::size_t length()

Return the number of array elements.

shdr.h, line 210
array() : elements_()

Initialize every element to its zero/default value.

shdr.h, line 214
template <class... A>
    explicit array(const A&... values) : elements_

Construct from exactly N scalar or aggregate element values.

shdr.h, line 217
array(std::initializer_list<T> values) : elements_()

Initialize from a C++ brace list containing exactly N elements.
A length mismatch throws std::invalid_argument.

shdr.h, line 222
T& operator[](std::size_t i)

Read or modify element i. i must be less than length().

shdr.h, line 232
template <class T, std::size_t N> bool operator==(const array<T, N>& a, const array<T, N>& b)

Compare two arrays by comparing every element.

shdr.h, line 241
template <class T, std::size_t N> bool operator!=(const array<T, N>& a, const array<T, N>& b)

Return true when any pair of corresponding elements differs.

shdr.h, line 248
template <class T, std::size_t N> class vec : public detail::storage<T, N>

A vector with two, three or four components of one scalar type.
A scalar constructor fills every component. Component constructors consume
scalar, vector and matrix arguments from left to right. matrices contribute
columns in order. Excess components in the final argument are discarded.
Vector conversion takes the first N components of a source with at least N components.
Default construction initializes every component to zero. Indexing requires
an index less than length().

shdr.h, line 253
static constexpr std::size_t length()

Return the number of vector components.

shdr.h, line 268
template <class U, std::size_t C, std::size_t R> explicit vec(const mat<U, C, R>& value)

Read matrix columns consecutively to initialize the vector.

shdr.h, line 291
T& r()

Color aliases for x/y/z/w. b and a require three and four components.

shdr.h, line 316
template <std::size_t I> T& swizzle()

Select one component as a scalar reference.

shdr.h, line 374
template <std::size_t... I>
    typename std::enable_if<(sizeof...(I) >= 2), swizzle_ref<T, N, I...>>::type swizzle()

Select components in the requested order. writable destinations
must contain unique indices. Const vectors produce an independent value.

shdr.h, line 383
template <class T, std::size_t N, std::size_t... I> class swizzle_ref

A component selection referencing an existing vector.
Assignment evaluates all source components before writing any destination,
so exchanging components of the same vector is safe. Duplicate destination
indices are rejected at compile time. The vector must outlive the selection.
construct a vec value to keep an independent copy.

shdr.h, line 449
Vector component arithmetic
operator+, operator-, operator*, operator/, operator%, operator&, operator|, operator^, operator<<, operator>>

Vector/scalar and scalar/vector forms broadcast the scalar.
Integer operators require integer components, as in GLSL.

shdr.h, line 509
template <class T, std::size_t C, std::size_t R> class mat

A floating-point matrix with C columns and R rows.
A scalar constructor initializes the diagonal and sets other entries to
zero. Component constructors consume scalars and vectors in column order,
discarding excess components in the final argument. Matrix conversion copies
the common region and fills the remaining entries with the identity matrix.
Default construction initializes every component to zero.

shdr.h, line 602
static constexpr std::size_t length()

Return the number of matrix columns.

shdr.h, line 620
template <class A, typename std::enable_if<detail::traits<A>::vector, int>::type = 0>
    explicit mat(const A& value)

Construct a matrix from the components of one vector or swizzle.

shdr.h, line 638
column_type& operator[](std::size_t c)

Read or modify column c. m[c][r] selects row r within that column.

shdr.h, line 662
template <class T, class A>
typename std::enable_if<std::is_arithmetic<T>::value && detail::traits<A>::valid, T>::type
scalar_cast(const A& value)

Convert a scalar, or the first component of a vector, to T.
This implements GLSL scalar constructors such as float(vec3) for generated
C++ kernels. Ordinary C++ callers may use scalar_cast<float>(value) directly.

shdr.h, line 712
template <class T, class U, std::size_t C, std::size_t R>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
scalar_cast(const mat<U, C, R>& value)

Convert the first column's first matrix component to scalar type T.

shdr.h, line 721
template <class T, std::size_t C, std::size_t R, class A>
typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == C, vec<T, R>>::type
operator*(const mat<T, C, R>& a, const A& b)

Algebraic matrix-vector multiplication.

shdr.h, line 825
template <class T, std::size_t C, std::size_t R, std::size_t K>
mat<T, K, R> operator*(const mat<T, C, R>& a, const mat<T, K, C>& b)

Algebraic multiplication, including nonsquare matrices.

shdr.h, line 844
template <class T, std::size_t C, std::size_t R> mat<T, R, C> transpose(const mat<T, C, R>& a)

Exchange rows and columns, including rectangular matrices.

shdr.h, line 852
template <class T, std::size_t C, std::size_t R>
mat<T, C, R> matrixCompMult(const mat<T, C, R>& a, const mat<T, C, R>& b)

Multiply corresponding matrix components element by element.

shdr.h, line 860
template <class T, std::size_t R, std::size_t C>
mat<T, C, R> outerProduct(const vec<T, R>& column, const vec<T, C>& row)

Form a column-by-row outer product. output column j is column*row[j].

shdr.h, line 868
template <class T, std::size_t N> T determinant(mat<T, N, N> a)

Determinant using partial-pivot elimination.

shdr.h, line 876
template <class T, std::size_t N> mat<T, N, N> inverse(mat<T, N, N> a)

Inverse using partial-pivot Gauss-Jordan elimination.
Singular input has undefined GLSL semantics. the host returns quiet NaNs.

shdr.h, line 904
Angle, exponential and common scalar/vector math
radians, degrees, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, exp, log, exp2, log2, sqrt, inversesqrt, floor, trunc, round, ceil, fract, abs, sign, roundEven, pow, mod, min, max, step, fma, clamp, mix, smoothstep, isnan, isinf, modf, frexp, ldexp

Floating-point overloads preserve their component type. Vector overloads
apply each scalar operation independently, including swizzle expressions.

shdr.h, line 954
template <class T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type roundEven(T x)

Round halfway cases to the nearest even integer, independent of the
host's floating-point rounding mode. Nonfinite inputs are preserved.

shdr.h, line 1021
template <class T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type fma(T a, T b, T c)

Fused multiply-add. final rounding may differ across CPU/GPU.

shdr.h, line 1066
template <class A, class B>
typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector,
                        typename detail::result<A>::type>::type
modf(const A& x, B&& integer)

Split a vector into signed fractional and integer parts.
The return value contains fractional components. integer receives the
integral components. Both arguments may be swizzles, including selections
of the same vector, because the input is copied before output assignment.

shdr.h, line 1168
template <class A, class B>
typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector,
                        typename detail::result<A>::type>::type
frexp(const A& x, B&& exponent)

Return binary significands and write matching signed exponents.
Each nonzero component satisfies x = significand * 2^exponent. Output may be
an integer vector or a writable swizzle with matching component count.

shdr.h, line 1192
template <class A, class B>
typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector,
                        typename detail::result<A>::type>::type
ldexp(const A& x, const B& exponent)

Multiply each component by two raised to its signed integer exponent.

shdr.h, line 1218
Geometry
dot, length, distance, cross, normalize, faceforward, reflect, refract

Geometry uses scalar dot products and GLSL's usual component formulas.
normalize requires nonzero length. Inputs to reflect, refract and faceforward
should obey GLSL's normalized-normal requirements.

shdr.h, line 1233
Vector relational functions
lessThan, lessThanEqual, greaterThan, greaterThanEqual, equal, notEqual, any, all, logicalNot, _not

operator== compares the whole vector and returns bool. These builtins return
component masks. logicalNot is the C++ spelling of GLSL's reserved not.

shdr.h, line 1301
32-bit bit operations
floatBitsToUint, floatBitsToInt, uintBitsToFloat, intBitsToFloat, bitCount, findLSB, findMSB, bitfieldReverse, bitfieldExtract, bitfieldInsert, uaddCarry, usubBorrow, umulExtended, imulExtended

Reinterpretation uses memcpy and requires IEEE binary32 floats and 32-bit
integers. Bitfield ranges must satisfy 0 <= offset,bits and offset+bits<=32.
The 64-bit host intermediates in extended multiplication are never exposed
to shared shaders. Bit searches and counts return signed integer results.

shdr.h, line 1350
template <class A, class B, class C>
typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector &&
                            detail::traits<C>::vector,
                        vec<std::uint32_t, detail::traits<A>::size>>::type
uaddCarry(const A& x, const B& y, C&& carry)

Add unsigned vectors modulo 2^32 and write their carry flags.

shdr.h, line 1513
template <class A, class B, class C>
typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector &&
                            detail::traits<C>::vector,
                        vec<std::uint32_t, detail::traits<A>::size>>::type
usubBorrow(const A& x, const B& y, C&& borrow)

Subtract unsigned vectors modulo 2^32 and write their borrow flags.

shdr.h, line 1534
Packing
packUnorm2x16, unpackUnorm2x16, packSnorm2x16, unpackSnorm2x16, packUnorm4x8, unpackUnorm4x8, packSnorm4x8, unpackSnorm4x8, packHalf2x16, unpackHalf2x16

Normalized packing follows the GLSL clamp-and-round formulas. unpacking
places the least significant byte/halfword in x. Half-float encoding rounds
to nearest even and preserves infinities and a quiet-NaN representation.

shdr.h, line 1583

C++ adapter declaration macros

#define SHDR_DETAIL_MATRIX_ALIASES(T, PREFIX)

GLSL square and rectangular matrix aliases. dimensions are columns
followed by rows. Float aliases are mat2..4 and mat2x2..mat4x4. double aliases
use dmat. Double arithmetic is a host extension and requires a supporting
desktop GLSL profile when used by shared shaders.

shdr.h, line 727
#define SHDR_BEGIN(name, x, y, z)

Begin one shared shader declaration with a fixed local work group size.

shdr.h, line 4096
#define SHDR_MAIN()

Declare the shared entry point, executed once per invocation on CPU or GPU.

shdr.h, line 4111
#define SHDR_BUFFER(binding, type, name, mode)

Declare a typed std430 SSBO with readonly/writeonly/readwrite access.

shdr.h, line 4113
#define SHDR_UNIFORM(type, name)

Declare a typed scalar, vector or float matrix uniform.

shdr.h, line 4116
#define SHDR_IMAGE2D(binding, format, type, name, mode)

Declare a 2D storage image. Supported formats are r32f/i/ui and rgba32f/i/ui.

shdr.h, line 4120
#define SHDR_SWIZZLE(value, pattern)

GLSL-style component selection, with safe simultaneous CPU swizzle assignment.
Use xyzw, rgba or stpq consistently. Duplicate components are read-only.

shdr.h, line 4135
#define SHDR_NOT(value)

Portable spelling of GLSL's boolean vector not builtin.

shdr.h, line 4139
#define SHDR_IN(type, name)

Declare a shared helper function input parameter.

shdr.h, line 4141
#define SHDR_OUT(type, name)

Declare a shared helper function output parameter.

shdr.h, line 4143
#define SHDR_INOUT(type, name)

Declare a shared helper function input/output parameter.

shdr.h, line 4145

Other documented declarations

void synchronize()

Wait for submitted GPU work to complete, including for accurate wall-clock benchmarks.

shdr.h, line 2567
void collect_garbage()

Delete GL objects retired by CPU workers and poll pending completions.

shdr.h, line 2573
std::string renderer() const

Current GL renderer name, for diagnostics and reproducible benchmark reports.

shdr.h, line 2577
T* data()

Synchronize newer GPU contents and return mutable host elements.
Marks host data modified. Reacquire this pointer after GPU work before using it.

shdr.h, line 2630
const T* data() const

Synchronize newer GPU contents and return readonly host elements.

shdr.h, line 2638
T& operator[](std::size_t i)

Access one host element after synchronization. reject an out-of-range index.

shdr.h, line 2643
const T& operator[](std::size_t i) const

Read one host element after synchronization. reject an out-of-range index.

shdr.h, line 2649
void mark_host_modified()

Notify shdr after changing previously obtained or borrowed host memory.
Call data() before editing if GPU data must first be preserved.

shdr.h, line 2676
unsigned width() const

Return the stored number of pixels in each row.

shdr.h, line 2713
T* data()

Synchronize newer GPU contents and return mutable interleaved host pixels.
Index component c at (x,y) as data()[(y*width()+x)*C+c]. Marks host data
modified. reacquire the pointer after GPU work before using it.

shdr.h, line 2721
const T* data() const

Synchronize newer GPU contents and return readonly interleaved host pixels.

shdr.h, line 2730
void mark_host_modified()

Notify shdr after changing a retained host pixel pointer.

shdr.h, line 2756
const std::string& name() const

Return the kernel's diagnostic name.

shdr.h, line 2864
template <class T> class uniform_port : public detail::port_base

A zero-initialized typed shader uniform, assigned with ordinary C++ syntax.

shdr.h, line 3024
uniform_port& operator=(const T& value)

Set the uniform value uploaded at the next dispatch.

shdr.h, line 3040
operator T() const

Read the uniform as its declared shader type during CPU execution.

shdr.h, line 3045
void require_host_ready() const

Validate CPU execution support and current host data for a deferred job.

shdr.h, line 3386
Browse the complete documented header source
1// shdr 1.0.0
2// C++11 CPU and OpenGL compute pipelines.
3#ifndef SHDR_SINGLE_HEADER_INCLUDED
4#define SHDR_SINGLE_HEADER_INCLUDED
5
6// ---- math.hpp ----
7/** @file math.hpp
8 * @brief GLSL-compatible scalar, vector and matrix operations for C++11.
9 *
10 * Vectors provide x/y/z/w component fields, indexed access, and writable
11 * swizzles. Color and texture-coordinate aliases are accessor functions in
12 * ordinary C++ code. Matrices use GLSL column-major order. The same types and
13 * functions are available to generated CPU kernels and application code.
14 *
15 * Floating-point precision and exceptional values depend on the implementation.
16 * Normalize nonzero vectors, invert nonsingular matrices and use valid shift
17 * counts. Keep signed arithmetic within its representable range and use
18 * nonnegative signed operands for left shifts to follow portable C++ rules.
19 * Resource element layout is defined by the buffer and image APIs separately.
20 */
21#ifndef SHDR_DETAIL_MATH_HPP // Include this math layer only once.
22#define SHDR_DETAIL_MATH_HPP // Remember that the math layer is available.
23#include <cmath> // Use the standard scalar math functions.
24#include <cstddef> // Use portable size types.
25#include <cstdint> // Use exact-width GLSL integer types.
26#include <cstring> // Copy bit patterns through byte storage.
27#include <initializer_list> // Accept ordinary C++ brace lists.
28#include <limits> // Query numeric limits and quiet NaNs.
29#include <ostream> // Support readable vector and matrix output.
30#include <stdexcept> // Report invalid array initializers.
31#include <type_traits> // Choose only compatible template overloads.
32namespace shdr { // Keep these names inside the shdr namespace.
33namespace glsl { // Keep these names inside the glsl namespace.
34/** @brief GLSL's portable 32-bit unsigned scalar spelling. */
35typedef std::uint32_t uint; // Use a portable 32-bit unsigned scalar.
36template <class T, std::size_t N> class vec; // Store a fixed-size vector with named component fields.
37template <class T, std::size_t N> class array; // Store a fixed number of values of one element type.
38template <class T, std::size_t N, std::size_t... I> class swizzle_ref; // Describe a component selection that refers to a vector.
39template <class T, std::size_t C, std::size_t R> class mat; // Describe a matrix by its scalar type and dimensions.
40namespace detail { // Keep these names inside the detail namespace.
41template <class T, std::size_t N> struct storage; // Choose named storage for the vector dimension.
42template <class T> struct storage<T, 2> { // Choose named storage for the vector dimension.
43    T x, y; // Store the named vector components in order.
44    T& at(std::size_t i) { // Select the named component matching this index.
45        return i == 0 ? x : y; // Select the named field for this valid component index.
46    } // Finish the at operation.
47    const T& at(std::size_t i) const { // Select the named component matching this index.
48        return i == 0 ? x : y; // Select the named field for this valid component index.
49    } // Finish the at operation.
50}; // Finish the storage type description.
51template <class T> struct storage<T, 3> { // Choose named storage for the vector dimension.
52    T x, y, z; // Store the named vector components in order.
53    T& at(std::size_t i) { // Select the named component matching this index.
54        return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
55    } // Finish the at operation.
56    const T& at(std::size_t i) const { // Select the named component matching this index.
57        return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
58    } // Finish the at operation.
59}; // Finish the storage type description.
60template <class T> struct storage<T, 4> { // Choose named storage for the vector dimension.
61    T x, y, z, w; // Store the named vector components in order.
62    T& at(std::size_t i) { // Select the named component matching this index.
63        return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
64    } // Finish the at operation.
65    const T& at(std::size_t i) const { // Select the named component matching this index.
66        return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
67    } // Finish the at operation.
68}; // Finish the storage type description.
69template <class A> struct shape { // Describe an ordinary scalar input.
70    typedef A scalar; // Keep the chosen component type for the calculation.
71    static const std::size_t size = 1; // Treat a scalar as one component.
72    static const bool vector = false; // Keep this input out of vector-only overloads.
73    static const bool valid = std::is_arithmetic<A>::value; // Record whether componentwise arithmetic accepts this shape.
74}; // Finish the shape type description.
75template <class T, std::size_t N> struct shape<vec<T, N>> { // Describe the scalar type and size of a vector.
76    typedef T scalar; // Keep the chosen component type for the calculation.
77    static const std::size_t size = N; // Keep the fixed component count available at compile time.
78    static const bool vector = true; // Mark this input as a vector-shaped value.
79    static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
80}; // Finish the shape type description.
81template <class T, std::size_t N, std::size_t... I> struct shape<swizzle_ref<T, N, I...>> { // Describe the scalar type and size of a component selection.
82    typedef T scalar; // Keep the chosen component type for the calculation.
83    static const std::size_t size = sizeof...(I); // Count the selected vector components.
84    static const bool vector = true; // Mark this input as a vector-shaped value.
85    static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
86}; // Finish the shape type description.
87template <class A> struct traits : shape<typename std::decay<A>::type> {}; // Ignore references and const when inspecting an input type.
88template <class... A> struct count; // Count components supplied by constructor arguments.
89template <> struct count<> { // Count components supplied by constructor arguments.
90    static const std::size_t value = 0; // Start the component count at zero.
91}; // Finish the count type description.
92template <class A, class... B> struct count<A, B...> { // Count components supplied by constructor arguments.
93    static const std::size_t value = traits<A>::size + count<B...>::value; // Add this argument count to the remaining components.
94}; // Finish the count type description.
95template <class... A> struct prefix_count; // Count constructor components before the final argument.
96template <class Last> struct prefix_count<Last> { // Count constructor components before the final argument.
97    static const std::size_t value = 0; // Start the component count at zero.
98}; // Finish the prefix_count type description.
99template <class A, class B, class... Rest> struct prefix_count<A, B, Rest...> { // Count constructor components before the final argument.
100    static const std::size_t value = traits<A>::size + prefix_count<B, Rest...>::value; // Add this argument count to the remaining components.
101}; // Finish the prefix_count type description.
102template <class A> struct is_matrix : std::false_type {}; // Identify matrix types at compile time.
103template <class T, std::size_t C, std::size_t R> struct is_matrix<mat<T, C, R>> : std::true_type {}; // Identify matrix types at compile time.
104template <class T, std::size_t C, std::size_t R> struct shape<mat<T, C, R>> { // Describe a matrix separately from vector arithmetic.
105    typedef T scalar; // Keep the chosen component type for the calculation.
106    static const std::size_t size = C * R; // Count scalar entries across every matrix column.
107    static const bool vector = false; // Keep this input out of vector-only overloads.
108    static const bool valid = false; // Record whether componentwise arithmetic accepts this shape.
109}; // Finish the shape type description.
110template <class... A> struct any_matrix; // Check whether a constructor argument is a matrix.
111template <> struct any_matrix<> : std::false_type {}; // Check whether a constructor argument is a matrix.
112template <class A, class... B> // Accept the matching input types and dimensions.
113struct any_matrix<A, B...> // Describe this input or selection at compile time.
114    : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
115                             is_matrix<typename std::decay<A>::type>::value || // Complete the type and dimension rule for this overload.
116                                 any_matrix<B...>::value> {}; // Complete the type and dimension rule for this overload.
117template <std::size_t Needle, std::size_t... I> struct contains; // Check whether the remaining index list contains an index.
118template <std::size_t Needle> struct contains<Needle> : std::false_type {}; // Check whether the remaining index list contains an index.
119template <std::size_t Needle, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
120struct contains<Needle, A, I...> // Describe this input or selection at compile time.
121    : std::integral_constant<bool, Needle == A || contains<Needle, I...>::value> {}; // Turn the component rule into a compile-time boolean.
122template <std::size_t... I> struct unique; // Check that selected component indices are distinct.
123template <> struct unique<> : std::true_type {}; // Check that selected component indices are distinct.
124template <std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
125struct unique<A, I...> // Describe this input or selection at compile time.
126    : std::integral_constant<bool, !contains<A, I...>::value && unique<I...>::value> {}; // Turn the component rule into a compile-time boolean.
127template <class A> struct writable_shape : std::false_type {}; // Identify vector selections that can receive values.
128template <class T, std::size_t N> struct writable_shape<vec<T, N>> : std::true_type {}; // Describe the scalar type and size of a vector.
129template <class T, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
130struct writable_shape<swizzle_ref<T, N, I...>> : unique<I...> {}; // Describe this input or selection at compile time.
131template <class A> // Accept the matching input types and dimensions.
132struct writable // Describe this input or selection at compile time.
133    : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
134                             writable_shape<typename std::decay<A>::type>::value && // Complete the type and dimension rule for this overload.
135                                 !std::is_const<typename std::remove_reference<A>::type>::value> {}; // Complete the type and dimension rule for this overload.
136template <std::size_t N, std::size_t... I> struct in_range; // Check that every selected index fits the vector.
137template <std::size_t N> struct in_range<N> : std::true_type {}; // Check that every selected index fits the vector.
138template <std::size_t N, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
139struct in_range<N, A, I...> : std::integral_constant<bool, // Check this index and the remaining selected indices.
140    A < N && in_range<N, I...>::value> {}; // Require every selected component index to fit the vector.
141template <class A> // Accept the matching input types and dimensions.
142typename std::enable_if<!traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
143component(const A& a, std::size_t) { // Read the requested scalar or vector component.
144    return a; // Return the scalar unchanged.
145} // Finish the component operation.
146template <class A> // Accept the matching input types and dimensions.
147typename std::enable_if<traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
148component(const A& a, std::size_t i) { // Read the requested scalar or vector component.
149    return a[i]; // Read the requested scalar or vector component.
150} // Finish the component operation.
151template <class A, class B> struct binary { // Choose compatible componentwise operand shapes.
152    static const bool valid = // Record whether componentwise arithmetic accepts this shape.
153        traits<A>::valid && traits<B>::valid && (traits<A>::vector || traits<B>::vector) && // Complete the type and dimension rule for this overload.
154        (!traits<A>::vector || !traits<B>::vector || traits<A>::size == traits<B>::size); // Require equal lengths when both operands are vectors.
155    typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
156                                      typename traits<A>::scalar, // Preserve the selected component type and result shape.
157                                      typename traits<B>::scalar>::type scalar; // Preserve the selected component type and result shape.
158    static const std::size_t size = traits<A>::vector ? traits<A>::size : traits<B>::size; // Record the compile-time component rule.
159    typedef vec<scalar, size> result; // Name the vector type produced by this operation.
160}; // Finish the binary type description.
161template <class A> struct result { // Choose the value type for this expression result.
162    typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
163                                      vec<typename traits<A>::scalar, traits<A>::size>, // Preserve the selected component type and result shape.
164                                      typename traits<A>::scalar>::type type; // Preserve the selected component type and result shape.
165}; // Finish the result type description.
166template <class T, class U> // Accept the matching input types and dimensions.
167typename std::enable_if<std::is_arithmetic<U>::value>::type // Enable this overload only for compatible input types.
168append(T* target, std::size_t& n, const U& a) { // Append the next argument to the flat component list.
169    target[n++] = static_cast<T>(a); // Append this component and advance the destination position.
170} // Finish the append operation.
171template <class T, class U, std::size_t N> // Accept the matching input types and dimensions.
172void append(T* target, std::size_t& n, const vec<U, N>& a) { // Append constructor components in their original order.
173    for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
174        target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
175} // Finish the append operation.
176template <class T, class U, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
177void append(T* target, std::size_t& n, const swizzle_ref<U, N, I...>& a) { // Append constructor components in their original order.
178    for (std::size_t i = 0; i < sizeof...(I); ++i) // Visit each component needed by this calculation.
179        target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
180} // Finish the append operation.
181template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
182void append(T* target, std::size_t& n, const mat<U, C, R>& a) { // Append constructor components in their original order.
183    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
184        for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
185            target[n++] = static_cast<T>(a[c][r]); // Append this component and advance the destination position.
186} // Finish the append operation.
187template <class T> void flatten(T*, std::size_t&) { // Accept the matching input types and dimensions.
188} // Finish the flatten operation.
189template <class T, class A, class... B> // Accept the matching input types and dimensions.
190void flatten(T* target, std::size_t& n, const A& a, const B&... b) { // Collect components from the remaining constructor arguments.
191    append(target, n, a); // Append the next argument to the flat component list.
192    flatten(target, n, b...); // Append the remaining arguments in order.
193} // Finish the flatten operation.
194} // namespace detail
195
196/** @brief A fixed-size array for GLSL local variables and function arguments.
197 * The size must be positive. Default construction initializes every element to
198 * its zero/default value.  component construction requires exactly N elements.
199 * Copy construction and assignment copy all elements. Use length() to query
200 * the element count and operator[] to select an element with a valid index.
201 * Resource ports define buffer and uniform memory layouts separately.
202 */
203template <class T, std::size_t N> class array { // Store a fixed number of values of one element type.
204    static_assert(N > 0, "GLSL fixed arrays require a positive size"); // Require at least one fixed-array element.
205    T elements_[N]; // Keep exactly N fixed-array elements.
206
207  public: // Expose the public math operations.
208    typedef T value_type; // Expose the element type to host code and templates.
209    static const std::size_t size_value = N; // Keep the fixed component count available at compile time.
210    /** @brief Return the number of array elements. */
211    static constexpr std::size_t length() { // Record the compile-time component rule.
212        return N; // Return the fixed number of available components.
213    } // Finish the length operation.
214    /** @brief Initialize every element to its zero/default value. */
215    array() : elements_() { // Initialize fixed-array storage from the supplied values.
216    } // Finish initializing the fixed array.
217    /** @brief Construct from exactly N scalar or aggregate element values. */
218    template <class... A> // Accept the matching input types and dimensions.
219    explicit array(const A&... values) : elements_{static_cast<T>(values)...} { // Initialize fixed-array storage from the supplied values.
220        static_assert(sizeof...(A) == N, "array constructor element count mismatch"); // Require exactly one argument for each array element.
221    } // Finish initializing the fixed array.
222    /** @brief Initialize from a C++ brace list containing exactly N elements.
223     * A length mismatch throws std::invalid_argument.
224     */
225    array(std::initializer_list<T> values) : elements_() { // Initialize fixed-array storage from the supplied values.
226        if (values.size() != N) // Reject a brace list with the wrong element count.
227            throw std::invalid_argument("array initializer element count mismatch"); // Report an initializer length mismatch.
228        std::size_t i = 0; // Begin filling the first array element.
229        for (const T& value : values) // Read initializer values in their original order.
230            elements_[i++] = value; // Store the next brace-list element.
231    } // Finish initializing the fixed array.
232    /** @brief Read or modify element i.  i must be less than length(). */
233    T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
234        return elements_[i]; // Return the selected component with its original reference type.
235    } // Finish this operator overload.
236    const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
237        return elements_[i]; // Return the selected component with its original reference type.
238    } // Finish this operator overload.
239}; // Finish the array type description.
240template <class T, std::size_t N> const std::size_t array<T, N>::size_value; // Accept the matching input types and dimensions.
241/** @brief Compare two arrays by comparing every element. */
242template <class T, std::size_t N> bool operator==(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
243    for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
244        if (!(a[i] == b[i])) // Stop when corresponding components differ.
245            return false; // Report that at least one component differs.
246    return true; // Report that every required component matched.
247} // Finish this operator overload.
248/** @brief Return true when any pair of corresponding elements differs. */
249template <class T, std::size_t N> bool operator!=(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
250    return !(a == b); // Return the component count or geometric length.
251} // Finish this operator overload.
252
253/** @brief A vector with two, three or four components of one scalar type.
254 * A scalar constructor fills every component. Component constructors consume
255 * scalar, vector and matrix arguments from left to right.  matrices contribute
256 * columns in order. Excess components in the final argument are discarded.
257 * Vector conversion takes the first N components of a source with at least N components.
258 * Default construction initializes every component to zero. Indexing requires
259 * an index less than length().
260 */
261template <class T, std::size_t N> class vec : public detail::storage<T, N> { // Store a fixed-size vector with named component fields.
262    static_assert(N >= 2 && N <= 4, "GLSL vectors require 2 to 4 components"); // Require two, three or four vector components.
263
264  public: // Expose the public math operations.
265    typedef T value_type; // Expose the element type to host code and templates.
266    typedef T component_type; // Expose the element type to host code and templates.
267    static const std::size_t length_value = N; // Keep the fixed component count available at compile time.
268    /** @brief Return the number of vector components. */
269    static constexpr std::size_t length() { // Record the compile-time component rule.
270        return N; // Return the fixed number of available components.
271    } // Finish the length operation.
272    vec() { // Initialize vector components from the supplied values.
273        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
274            (*this)[i] = T(); // Update the selected destination component.
275    } // Finish initializing the vector.
276    template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
277    explicit vec(U value) { // Initialize vector components from the supplied values.
278        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
279            (*this)[i] = static_cast<T>(value); // Update the selected destination component.
280    } // Finish initializing the vector.
281    template <class U, std::size_t M> explicit vec(const vec<U, M>& value) { // Accept the matching input types and dimensions.
282        static_assert(M >= N, "vector conversion cannot invent components"); // Check this type or dimension requirement at compile time.
283        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
284            (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
285    } // Finish initializing the vector.
286    template <class U, std::size_t M, std::size_t... I> vec(const swizzle_ref<U, M, I...>& value) { // Accept the matching input types and dimensions.
287        static_assert(sizeof...(I) >= N, "swizzle conversion cannot invent components"); // Check this type or dimension requirement at compile time.
288        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
289            (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
290    } // Finish initializing the vector.
291    /** @brief Read matrix columns consecutively to initialize the vector. */
292    template <class U, std::size_t C, std::size_t R> explicit vec(const mat<U, C, R>& value) { // Accept the matching input types and dimensions.
293        static_assert(C * R >= N, "matrix does not provide enough vector components"); // Check this type or dimension requirement at compile time.
294        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
295            (*this)[i] = static_cast<T>(value[i / R][i % R]); // Update the selected destination component.
296    } // Finish initializing the vector.
297    template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
298    explicit vec(const A& a, const B& b, const Rest&... rest) { // Initialize vector components from the supplied values.
299        static_assert(detail::count<A, B, Rest...>::value >= N, // Require enough components to fill the destination.
300                      "vector constructor has too few components"); // Explain the rejected input: vector constructor has too few components.
301        static_assert(detail::prefix_count<A, B, Rest...>::value < N, // Reject constructor arguments that would go unused.
302                      "vector constructor has unused arguments"); // Explain the rejected input: vector constructor has unused arguments.
303        T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
304        std::size_t n = 0; // Begin appending at the first temporary component.
305        detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
306        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
307            (*this)[i] = values[i]; // Update the selected destination component.
308    } // Finish initializing the vector.
309    /** @brief Read or modify component i. */
310    T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
311        return this->at(i); // Return the selected component with its original reference type.
312    } // Finish this operator overload.
313    const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
314        return this->at(i); // Return the selected component with its original reference type.
315    } // Finish this operator overload.
316    /** @brief Color aliases for x/y/z/w.  b and a require three and four components. */
317    T& r() { // Expose the first component through its color name.
318        return (*this)[0]; // Return the selected component with its original reference type.
319    } // Finish the r operation.
320    const T& r() const { // Expose the first component through its color name.
321        return (*this)[0]; // Return the selected component with its original reference type.
322    } // Finish the r operation.
323    T& g() { // Expose the second component through its color name.
324        return (*this)[1]; // Return the selected component with its original reference type.
325    } // Finish the g operation.
326    const T& g() const { // Expose the second component through its color name.
327        return (*this)[1]; // Return the selected component with its original reference type.
328    } // Finish the g operation.
329    T& b() { // Expose the third component through its color name.
330        static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
331        return (*this)[2]; // Return the selected component with its original reference type.
332    } // Finish the b operation.
333    const T& b() const { // Expose the third component through its color name.
334        static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
335        return (*this)[2]; // Return the selected component with its original reference type.
336    } // Finish the b operation.
337    T& a() { // Expose the fourth component through its color name.
338        static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
339        return (*this)[3]; // Return the selected component with its original reference type.
340    } // Finish the a operation.
341    const T& a() const { // Expose the fourth component through its color name.
342        static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
343        return (*this)[3]; // Return the selected component with its original reference type.
344    } // Finish the a operation.
345    /** @brief Texture-coordinate aliases for x/y/z/w. */
346    T& s() { // Expose the first texture coordinate.
347        return (*this)[0]; // Return the selected component with its original reference type.
348    } // Finish the s operation.
349    const T& s() const { // Expose the first texture coordinate.
350        return (*this)[0]; // Return the selected component with its original reference type.
351    } // Finish the s operation.
352    T& t() { // Expose the second texture coordinate.
353        return (*this)[1]; // Return the selected component with its original reference type.
354    } // Finish the t operation.
355    const T& t() const { // Expose the second texture coordinate.
356        return (*this)[1]; // Return the selected component with its original reference type.
357    } // Finish the t operation.
358    T& p() { // Expose the third texture coordinate.
359        static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
360        return (*this)[2]; // Return the selected component with its original reference type.
361    } // Finish the p operation.
362    const T& p() const { // Expose the third texture coordinate.
363        static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
364        return (*this)[2]; // Return the selected component with its original reference type.
365    } // Finish the p operation.
366    T& q() { // Expose the fourth texture coordinate.
367        static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
368        return (*this)[3]; // Return the selected component with its original reference type.
369    } // Finish the q operation.
370    const T& q() const { // Expose the fourth texture coordinate.
371        static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
372        return (*this)[3]; // Return the selected component with its original reference type.
373    } // Finish the q operation.
374    /** @brief Select one component as a scalar reference. */
375    template <std::size_t I> T& swizzle() { // Accept the matching input types and dimensions.
376        static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
377        return (*this)[I]; // Return the selected component with its original reference type.
378    } // Finish the swizzle operation.
379    template <std::size_t I> const T& swizzle() const { // Accept the matching input types and dimensions.
380        static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
381        return (*this)[I]; // Return the selected component with its original reference type.
382    } // Finish the swizzle operation.
383    /** @brief Select components in the requested order.  writable destinations
384     * must contain unique indices. Const vectors produce an independent value.
385     */
386    template <std::size_t... I> // Accept the matching input types and dimensions.
387    typename std::enable_if<(sizeof...(I) >= 2), swizzle_ref<T, N, I...>>::type swizzle() { // Enable this overload only for compatible input types.
388        static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
389        static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
390        return swizzle_ref<T, N, I...>(*this); // Select components in the requested order.
391    } // Finish the swizzle operation.
392    template <std::size_t... I> // Accept the matching input types and dimensions.
393    typename std::enable_if<(sizeof...(I) >= 2), vec<T, sizeof...(I)>>::type swizzle() const { // Enable this overload only for compatible input types.
394        static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
395        static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
396        const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
397        vec<T, sizeof...(I)> out; // Keep an independent value for the result or aliased inputs.
398        for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
399            out[j] = (*this)[indices[j]]; // Store the computed component in the independent result.
400        return out; // Return the completed result.
401    } // Finish the swizzle operation.
402#define SHDR_DETAIL_VEC_ASSIGN(OP) /* Generate the matching scalar and vector overloads. */ \
403    template <class A> vec& operator OP(const A & a) { /* Accept the matching input types and dimensions. */ \
404        static_assert(!detail::traits<A>::vector || detail::traits<A>::size == N, /* Require matching component counts. */ \
405                      "vector dimension mismatch"); /* Explain the rejected input: vector dimension mismatch. */ \
406        T values[N]; /* Allocate space for the supplied constructor components. */ \
407        for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
408            values[i] = static_cast<T>(detail::component(a, i)); /* Copy source components before any destination is changed. */ \
409        } /* Finish this component or matrix pass. */ \
410        for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
411            (*this)[i] OP values[i]; /* Update the selected destination component. */ \
412        } /* Finish this component or matrix pass. */ \
413        return *this; /* Allow this update to be used in a chained expression. */ \
414    } /* Finish this operator overload. */
415    SHDR_DETAIL_VEC_ASSIGN(+=) // Provide componentwise addition.
416    SHDR_DETAIL_VEC_ASSIGN(-=) // Provide componentwise subtraction.
417    SHDR_DETAIL_VEC_ASSIGN(*=) // Provide componentwise multiplication.
418    SHDR_DETAIL_VEC_ASSIGN(/=) // Provide componentwise division.
419    SHDR_DETAIL_VEC_ASSIGN(%=) // Provide componentwise integer remainder.
420    SHDR_DETAIL_VEC_ASSIGN(&=) // Provide componentwise bitwise AND.
421    SHDR_DETAIL_VEC_ASSIGN(|=) // Provide componentwise bitwise OR.
422    SHDR_DETAIL_VEC_ASSIGN(^=) // Provide componentwise bitwise XOR.
423    SHDR_DETAIL_VEC_ASSIGN(<<=) // Provide componentwise left shifting.
424    SHDR_DETAIL_VEC_ASSIGN(>>=) // Provide componentwise right shifting.
425#undef SHDR_DETAIL_VEC_ASSIGN // Remove this local code generator macro.
426    vec& operator++() { // Provide this arithmetic or component access overload.
427        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
428            ++(*this)[i]; // Increment this vector component.
429        return *this; // Allow this update to be used in a chained expression.
430    } // Finish this operator overload.
431    vec operator++(int) { // Provide this arithmetic or component access overload.
432        vec old(*this); // Save the vector value before incrementing or decrementing it.
433        ++*this; // Increment every vector component.
434        return old; // Return the value from before the update.
435    } // Finish this operator overload.
436    vec& operator--() { // Provide this arithmetic or component access overload.
437        for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
438            --(*this)[i]; // Decrement this vector component.
439        return *this; // Allow this update to be used in a chained expression.
440    } // Finish this operator overload.
441    vec operator--(int) { // Provide this arithmetic or component access overload.
442        vec old(*this); // Save the vector value before incrementing or decrementing it.
443        --*this; // Decrement every vector component.
444        return old; // Return the value from before the update.
445    } // Finish this operator overload.
446}; // Finish the vec type description.
447template <class T, std::size_t N> const std::size_t vec<T, N>::length_value; // Accept the matching input types and dimensions.
448
449/** @brief A component selection referencing an existing vector.
450 * Assignment evaluates all source components before writing any destination,
451 * so exchanging components of the same vector is safe. Duplicate destination
452 * indices are rejected at compile time. The vector must outlive the selection.
453 * construct a vec value to keep an independent copy.
454 */
455template <class T, std::size_t N, std::size_t... I> class swizzle_ref { // Describe a component selection that refers to a vector.
456    vec<T, N>* source_; // Refer to the vector that owns the selected components.
457
458  public: // Expose the public math operations.
459    static constexpr std::size_t length() { // Record the compile-time component rule.
460        return sizeof...(I); // Return the fixed number of available components.
461    } // Finish the length operation.
462    explicit swizzle_ref(vec<T, N>& source) : source_(&source) { // Keep a reference to the source vector.
463    } // Finish keeping the source vector reference.
464    swizzle_ref(const swizzle_ref&) = default; // Copy the reference to the same source vector.
465    T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
466        const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
467        return (*source_)[indices[i]]; // Return the selected component with its original reference type.
468    } // Finish this operator overload.
469    const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
470        const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
471        return (*source_)[indices[i]]; // Return the selected component with its original reference type.
472    } // Finish this operator overload.
473    operator vec<T, sizeof...(I)>() const { // Provide this arithmetic or component access overload.
474        return vec<T, sizeof...(I)>(*this); // Return the component count or geometric length.
475    } // Finish this operator overload.
476    swizzle_ref& operator=(const swizzle_ref& rhs) { // Provide this arithmetic or component access overload.
477        return assign(rhs); // Write through a temporary so overlapping selections remain safe.
478    } // Finish this operator overload.
479    template <class A> swizzle_ref& operator=(const A& rhs) { // Accept the matching input types and dimensions.
480        return assign(rhs); // Write through a temporary so overlapping selections remain safe.
481    } // Finish this operator overload.
482    template <class A> swizzle_ref& assign(const A& rhs) { // Accept the matching input types and dimensions.
483        static_assert(detail::unique<I...>::value, "a writable swizzle cannot repeat components"); // Prevent repeated destination components.
484        static_assert(!detail::traits<A>::vector || detail::traits<A>::size == sizeof...(I), // Require matching component counts.
485                      "swizzle dimension mismatch"); // Explain the rejected input: swizzle dimension mismatch.
486        vec<T, sizeof...(I)> temp; // Keep an independent value for the result or aliased inputs.
487        for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
488            temp[j] = static_cast<T>(detail::component(rhs, j)); // Save this source component before writing the selection.
489        for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
490            (*this)[j] = temp[j]; // Update the selected destination component.
491        return *this; // Allow this update to be used in a chained expression.
492    } // Finish the assign operation.
493#define SHDR_DETAIL_SWIZZLE_ASSIGN(OP, BINARY) /* Generate the matching scalar and vector overloads. */ \
494    template <class A> swizzle_ref& operator OP(const A & rhs) { /* Accept the matching input types and dimensions. */ \
495        return assign(vec<T, sizeof...(I)>(*this) BINARY rhs); /* Write through a temporary so overlapping selections remain safe. */ \
496    } /* Finish this operator overload. */
497    SHDR_DETAIL_SWIZZLE_ASSIGN(+=, +) // Provide componentwise addition.
498    SHDR_DETAIL_SWIZZLE_ASSIGN(-=, -) // Provide componentwise subtraction.
499    SHDR_DETAIL_SWIZZLE_ASSIGN(*=, *) // Provide componentwise multiplication.
500    SHDR_DETAIL_SWIZZLE_ASSIGN(/=, /) // Provide componentwise division.
501    SHDR_DETAIL_SWIZZLE_ASSIGN(%=, %) // Provide componentwise integer remainder.
502    SHDR_DETAIL_SWIZZLE_ASSIGN(&=, &) // Provide componentwise bitwise AND.
503    SHDR_DETAIL_SWIZZLE_ASSIGN(|=, |) // Provide componentwise bitwise OR.
504    SHDR_DETAIL_SWIZZLE_ASSIGN(^=, ^) // Provide componentwise bitwise XOR.
505    SHDR_DETAIL_SWIZZLE_ASSIGN(<<=, <<) // Provide componentwise left shifting.
506    SHDR_DETAIL_SWIZZLE_ASSIGN(>>=, >>) // Provide componentwise right shifting.
507#undef SHDR_DETAIL_SWIZZLE_ASSIGN // Remove this local code generator macro.
508}; // Finish the swizzle_ref type description.
509/** @name Vector component arithmetic
510 * Vector/scalar and scalar/vector forms broadcast the scalar.
511 * Integer operators require integer components, as in GLSL.
512 * @{ */
513#define SHDR_DETAIL_VEC_BINARY(OP) /* Generate the matching scalar and vector overloads. */ \
514    template <class A, class B> /* Accept the matching input types and dimensions. */ \
515    typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
516                            typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
517    operator OP(const A& a, const B& b) { /* Provide this arithmetic or component access overload. */ \
518        typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
519        typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
520        for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
521            out[i] = static_cast<T>(detail::component(a, i) OP detail::component(b, i)); /* Store the computed component in the independent result. */ \
522        } /* Finish this component or matrix pass. */ \
523        return out; /* Return the completed result. */ \
524    } /* Finish this operator overload. */
525SHDR_DETAIL_VEC_BINARY(+) // Provide componentwise addition.
526SHDR_DETAIL_VEC_BINARY(-) // Provide componentwise subtraction.
527SHDR_DETAIL_VEC_BINARY(*) // Provide componentwise multiplication.
528SHDR_DETAIL_VEC_BINARY(/) // Provide componentwise division.
529SHDR_DETAIL_VEC_BINARY(%) // Provide componentwise integer remainder.
530SHDR_DETAIL_VEC_BINARY(&) // Provide componentwise bitwise AND.
531SHDR_DETAIL_VEC_BINARY(|) // Provide componentwise bitwise OR.
532SHDR_DETAIL_VEC_BINARY(^) // Provide componentwise bitwise XOR.
533SHDR_DETAIL_VEC_BINARY(<<) // Provide componentwise left shifting.
534SHDR_DETAIL_VEC_BINARY(>>) // Provide componentwise right shifting.
535#undef SHDR_DETAIL_VEC_BINARY // Remove this local code generator macro.
536template <class A> // Accept the matching input types and dimensions.
537typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
538operator-(const A& a) { // Provide this arithmetic or component access overload.
539    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
540    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
541        out[i] = -a[i]; // Store the computed component in the independent result.
542    return out; // Return the completed result.
543} // Finish this operator overload.
544template <class A> // Accept the matching input types and dimensions.
545typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
546operator+(const A& a) { // Provide this arithmetic or component access overload.
547    return typename detail::result<A>::type(a); // Copy source components before changing the destination.
548} // Finish this operator overload.
549template <class A> // Accept the matching input types and dimensions.
550typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
551operator~(const A& a) { // Provide this arithmetic or component access overload.
552    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
553    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
554        out[i] = ~a[i]; // Store the computed component in the independent result.
555    return out; // Return the completed result.
556} // Finish this operator overload.
557template <class A, class B> // Accept the matching input types and dimensions.
558typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
559                            detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
560                        bool>::type // Complete the type and dimension rule for this overload.
561operator==(const A& a, const B& b) { // Provide this arithmetic or component access overload.
562    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
563        if (a[i] != b[i]) // Stop when corresponding components differ.
564            return false; // Report that at least one component differs.
565    } // Finish this component or matrix pass.
566    return true; // Report that every required component matched.
567} // Finish this operator overload.
568template <class A, class B> // Accept the matching input types and dimensions.
569typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
570                            detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
571                        bool>::type // Complete the type and dimension rule for this overload.
572operator!=(const A& a, const B& b) { // Provide this arithmetic or component access overload.
573    return !(a == b); // Copy source components before changing the destination.
574} // Finish this operator overload.
575/** @} */
576typedef vec<float, 2> vec2; // Name the 2-component float vector.
577typedef vec<float, 3> vec3; // Name the 3-component float vector.
578typedef vec<float, 4> vec4; // Name the 4-component float vector.
579typedef vec<double, 2> dvec2; // Name the 2-component double vector.
580typedef vec<double, 3> dvec3; // Name the 3-component double vector.
581typedef vec<double, 4> dvec4; // Name the 4-component double vector.
582typedef vec<std::int32_t, 2> ivec2; // Name the 2-component signed integer vector.
583typedef vec<std::int32_t, 3> ivec3; // Name the 3-component signed integer vector.
584typedef vec<std::int32_t, 4> ivec4; // Name the 4-component signed integer vector.
585typedef vec<std::uint32_t, 2> uvec2; // Name the 2-component unsigned integer vector.
586typedef vec<std::uint32_t, 3> uvec3; // Name the 3-component unsigned integer vector.
587typedef vec<std::uint32_t, 4> uvec4; // Name the 4-component unsigned integer vector.
588typedef vec<bool, 2> bvec2; // Name the 2-component boolean vector.
589typedef vec<bool, 3> bvec3; // Name the 3-component boolean vector.
590typedef vec<bool, 4> bvec4; // Name the 4-component boolean vector.
591template <class T, std::size_t N> // Accept the matching input types and dimensions.
592std::ostream& operator<<(std::ostream& out, const vec<T, N>& value) { // Provide this arithmetic or component access overload.
593    out << '('; // Write the next component or separator for readable output.
594    for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
595        if (i) // Write a separator only after the first component.
596            out << ", "; // Write the next component or separator for readable output.
597        out << value[i]; // Write the next component or separator for readable output.
598    } // Finish this component or matrix pass.
599    return out << ')'; // Finish the readable representation and return the stream.
600} // Finish this operator overload.
601
602/** @brief A floating-point matrix with C columns and R rows.
603 * A scalar constructor initializes the diagonal and sets other entries to
604 * zero. Component constructors consume scalars and vectors in column order,
605 * discarding excess components in the final argument. Matrix conversion copies
606 * the common region and fills the remaining entries with the identity matrix.
607 * Default construction initializes every component to zero.
608 */
609template <class T, std::size_t C, std::size_t R> class mat { // Describe a matrix by its scalar type and dimensions.
610    static_assert(C >= 2 && C <= 4 && R >= 2 && R <= 4, "matrix dimensions require 2 to 4"); // Require matching component counts.
611    static_assert(std::is_floating_point<T>::value, // Require floating-point components for this operation.
612                  "GLSL matrices require floating point components"); // Explain the rejected input: GLSL matrices require floating point components.
613    vec<T, R> columns_[C]; // Store each matrix column as a vector.
614
615  public: // Expose the public math operations.
616    typedef T value_type; // Expose the element type to host code and templates.
617    typedef vec<T, R> column_type; // Expose the vector type used for each matrix column.
618    static const std::size_t columns = C; // Keep the matrix column count available at compile time.
619    static const std::size_t rows = R; // Keep the matrix row count available at compile time.
620    /** @brief Return the number of matrix columns. */
621    static constexpr std::size_t length() { // Record the compile-time component rule.
622        return C; // Return the fixed number of available components.
623    } // Finish the length operation.
624    mat() : columns_() { // Initialize matrix columns from the supplied values.
625    } // Finish initializing the matrix.
626    template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
627    explicit mat(U diagonal) : columns_() { // Initialize matrix columns from the supplied values.
628        for (std::size_t c = 0; c < C && c < R; ++c) // Visit each matrix column.
629            columns_[c][c] = static_cast<T>(diagonal); // Set this diagonal entry to the requested scalar.
630    } // Finish initializing the matrix.
631    template <class U, std::size_t A, std::size_t B> // Accept the matching input types and dimensions.
632    explicit mat(const mat<U, A, B>& other) : columns_() { // Initialize matrix columns from the supplied values.
633        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
634            for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
635                columns_[c][r] = // Copy or complete this matrix entry.
636                    c < A && r < B ? static_cast<T>(other[c][r]) : (c == r ? T(1) : T(0)); // Copy the common region and use identity entries elsewhere.
637    } // Finish initializing the matrix.
638    /** @brief Construct a matrix from the components of one vector or swizzle. */
639    template <class A, typename std::enable_if<detail::traits<A>::vector, int>::type = 0> // Accept the matching input types and dimensions.
640    explicit mat(const A& value) { // Initialize matrix columns from the supplied values.
641        static_assert(detail::traits<A>::size >= C * R, // Check this type or dimension requirement at compile time.
642                      "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
643        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
644            for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
645                columns_[c][r] = static_cast<T>(value[c * R + r]); // Copy the next source component in column order.
646    } // Finish initializing the matrix.
647    template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
648    explicit mat(const A& a, const B& b, const Rest&... rest) { // Initialize matrix columns from the supplied values.
649        static_assert(!detail::any_matrix<A, B, Rest...>::value, // Check this type or dimension requirement at compile time.
650                      "matrix conversion cannot be mixed with other arguments"); // Require the matrix to be the sole conversion argument.
651        static_assert(detail::count<A, B, Rest...>::value >= C * R, // Require enough components to fill the destination.
652                      "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
653        static_assert(detail::prefix_count<A, B, Rest...>::value < C * R, // Reject constructor arguments that would go unused.
654                      "matrix constructor has unused arguments"); // Explain the rejected input: matrix constructor has unused arguments.
655        T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
656        std::size_t n = 0; // Begin appending at the first temporary component.
657        detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
658        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
659            for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
660                columns_[c][r] = values[c * R + r]; // Fill the column from the flattened constructor values.
661    } // Finish initializing the matrix.
662    /** @brief Read or modify column c.  m[c][r] selects row r within that column. */
663    column_type& operator[](std::size_t c) { // Provide this arithmetic or component access overload.
664        return columns_[c]; // Return the component count or geometric length.
665    } // Finish this operator overload.
666    const column_type& operator[](std::size_t c) const { // Provide this arithmetic or component access overload.
667        return columns_[c]; // Return the component count or geometric length.
668    } // Finish this operator overload.
669    mat& operator+=(const mat& b) { // Provide this arithmetic or component access overload.
670        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
671            columns_[c] += b[c]; // Add the corresponding matrix column.
672        return *this; // Allow this update to be used in a chained expression.
673    } // Finish this operator overload.
674    mat& operator-=(const mat& b) { // Provide this arithmetic or component access overload.
675        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
676            columns_[c] -= b[c]; // Subtract the corresponding matrix column.
677        return *this; // Allow this update to be used in a chained expression.
678    } // Finish this operator overload.
679    mat& operator+=(T b) { // Provide this arithmetic or component access overload.
680        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
681            columns_[c] += b; // Add the scalar to every entry in this column.
682        return *this; // Allow this update to be used in a chained expression.
683    } // Finish this operator overload.
684    mat& operator-=(T b) { // Provide this arithmetic or component access overload.
685        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
686            columns_[c] -= b; // Subtract the scalar from every entry in this column.
687        return *this; // Allow this update to be used in a chained expression.
688    } // Finish this operator overload.
689    mat& operator*=(T b) { // Provide this arithmetic or component access overload.
690        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
691            columns_[c] *= b; // Scale this column by the scalar.
692        return *this; // Allow this update to be used in a chained expression.
693    } // Finish this operator overload.
694    mat& operator/=(T b) { // Provide this arithmetic or component access overload.
695        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
696            columns_[c] /= b; // Divide this column by the scalar.
697        return *this; // Allow this update to be used in a chained expression.
698    } // Finish this operator overload.
699    mat& operator/=(const mat& b) { // Provide this arithmetic or component access overload.
700        for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
701            columns_[c] /= b[c]; // Divide corresponding entries in this column.
702        return *this; // Allow this update to be used in a chained expression.
703    } // Finish this operator overload.
704    mat& operator*=(const mat<T, C, C>& b) { // Provide this arithmetic or component access overload.
705        *this = *this * b;
706        return *this; // Allow this update to be used in a chained expression.
707    } // Finish this operator overload.
708}; // Finish the mat type description.
709template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::columns; // Accept the matching input types and dimensions.
710template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::rows; // Accept the matching input types and dimensions.
711
712/** @brief Convert a scalar, or the first component of a vector, to T.
713 * This implements GLSL scalar constructors such as float(vec3) for generated
714 * C++ kernels. Ordinary C++ callers may use scalar_cast<float>(value) directly.
715 */
716template <class T, class A> // Accept the matching input types and dimensions.
717typename std::enable_if<std::is_arithmetic<T>::value && detail::traits<A>::valid, T>::type // Enable this overload only for compatible input types.
718scalar_cast(const A& value) { // Convert the first scalar component to the requested type.
719    return static_cast<T>(detail::component(value, 0)); // Convert the first scalar component to the requested type.
720} // Finish the scalar_cast operation.
721/** @brief Convert the first column's first matrix component to scalar type T. */
722template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
723typename std::enable_if<std::is_arithmetic<T>::value, T>::type // Enable this overload only for compatible input types.
724scalar_cast(const mat<U, C, R>& value) { // Convert the first scalar component to the requested type.
725    return static_cast<T>(value[0][0]); // Convert the first scalar component to the requested type.
726} // Finish the scalar_cast operation.
727/** @brief GLSL square and rectangular matrix aliases.  dimensions are columns
728 * followed by rows. Float aliases are mat2..4 and mat2x2..mat4x4.  double aliases
729 * use dmat. Double arithmetic is a host extension and requires a supporting
730 * desktop GLSL profile when used by shared shaders.
731 */
732#define SHDR_DETAIL_MATRIX_ALIASES(T, PREFIX) /* Generate the matching scalar and vector overloads. */ \
733    typedef mat<T, 2, 2> PREFIX##2; /* Name the type selected for this math result. */ \
734    typedef mat<T, 3, 3> PREFIX##3; /* Name the type selected for this math result. */ \
735    typedef mat<T, 4, 4> PREFIX##4; /* Name the type selected for this math result. */ \
736    typedef mat<T, 2, 2> PREFIX##2x2; /* Name the type selected for this math result. */ \
737    typedef mat<T, 2, 3> PREFIX##2x3; /* Name the type selected for this math result. */ \
738    typedef mat<T, 2, 4> PREFIX##2x4; /* Name the type selected for this math result. */ \
739    typedef mat<T, 3, 2> PREFIX##3x2; /* Name the type selected for this math result. */ \
740    typedef mat<T, 3, 3> PREFIX##3x3; /* Name the type selected for this math result. */ \
741    typedef mat<T, 3, 4> PREFIX##3x4; /* Name the type selected for this math result. */ \
742    typedef mat<T, 4, 2> PREFIX##4x2; /* Name the type selected for this math result. */ \
743    typedef mat<T, 4, 3> PREFIX##4x3; /* Name the type selected for this math result. */ \
744    typedef mat<T, 4, 4> PREFIX##4x4; /* Name the type selected for this math result. */
745SHDR_DETAIL_MATRIX_ALIASES(float, mat) // Provide the single-precision matrix names.
746SHDR_DETAIL_MATRIX_ALIASES(double, dmat) // Provide the double-precision matrix names.
747#undef SHDR_DETAIL_MATRIX_ALIASES // Remove this local code generator macro.
748template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
749mat<T, C, R> operator+(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
750    return a += b; // Convert the first scalar component to the requested type.
751} // Finish this operator overload.
752template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
753mat<T, C, R> operator-(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
754    return a -= b; // Convert the first scalar component to the requested type.
755} // Finish this operator overload.
756template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator-(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
757    mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
758    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
759        out[c] = -a[c]; // Store the computed component in the independent result.
760    return out; // Return the completed result.
761} // Finish this operator overload.
762template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator+(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
763    return a; // Return the scalar unchanged.
764} // Finish this operator overload.
765#define SHDR_DETAIL_MATRIX_SCALAR(OP, ASSIGN) /* Generate the matching scalar and vector overloads. */ \
766    template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
767    typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
768        mat<T, C, R> a, U b) { /* Keep an independent value for the result or aliased inputs. */ \
769        return a ASSIGN static_cast<T>(b); /* Convert the first scalar component to the requested type. */ \
770    } /* Finish this declaration. */ \
771    template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
772    typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
773        U a, const mat<T, C, R>& b) { /* Accept a scalar before the matrix operand. */ \
774        mat<T, C, R> out; /* Keep an independent value for the result or aliased inputs. */ \
775        for (std::size_t c = 0; c < C; ++c) { /* Visit each matrix column. */ \
776            out[c] = static_cast<T>(a) OP b[c]; /* Store the computed component in the independent result. */ \
777        } /* Finish this component or matrix pass. */ \
778        return out; /* Return the completed result. */ \
779    } /* Finish this declaration. */
780SHDR_DETAIL_MATRIX_SCALAR(+, +=) // Provide componentwise addition.
781SHDR_DETAIL_MATRIX_SCALAR(-, -=) // Provide componentwise subtraction.
782#undef SHDR_DETAIL_MATRIX_SCALAR // Remove this local code generator macro.
783template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
784typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator*(mat<T, C, R> a, // Enable this overload only for compatible input types.
785                                                                                    U b) { // Accept a scalar after the matrix operand.
786    return a *= static_cast<T>(b); // Convert the first scalar component to the requested type.
787} // Finish this declaration.
788template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
789typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
790operator*(U a, mat<T, C, R> b) { // Provide this arithmetic or component access overload.
791    return b *= static_cast<T>(a); // Convert the first scalar component to the requested type.
792} // Finish this operator overload.
793template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
794typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator/(mat<T, C, R> a, // Enable this overload only for compatible input types.
795                                                                                    U b) { // Accept a scalar after the matrix operand.
796    return a /= static_cast<T>(b); // Convert the first scalar component to the requested type.
797} // Finish this declaration.
798template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
799typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
800operator/(U a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
801    mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
802    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
803        out[c] = static_cast<T>(a) / b[c]; // Store the computed component in the independent result.
804    return out; // Return the completed result.
805} // Finish this operator overload.
806template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
807mat<T, C, R> operator/(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
808    mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
809    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
810        out[c] = a[c] / b[c]; // Store the computed component in the independent result.
811    return out; // Return the completed result.
812} // Finish this operator overload.
813template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
814bool operator==(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
815    for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
816        if (a[c] != b[c]) // Handle the exceptional or boundary case before continuing.
817            return false; // Report that at least one component differs.
818    } // Finish this component or matrix pass.
819    return true; // Report that every required component matched.
820} // Finish this operator overload.
821template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
822bool operator!=(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
823    return !(a == b); // Convert the first scalar component to the requested type.
824} // Finish this operator overload.
825/** @brief Algebraic matrix-vector multiplication. */
826template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
827typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == C, vec<T, R>>::type // Enable this overload only for compatible input types.
828operator*(const mat<T, C, R>& a, const A& b) { // Provide this arithmetic or component access overload.
829    vec<T, R> out(T(0)); // Keep an independent value for the result or aliased inputs.
830    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
831        out += a[c] * b[c]; // Add this component product to the running total.
832    return out; // Return the completed result.
833} // Finish this operator overload.
834template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
835typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == R, vec<T, C>>::type // Enable this overload only for compatible input types.
836operator*(const A& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
837    vec<T, C> out(T(0)); // Keep an independent value for the result or aliased inputs.
838    for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
839        for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
840            out[c] += a[r] * b[c][r]; // Store the computed component in the independent result.
841    } // Finish this component or matrix pass.
842    return out; // Return the completed result.
843} // Finish this operator overload.
844/** @brief Algebraic multiplication, including nonsquare matrices. */
845template <class T, std::size_t C, std::size_t R, std::size_t K> // Accept the matching input types and dimensions.
846mat<T, K, R> operator*(const mat<T, C, R>& a, const mat<T, K, C>& b) { // Provide this arithmetic or component access overload.
847    mat<T, K, R> out; // Keep an independent value for the result or aliased inputs.
848    for (std::size_t c = 0; c < K; ++c) // Visit each matrix column.
849        out[c] = a * b[c]; // Store the computed component in the independent result.
850    return out; // Return the completed result.
851} // Finish this operator overload.
852/** @brief Exchange rows and columns, including rectangular matrices. */
853template <class T, std::size_t C, std::size_t R> mat<T, R, C> transpose(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
854    mat<T, R, C> out; // Keep an independent value for the result or aliased inputs.
855    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
856        for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
857            out[r][c] = a[c][r]; // Copy the entry to its exchanged row and column.
858    return out; // Return the completed result.
859} // Finish the transpose operation.
860/** @brief Multiply corresponding matrix components element by element. */
861template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
862mat<T, C, R> matrixCompMult(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Multiply corresponding matrix entries.
863    mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
864    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
865        out[c] = a[c] * b[c]; // Store the computed component in the independent result.
866    return out; // Return the completed result.
867} // Finish the matrixCompMult operation.
868/** @brief Form a column-by-row outer product.  output column j is column*row[j]. */
869template <class T, std::size_t R, std::size_t C> // Accept the matching input types and dimensions.
870mat<T, C, R> outerProduct(const vec<T, R>& column, const vec<T, C>& row) { // Keep an independent value for the result or aliased inputs.
871    mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
872    for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
873        out[c] = column * row[c]; // Store the computed component in the independent result.
874    return out; // Return the completed result.
875} // Finish the outerProduct operation.
876/** @brief Determinant using partial-pivot elimination. */
877template <class T, std::size_t N> T determinant(mat<T, N, N> a) { // Accept the matching input types and dimensions.
878    T result(1); // Begin the determinant product with multiplicative identity.
879    for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
880        std::size_t pivot = i; // Begin with the current row as the pivot candidate.
881        for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
882            if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
883                pivot = r; // Use the stronger row for the next pivot.
884        if (a[i][pivot] == T(0)) // Detect a singular column before division.
885            return T(0); // Compute the determinant with row pivoting.
886        if (pivot != i) { // Swap rows when a better pivot was found.
887            for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
888                T temp = a[c][i]; // Save an entry while exchanging the two rows.
889                a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
890                a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
891            } // Finish this component or matrix pass.
892            result = -result; // Reverse the determinant sign after a row exchange.
893        } // Finish handling this condition.
894        T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
895        result *= diagonal; // Multiply the determinant by the next diagonal value.
896        for (std::size_t r = i + 1; r < N; ++r) { // Visit each matrix row.
897            T factor = a[i][r] / diagonal; // Find the amount of the pivot row to eliminate.
898            for (std::size_t c = i + 1; c < N; ++c) // Visit each matrix column.
899                a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
900        } // Finish this component or matrix pass.
901    } // Finish this component or matrix pass.
902    return result; // Return the completed result.
903} // Finish the determinant operation.
904/** @brief Inverse using partial-pivot Gauss-Jordan elimination.
905 * Singular input has undefined GLSL semantics.  the host returns quiet NaNs.
906 */
907template <class T, std::size_t N> mat<T, N, N> inverse(mat<T, N, N> a) { // Accept the matching input types and dimensions.
908    mat<T, N, N> out(T(1)); // Keep an independent value for the result or aliased inputs.
909    for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
910        std::size_t pivot = i; // Begin with the current row as the pivot candidate.
911        for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
912            if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
913                pivot = r; // Use the stronger row for the next pivot.
914        if (a[i][pivot] == T(0)) { // Detect a singular column before division.
915            for (std::size_t c = 0; c < N; ++c) // Visit each matrix column.
916                out[c] = vec<T, N>(std::numeric_limits<T>::quiet_NaN()); // Store the computed component in the independent result.
917            return out; // Return the completed result.
918        } // Finish handling this condition.
919        if (pivot != i) // Swap rows when a better pivot was found.
920            for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
921                T temp = a[c][i]; // Save an entry while exchanging the two rows.
922                a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
923                a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
924                temp = out[c][i]; // Save an entry while exchanging the two rows.
925                out[c][i] = out[c][pivot]; // Store the computed component in the independent result.
926                out[c][pivot] = temp; // Store the computed component in the independent result.
927            } // Finish this component or matrix pass.
928        T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
929        for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
930            a[c][i] /= diagonal; // Update this matrix entry during row elimination or exchange.
931            out[c][i] /= diagonal; // Store the computed component in the independent result.
932        } // Finish this component or matrix pass.
933        for (std::size_t r = 0; r < N; ++r) // Visit each matrix row.
934            if (r != i) { // Handle the exceptional or boundary case before continuing.
935                T factor = a[i][r]; // Find the amount of the pivot row to eliminate.
936                for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
937                    a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
938                    out[c][r] -= factor * out[c][i]; // Subtract the pivot-row contribution from the inverse.
939                } // Finish this component or matrix pass.
940            } // Finish handling this condition.
941    } // Finish this component or matrix pass.
942    return out; // Return the completed result.
943} // Finish the inverse operation.
944template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
945std::ostream& operator<<(std::ostream& out, const mat<T, C, R>& value) { // Provide this arithmetic or component access overload.
946    out << '['; // Write the next component or separator for readable output.
947    for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
948        if (c) // Write a separator only after the first component.
949            out << ", "; // Write the next component or separator for readable output.
950        out << value[c]; // Write the next component or separator for readable output.
951    } // Finish this component or matrix pass.
952    return out << ']'; // Finish the readable representation and return the stream.
953} // Finish this operator overload.
954/** @name Angle, exponential and common scalar/vector math
955 * Floating-point overloads preserve their component type. Vector overloads
956 * apply each scalar operation independently, including swizzle expressions.
957 * @{ */
958#define SHDR_DETAIL_FLOAT_UNARY(NAME, EXPR) /* Generate the matching scalar and vector overloads. */ \
959    template <class T> /* Accept the matching input types and dimensions. */ \
960    typename std::enable_if<std::is_floating_point<T>::value, T>::type NAME(T x) { /* Enable this overload only for compatible input types. */ \
961        return static_cast<T>(EXPR); /* Compute the inverse with row pivoting. */ \
962    } /* Finish this generated overload. */ \
963    template <class A> /* Accept the matching input types and dimensions. */ \
964    typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type /* Enable this overload only for compatible input types. */ \
965    NAME(const A& x) { /* Start the matching math overload. */ \
966        typedef typename detail::traits<A>::scalar T; /* Keep the chosen component type for the calculation. */ \
967        static_assert(std::is_floating_point<T>::value, "floating point components required"); /* Require floating-point components for this operation. */ \
968        typename detail::result<A>::type out; /* Allocate an independent result with the correct shape. */ \
969        for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
970            out[i] = glsl::NAME(x[i]); /* Store the computed component in the independent result. */ \
971        return out; /* Return the completed result. */ \
972    } /* Finish this generated overload. */
973SHDR_DETAIL_FLOAT_UNARY(radians, x* T(0.01745329251994329576923690768489L)) // Convert degrees to radians for scalars and vector components.
974SHDR_DETAIL_FLOAT_UNARY(degrees, x* T(57.295779513082320876798154814105L)) // Convert radians to degrees for scalars and vector components.
975SHDR_DETAIL_FLOAT_UNARY(sin, std::sin(x)) // Compute the sine for scalars and vector components.
976SHDR_DETAIL_FLOAT_UNARY(cos, std::cos(x)) // Compute the cosine for scalars and vector components.
977SHDR_DETAIL_FLOAT_UNARY(tan, std::tan(x)) // Compute the tangent for scalars and vector components.
978SHDR_DETAIL_FLOAT_UNARY(asin, std::asin(x)) // Compute the inverse sine for scalars and vector components.
979SHDR_DETAIL_FLOAT_UNARY(acos, std::acos(x)) // Compute the inverse cosine for scalars and vector components.
980SHDR_DETAIL_FLOAT_UNARY(atan, std::atan(x)) // Compute the inverse tangent for scalars and vector components.
981SHDR_DETAIL_FLOAT_UNARY(sinh, std::sinh(x)) // Compute the hyperbolic sine for scalars and vector components.
982SHDR_DETAIL_FLOAT_UNARY(cosh, std::cosh(x)) // Compute the hyperbolic cosine for scalars and vector components.
983SHDR_DETAIL_FLOAT_UNARY(tanh, std::tanh(x)) // Compute the hyperbolic tangent for scalars and vector components.
984SHDR_DETAIL_FLOAT_UNARY(asinh, std::asinh(x)) // Compute the inverse hyperbolic sine for scalars and vector components.
985SHDR_DETAIL_FLOAT_UNARY(acosh, std::acosh(x)) // Compute the inverse hyperbolic cosine for scalars and vector components.
986SHDR_DETAIL_FLOAT_UNARY(atanh, std::atanh(x)) // Compute the inverse hyperbolic tangent for scalars and vector components.
987SHDR_DETAIL_FLOAT_UNARY(exp, std::exp(x)) // Raise e to the input power for scalars and vector components.
988SHDR_DETAIL_FLOAT_UNARY(log, std::log(x)) // Compute the natural logarithm for scalars and vector components.
989SHDR_DETAIL_FLOAT_UNARY(exp2, std::exp2(x)) // Raise two to the input power for scalars and vector components.
990SHDR_DETAIL_FLOAT_UNARY(log2, std::log2(x)) // Compute the base-two logarithm for scalars and vector components.
991SHDR_DETAIL_FLOAT_UNARY(sqrt, std::sqrt(x)) // Compute the square root for scalars and vector components.
992SHDR_DETAIL_FLOAT_UNARY(inversesqrt, T(1) / std::sqrt(x)) // Compute the reciprocal square root for scalars and vector components.
993SHDR_DETAIL_FLOAT_UNARY(floor, std::floor(x)) // Round toward negative infinity for scalars and vector components.
994SHDR_DETAIL_FLOAT_UNARY(trunc, std::trunc(x)) // Round toward zero for scalars and vector components.
995SHDR_DETAIL_FLOAT_UNARY(round, std::round(x)) // Round to the nearest integer for scalars and vector components.
996SHDR_DETAIL_FLOAT_UNARY(ceil, std::ceil(x)) // Round toward positive infinity for scalars and vector components.
997SHDR_DETAIL_FLOAT_UNARY(fract, x - std::floor(x)) // Keep the fraction above the floor for scalars and vector components.
998#undef SHDR_DETAIL_FLOAT_UNARY // Remove this local code generator macro.
999template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type abs(T x) { // Accept the matching input types and dimensions.
1000    return x < T(0) ? -x : x; // Return a nonnegative magnitude.
1001} // Finish the abs operation.
1002template <class A> // Accept the matching input types and dimensions.
1003typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1004abs(const A& a) { // Return a nonnegative magnitude.
1005    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1006    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1007        out[i] = glsl::abs(a[i]); // Store the computed component in the independent result.
1008    return out; // Return the completed result.
1009} // Finish the abs operation.
1010template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type sign(T x) { // Accept the matching input types and dimensions.
1011    return x > T(0) ? T(1) : (x < T(0) ? T(-1) : T(0)); // Return minus one, zero or one from the input sign.
1012} // Finish the sign operation.
1013template <class A> // Accept the matching input types and dimensions.
1014typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1015sign(const A& a) { // Return minus one, zero or one from the input sign.
1016    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1017    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1018        out[i] = glsl::sign(a[i]); // Store the computed component in the independent result.
1019    return out; // Return the completed result.
1020} // Finish the sign operation.
1021/** @brief Round halfway cases to the nearest even integer, independent of the
1022 * host's floating-point rounding mode. Nonfinite inputs are preserved.
1023 */
1024template <class T> // Accept the matching input types and dimensions.
1025typename std::enable_if<std::is_floating_point<T>::value, T>::type roundEven(T x) { // Enable this overload only for compatible input types.
1026    if (!std::isfinite(x)) // Keep nonfinite inputs unchanged.
1027        return x; // Round halfway values to the nearest even integer.
1028    T lo = std::floor(x), fraction = x - lo; // Separate the lower integer from its fractional remainder.
1029    if (fraction < T(0.5)) // Choose the lower integer below the halfway point.
1030        return lo; // Round halfway values to the nearest even integer.
1031    if (fraction > T(0.5)) // Choose the upper integer above the halfway point.
1032        return lo + T(1); // Round halfway values to the nearest even integer.
1033    return std::fmod(lo, T(2)) == T(0) ? lo : lo + T(1); // Round halfway values to the nearest even integer.
1034} // Finish the roundEven operation.
1035template <class A> // Accept the matching input types and dimensions.
1036typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1037roundEven(const A& a) { // Round halfway values to the nearest even integer.
1038    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1039    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1040        out[i] = glsl::roundEven(a[i]); // Store the computed component in the independent result.
1041    return out; // Return the completed result.
1042} // Finish the roundEven operation.
1043#define SHDR_DETAIL_MATH_BINARY(NAME, ENABLE, EXPR) /* Generate the matching scalar and vector overloads. */ \
1044    template <class T> typename std::enable_if<ENABLE, T>::type NAME(T x, T y) { /* Accept the matching input types and dimensions. */ \
1045        return static_cast<T>(EXPR); /* Round halfway values to the nearest even integer. */ \
1046    } /* Finish this generated overload. */ \
1047    template <class A, class B> /* Accept the matching input types and dimensions. */ \
1048    typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
1049                            typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
1050    NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1051        typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
1052        typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
1053        for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
1054            out[i] = glsl::NAME(static_cast<T>(detail::component(a, i)), /* Store the computed component in the independent result. */ \
1055                                static_cast<T>(detail::component(b, i))); /* Convert the second operand component to the result type. */ \
1056        } /* Finish this component or matrix pass. */ \
1057        return out; /* Return the completed result. */ \
1058    } /* Finish this generated overload. */
1059SHDR_DETAIL_MATH_BINARY(atan, std::is_floating_point<T>::value, std::atan2(x, y)) // Compute the inverse tangent for scalars and vector components.
1060SHDR_DETAIL_MATH_BINARY(pow, std::is_floating_point<T>::value, std::pow(x, y)) // Raise each base to its exponent.
1061SHDR_DETAIL_MATH_BINARY(mod, std::is_floating_point<T>::value, x - y * std::floor(x / y)) // Use the GLSL floor-based remainder.
1062SHDR_DETAIL_MATH_BINARY(min, std::is_arithmetic<T>::value, y < x ? y : x) // Choose the smaller value.
1063SHDR_DETAIL_MATH_BINARY(max, std::is_arithmetic<T>::value, x < y ? y : x) // Choose the larger value.
1064SHDR_DETAIL_MATH_BINARY(step, std::is_floating_point<T>::value, y < x ? T(0) : T(1)) // Return zero below the edge and one otherwise.
1065#undef SHDR_DETAIL_MATH_BINARY // Remove this local code generator macro.
1066/** @brief Fused multiply-add.  final rounding may differ across CPU/GPU. */
1067template <class T> // Accept the matching input types and dimensions.
1068typename std::enable_if<std::is_floating_point<T>::value, T>::type fma(T a, T b, T c) { // Enable this overload only for compatible input types.
1069    return std::fma(a, b, c); // Multiply and add with one final rounding.
1070} // Finish the fma operation.
1071template <class A, class B, class C> // Accept the matching input types and dimensions.
1072typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1073fma(const A& a, const B& b, const C& c) { // Multiply and add with one final rounding.
1074    static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1075                  "fma dimensions mismatch"); // Explain the rejected input: fma dimensions mismatch.
1076    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1077    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1078    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1079        out[i] = glsl::fma( // Store the computed component in the independent result.
1080            a[i], static_cast<T>(detail::component(b, i)), static_cast<T>(detail::component(c, i))); // Supply the matching three components to fused multiply-add.
1081    return out; // Return the completed result.
1082} // Finish the fma operation.
1083template <class T> // Accept the matching input types and dimensions.
1084typename std::enable_if<std::is_arithmetic<T>::value, T>::type clamp(T x, T lower, T upper) { // Enable this overload only for compatible input types.
1085    return glsl::min(glsl::max(x, lower), upper); // Keep a value between its lower and upper limits.
1086} // Finish the clamp operation.
1087template <class A, class B, class C> // Accept the matching input types and dimensions.
1088typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1089clamp(const A& a, const B& lower, const C& upper) { // Keep a value between its lower and upper limits.
1090    static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1091                  "clamp dimensions mismatch"); // Explain the rejected input: clamp dimensions mismatch.
1092    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1093    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1094    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1095        out[i] = glsl::clamp(a[i], // Store the computed component in the independent result.
1096                             static_cast<T>(detail::component(lower, i)), // Use the matching lower bound component.
1097                             static_cast<T>(detail::component(upper, i))); // Use the matching upper bound component.
1098    return out; // Return the completed result.
1099} // Finish the clamp operation.
1100template <class T, class U> // Accept the matching input types and dimensions.
1101typename std::enable_if<std::is_floating_point<T>::value && std::is_arithmetic<U>::value && // Enable this overload only for compatible input types.
1102                            !std::is_same<U, bool>::value, // Complete the type and dimension rule for this overload.
1103                        T>::type // Complete the type and dimension rule for this overload.
1104mix(T x, T y, U selector) { // Blend values or select one with a boolean.
1105    T a = static_cast<T>(selector); // Convert the interpolation amount to the component type.
1106    return x * (T(1) - a) + y * a; // Blend values or select one with a boolean.
1107} // Finish the mix operation.
1108template <class T, class B> // Accept the matching input types and dimensions.
1109typename std::enable_if<std::is_arithmetic<T>::value && std::is_same<B, bool>::value, T>::type // Enable this overload only for compatible input types.
1110mix(T x, T y, B a) { // Blend values or select one with a boolean.
1111    return a ? y : x; // Blend values or select one with a boolean.
1112} // Finish the mix operation.
1113template <class A, class B, class C> // Accept the matching input types and dimensions.
1114typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1115mix(const A& a, const B& b, const C& selector) { // Blend values or select one with a boolean.
1116    static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1117                  "mix dimensions mismatch"); // Explain the rejected input: mix dimensions mismatch.
1118    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1119    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1120    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1121        out[i] = glsl::mix( // Store the computed component in the independent result.
1122            a[i], static_cast<T>(detail::component(b, i)), detail::component(selector, i)); // Blend or select the matching input components.
1123    return out; // Return the completed result.
1124} // Finish the mix operation.
1125template <class T> // Accept the matching input types and dimensions.
1126typename std::enable_if<std::is_floating_point<T>::value, T>::type // Enable this overload only for compatible input types.
1127smoothstep(T lower, T upper, T x) { // Interpolate smoothly between two edges.
1128    T t = glsl::clamp((x - lower) / (upper - lower), T(0), T(1)); // Map the input into a clamped zero-to-one interval.
1129    return t * t * (T(3) - T(2) * t); // Interpolate smoothly between two edges.
1130} // Finish the smoothstep operation.
1131template <class A, class B, class C> // Accept the matching input types and dimensions.
1132typename std::enable_if<detail::traits<C>::vector, typename detail::result<C>::type>::type // Enable this overload only for compatible input types.
1133smoothstep(const A& lower, const B& upper, const C& x) { // Interpolate smoothly between two edges.
1134    static_assert(detail::binary<C, A>::valid && detail::binary<C, B>::valid, // Check this type or dimension requirement at compile time.
1135                  "smoothstep dimensions mismatch"); // Explain the rejected input: smoothstep dimensions mismatch.
1136    typedef typename detail::traits<C>::scalar T; // Keep the chosen component type for the calculation.
1137    typename detail::result<C>::type out; // Allocate an independent result with the correct shape.
1138    for (std::size_t i = 0; i < detail::traits<C>::size; ++i) // Visit each component needed by this calculation.
1139        out[i] = glsl::smoothstep(static_cast<T>(detail::component(lower, i)), // Store the computed component in the independent result.
1140                                  static_cast<T>(detail::component(upper, i)), // Use the matching upper interpolation edge.
1141                                  x[i]); // Interpolate this input component between its edges.
1142    return out; // Return the completed result.
1143} // Finish the smoothstep operation.
1144template <class T> // Accept the matching input types and dimensions.
1145typename std::enable_if<std::is_floating_point<T>::value, bool>::type isnan(T x) { // Enable this overload only for compatible input types.
1146    return std::isnan(x); // Check whether the value is not a number.
1147} // Finish the isnan operation.
1148template <class T> // Accept the matching input types and dimensions.
1149typename std::enable_if<std::is_floating_point<T>::value, bool>::type isinf(T x) { // Enable this overload only for compatible input types.
1150    return std::isinf(x); // Check whether the value is infinite.
1151} // Finish the isinf operation.
1152#define SHDR_DETAIL_CLASSIFICATION(NAME) /* Generate the matching scalar and vector overloads. */ \
1153    template <class A> /* Accept the matching input types and dimensions. */ \
1154    typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1155    NAME(const A& a) { /* Start the matching math overload. */ \
1156        vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1157        for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1158            out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1159        return out; /* Return the completed result. */ \
1160    } /* Finish this generated overload. */
1161SHDR_DETAIL_CLASSIFICATION(isnan) // Check whether the value is not a number.
1162SHDR_DETAIL_CLASSIFICATION(isinf) // Check whether the value is infinite.
1163#undef SHDR_DETAIL_CLASSIFICATION // Remove this local code generator macro.
1164template <class T> // Accept the matching input types and dimensions.
1165typename std::enable_if<std::is_floating_point<T>::value, T>::type modf(T x, T& integer) { // Enable this overload only for compatible input types.
1166    return std::modf(x, &integer); // Separate fractional and integral components.
1167} // Finish the modf operation.
1168/** @brief Split a vector into signed fractional and integer parts.
1169 * The return value contains fractional components.  integer receives the
1170 * integral components. Both arguments may be swizzles, including selections
1171 * of the same vector, because the input is copied before output assignment.
1172 */
1173template <class A, class B> // Accept the matching input types and dimensions.
1174typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1175                        typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1176modf(const A& x, B&& integer) { // Separate fractional and integral components.
1177    static_assert(detail::traits<A>::size == detail::traits<B>::size, "modf dimensions mismatch"); // Require matching component counts.
1178    static_assert( // Check this type or dimension requirement at compile time.
1179        std::is_same<typename detail::traits<A>::scalar, typename detail::traits<B>::scalar>::value, // Require the input and output component types to match.
1180        "modf component types must match"); // Explain the rejected input: modf component types must match.
1181    static_assert(detail::writable<B>::value, "modf output requires writable unique components"); // Prevent repeated destination components.
1182    typename detail::result<A>::type input(x), out, integral; // Preserve the selected component type and result shape.
1183    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1184        out[i] = glsl::modf(input[i], integral[i]); // Store the computed component in the independent result.
1185    integer = integral; // Publish all integral components after reading the input.
1186    return out; // Return the completed result.
1187} // Finish the modf operation.
1188template <class T> // Accept the matching input types and dimensions.
1189typename std::enable_if<std::is_floating_point<T>::value, T>::type frexp(T x, int& exponent) { // Enable this overload only for compatible input types.
1190    return std::frexp(x, &exponent); // Separate a significand and its binary exponent.
1191} // Finish the frexp operation.
1192/** @brief Return binary significands and write matching signed exponents.
1193 * Each nonzero component satisfies x = significand * 2^exponent. Output may be
1194 * an integer vector or a writable swizzle with matching component count.
1195 */
1196template <class A, class B> // Accept the matching input types and dimensions.
1197typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1198                        typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1199frexp(const A& x, B&& exponent) { // Separate a significand and its binary exponent.
1200    static_assert(detail::traits<A>::size == detail::traits<B>::size, "frexp dimensions mismatch"); // Require matching component counts.
1201    static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1202                  "frexp requires signed integer exponent components"); // Explain the rejected input: frexp requires signed integer exponent components.
1203    static_assert(detail::writable<B>::value, "frexp output requires writable unique components"); // Prevent repeated destination components.
1204    typename detail::result<A>::type input(x), out; // Allocate an independent result with the correct shape.
1205    vec<std::int32_t, detail::traits<A>::size> powers; // Use the selected vector or matrix shape for this value.
1206    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1207        int e = 0; // Prepare a signed exponent for this component.
1208        out[i] = std::frexp(input[i], &e); // Store the computed component in the independent result.
1209        powers[i] = e; // Store the binary exponent for this component.
1210    } // Finish this component or matrix pass.
1211    exponent = powers; // Publish all exponents after reading the input.
1212    return out; // Return the completed result.
1213} // Finish the frexp operation.
1214template <class T> // Accept the matching input types and dimensions.
1215typename std::enable_if<std::is_floating_point<T>::value, T>::type ldexp(T x, int exponent) { // Enable this overload only for compatible input types.
1216    return std::ldexp(x, exponent); // Scale a significand by a power of two.
1217} // Finish the ldexp operation.
1218/** @brief Multiply each component by two raised to its signed integer exponent. */
1219template <class A, class B> // Accept the matching input types and dimensions.
1220typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1221                        typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1222ldexp(const A& x, const B& exponent) { // Scale a significand by a power of two.
1223    static_assert(detail::traits<A>::size == detail::traits<B>::size, "ldexp dimensions mismatch"); // Require matching component counts.
1224    static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1225                  "ldexp requires signed integer exponent components"); // Explain the rejected input: ldexp requires signed integer exponent components.
1226    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1227    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1228        out[i] = std::ldexp(x[i], exponent[i]); // Store the computed component in the independent result.
1229    return out; // Return the completed result.
1230} // Finish the ldexp operation.
1231/** @} */
1232
1233/** @name Geometry
1234 * Geometry uses scalar dot products and GLSL's usual component formulas.
1235 * normalize requires nonzero length. Inputs to reflect, refract and faceforward
1236 * should obey GLSL's normalized-normal requirements.
1237 * @{ */
1238template <class T> // Accept the matching input types and dimensions.
1239typename std::enable_if<std::is_floating_point<T>::value, T>::type dot(T a, T b) { // Enable this overload only for compatible input types.
1240    return a * b; // Sum products of corresponding components.
1241} // Finish the dot operation.
1242template <class A, class B> // Accept the matching input types and dimensions.
1243typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1244                        typename detail::traits<A>::scalar>::type // Preserve the selected component type and result shape.
1245dot(const A& a, const B& b) { // Sum products of corresponding components.
1246    static_assert(detail::traits<A>::size == detail::traits<B>::size, "dot dimensions mismatch"); // Require matching component counts.
1247    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1248    T out(0); // Start the scalar accumulator at zero.
1249    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1250        out += a[i] * b[i]; // Add this component product to the running total.
1251    } // Finish this component or matrix pass.
1252    return out; // Return the completed result.
1253} // Finish the dot operation.
1254template <class T> typename std::enable_if<std::is_floating_point<T>::value, T>::type length(T x) { // Accept the matching input types and dimensions.
1255    return glsl::abs(x); // Return the component count or geometric length.
1256} // Finish the length operation.
1257template <class A> // Accept the matching input types and dimensions.
1258typename std::enable_if<detail::traits<A>::vector, typename detail::traits<A>::scalar>::type // Enable this overload only for compatible input types.
1259length(const A& a) { // Return the component count or geometric length.
1260    return glsl::sqrt(glsl::dot(a, a)); // Return the component count or geometric length.
1261} // Finish the length operation.
1262template <class A, class B> auto distance(const A& a, const B& b) -> decltype(glsl::length(a - b)) { // Accept the matching input types and dimensions.
1263    return glsl::length(a - b); // Measure the length of the difference.
1264} // Finish the distance operation.
1265template <class A, class B> // Accept the matching input types and dimensions.
1266typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1267                            detail::traits<A>::size == 3 && detail::traits<B>::size == 3, // Complete the type and dimension rule for this overload.
1268                        vec<typename detail::traits<A>::scalar, 3>>::type // Preserve the selected component type and result shape.
1269cross(const A& a, const B& b) { // Compute the three-dimensional cross product.
1270    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1271    return vec<T, 3>( // Compute the three-dimensional cross product.
1272        a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]); // Use the three signed two-by-two minors for the cross product.
1273} // Finish the cross operation.
1274template <class A> // Accept the matching input types and dimensions.
1275typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1276normalize(const A& a) { // Scale a nonzero value to unit length.
1277    return a / glsl::length(a); // Scale a nonzero value to unit length.
1278} // Finish the normalize operation.
1279template <class A, class B, class C> // Accept the matching input types and dimensions.
1280typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1281faceforward(const A& normal, const B& incident, const C& reference) { // Choose the normal direction facing the incident vector.
1282    return glsl::dot(reference, incident) < 0 ? normal : -normal; // Choose the normal direction facing the incident vector.
1283} // Finish the faceforward operation.
1284template <class A, class B> // Accept the matching input types and dimensions.
1285typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1286reflect(const A& incident, const B& normal) { // Reflect an incident vector around its normal.
1287    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1288    return incident - T(2) * glsl::dot(normal, incident) * normal; // Reflect an incident vector around its normal.
1289} // Finish the reflect operation.
1290template <class A, class B> // Accept the matching input types and dimensions.
1291typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1292refract(const A& incident, const B& normal, typename detail::traits<A>::scalar eta) { // Refract an incident vector using the index ratio.
1293    typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1294    T d = glsl::dot(normal, incident); // Measure the incident component along the normal.
1295    T k = T(1) - eta * eta * (T(1) - d * d); // Compute the refraction discriminant before taking its root.
1296    return k < T(0) ? typename detail::result<A>::type(T(0)) // Refract an incident vector using the index ratio.
1297                    : eta * incident - (eta * d + glsl::sqrt(k)) * normal; // Apply the transmitted-direction formula when refraction is possible.
1298} // Finish the refract operation.
1299/** @} */
1300
1301/** @name Vector relational functions
1302 * operator== compares the whole vector and returns bool. These builtins return
1303 * component masks. logicalNot is the C++ spelling of GLSL's reserved `not`.
1304 * @{ */
1305#define SHDR_DETAIL_RELATIONAL(NAME, OP) /* Generate the matching scalar and vector overloads. */ \
1306    template <class A, class B> /* Accept the matching input types and dimensions. */ \
1307    typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, /* Enable this overload only for compatible input types. */ \
1308                            vec<bool, detail::traits<A>::size>>::type /* Use the selected vector or matrix shape for this value. */ \
1309    NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1310        static_assert(detail::traits<A>::size == detail::traits<B>::size, /* Require matching component counts. */ \
1311                      "relational dimensions mismatch"); /* Explain the rejected input: relational dimensions mismatch. */ \
1312        vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1313        for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1314            out[i] = a[i] OP b[i]; /* Store the computed component in the independent result. */ \
1315        return out; /* Return the completed result. */ \
1316    } /* Finish this generated overload. */
1317SHDR_DETAIL_RELATIONAL(lessThan, <) // Provide the requested component operation.
1318SHDR_DETAIL_RELATIONAL(lessThanEqual, <=) // Provide the requested component operation.
1319SHDR_DETAIL_RELATIONAL(greaterThan, >) // Provide the requested component operation.
1320SHDR_DETAIL_RELATIONAL(greaterThanEqual, >=) // Provide the requested component operation.
1321SHDR_DETAIL_RELATIONAL(equal, ==) // Provide the requested component operation.
1322SHDR_DETAIL_RELATIONAL(notEqual, !=) // Provide the requested component operation.
1323#undef SHDR_DETAIL_RELATIONAL // Remove this local code generator macro.
1324template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type any(const A& a) { // Accept the matching input types and dimensions.
1325    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1326        if (a[i]) // Handle the exceptional or boundary case before continuing.
1327            return true; // Report that every required component matched.
1328    return false; // Report that at least one component differs.
1329} // Finish the any operation.
1330template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type all(const A& a) { // Accept the matching input types and dimensions.
1331    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1332        if (!a[i]) // Handle the exceptional or boundary case before continuing.
1333            return false; // Report that at least one component differs.
1334    return true; // Report that every required component matched.
1335} // Finish the all operation.
1336template <class A> // Accept the matching input types and dimensions.
1337typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1338logicalNot(const A& a) { // Invert each boolean component.
1339    vec<bool, detail::traits<A>::size> out; // Keep an independent value for the result or aliased inputs.
1340    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1341        out[i] = !a[i]; // Store the computed component in the independent result.
1342    return out; // Return the completed result.
1343} // Finish the logicalNot operation.
1344template <class A> // Accept the matching input types and dimensions.
1345typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1346_not(const A& a) { // Start the matching math overload.
1347    return glsl::logicalNot(a); // Invert each boolean component.
1348} // Finish the _not operation.
1349/** @} */
1350/** @name 32-bit bit operations
1351 * Reinterpretation uses memcpy and requires IEEE binary32 floats and 32-bit
1352 * integers. Bitfield ranges must satisfy 0 <= offset,bits and offset+bits<=32.
1353 * The 64-bit host intermediates in extended multiplication are never exposed
1354 * to shared shaders. Bit searches and counts return signed integer results.
1355 * @{ */
1356namespace detail { // Keep these names inside the detail namespace.
1357template <class To, class From> To bit_copy(const From& value) { // Accept the matching input types and dimensions.
1358    static_assert(sizeof(To) == sizeof(From), "bit conversion requires equal sizes"); // Check this type or dimension requirement at compile time.
1359    To out; // Allocate a destination with the same bit width.
1360    std::memcpy(&out, &value, sizeof(out)); // Copy the bits with the alias-safe byte-copy operation.
1361    return out; // Return the completed result.
1362} // Finish the bit_copy operation.
1363inline std::uint32_t bit_mask(int bits) { // Start the matching math overload.
1364    return bits == 32 ? UINT32_MAX : (bits == 0 ? 0u : (std::uint32_t(1) << bits) - 1u); // Invert each boolean component.
1365} // Finish the bit_mask operation.
1366template <class T> // Accept the matching input types and dimensions.
1367struct integer32 : std::integral_constant<bool, // Describe this input or selection at compile time.
1368                                          std::is_integral<T>::value && // Require integer components for the bit operation.
1369                                              !std::is_same<T, bool>::value && sizeof(T) == 4> {}; // Complete the type and dimension rule for this overload.
1370} // namespace detail
1371inline std::uint32_t floatBitsToUint(float x) { // Copy float bits into an unsigned integer.
1372    static_assert(sizeof(float) == 4 && std::numeric_limits<float>::is_iec559, // Check this type or dimension requirement at compile time.
1373                  "IEEE binary32 float required"); // Explain the rejected input: IEEE binary32 float required.
1374    return detail::bit_copy<std::uint32_t>(x); // Copy float bits into an unsigned integer.
1375} // Finish the floatBitsToUint operation.
1376inline std::int32_t floatBitsToInt(float x) { // Copy float bits into a signed integer.
1377    return detail::bit_copy<std::int32_t>(x); // Copy float bits into a signed integer.
1378} // Finish the floatBitsToInt operation.
1379inline float uintBitsToFloat(std::uint32_t x) { // Copy unsigned integer bits into a float.
1380    return detail::bit_copy<float>(x); // Copy unsigned integer bits into a float.
1381} // Finish the uintBitsToFloat operation.
1382inline float intBitsToFloat(std::int32_t x) { // Copy signed integer bits into a float.
1383    return detail::bit_copy<float>(x); // Copy signed integer bits into a float.
1384} // Finish the intBitsToFloat operation.
1385#define SHDR_DETAIL_BIT_VECTOR(NAME, OUT_T) /* Generate the matching scalar and vector overloads. */ \
1386    template <class A> /* Accept the matching input types and dimensions. */ \
1387    typename std::enable_if<detail::traits<A>::vector, vec<OUT_T, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1388    NAME(const A& a) { /* Start the matching math overload. */ \
1389        vec<OUT_T, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1390        for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1391            out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1392        return out; /* Return the completed result. */ \
1393    } /* Finish this generated overload. */
1394SHDR_DETAIL_BIT_VECTOR(floatBitsToUint, std::uint32_t) // Copy float bits into an unsigned integer.
1395SHDR_DETAIL_BIT_VECTOR(floatBitsToInt, std::int32_t) // Copy float bits into a signed integer.
1396SHDR_DETAIL_BIT_VECTOR(uintBitsToFloat, float) // Copy unsigned integer bits into a float.
1397SHDR_DETAIL_BIT_VECTOR(intBitsToFloat, float) // Copy signed integer bits into a float.
1398template <class T> // Accept the matching input types and dimensions.
1399typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type bitCount(T x) { // Enable this overload only for compatible input types.
1400    std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1401    std::int32_t count = 0; // Hold the exact integer bits used by this operation.
1402    while (v) { // Continue until the remaining bits reach the required form.
1403        v &= v - 1u; // Remove the least significant set bit.
1404        ++count; // Count the set bit that was removed.
1405    } // Finish this component or matrix pass.
1406    return count; // Count the set bits in a 32-bit value.
1407} // Finish the bitCount operation.
1408template <class T> // Accept the matching input types and dimensions.
1409typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findLSB(T x) { // Enable this overload only for compatible input types.
1410    std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1411    if (!v) // Handle the exceptional or boundary case before continuing.
1412        return -1; // Find the first set bit from the least significant end.
1413    std::int32_t position = 0; // Hold the exact integer bits used by this operation.
1414    while (!(v & 1u)) { // Continue until the remaining bits reach the required form.
1415        v >>= 1; // Move the next bit into the least significant position.
1416        ++position; // Advance the bit position being tested.
1417    } // Finish this component or matrix pass.
1418    return position; // Find the first set bit from the least significant end.
1419} // Finish the findLSB operation.
1420template <class T> // Accept the matching input types and dimensions.
1421typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findMSB(T x) { // Enable this overload only for compatible input types.
1422    std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1423    if (std::is_signed<T>::value && x < T(0)) // Handle the exceptional or boundary case before continuing.
1424        v = ~v; // For negative values, search for the highest zero bit.
1425    std::int32_t position = -1; // Hold the exact integer bits used by this operation.
1426    while (v) { // Continue until the remaining bits reach the required form.
1427        v >>= 1; // Move the next bit into the least significant position.
1428        ++position; // Advance the bit position being tested.
1429    } // Finish this component or matrix pass.
1430    return position; // Find the highest bit that differs from the sign bit.
1431} // Finish the findMSB operation.
1432SHDR_DETAIL_BIT_VECTOR(bitCount, std::int32_t) // Count the set bits in a 32-bit value.
1433SHDR_DETAIL_BIT_VECTOR(findLSB, std::int32_t) // Find the first set bit from the least significant end.
1434SHDR_DETAIL_BIT_VECTOR(findMSB, std::int32_t) // Find the highest bit that differs from the sign bit.
1435#undef SHDR_DETAIL_BIT_VECTOR // Remove this local code generator macro.
1436template <class T> // Accept the matching input types and dimensions.
1437typename std::enable_if<detail::integer32<T>::value, T>::type bitfieldReverse(T x) { // Enable this overload only for compatible input types.
1438    std::uint32_t v = static_cast<std::uint32_t>(x), out = 0; // Hold the exact integer bits used by this operation.
1439    for (int i = 0; i < 32; ++i) { // Visit all 32 bits of the value.
1440        out = (out << 1) | (v & 1u); // Append the current low bit in reversed order.
1441        v >>= 1; // Move the next bit into the least significant position.
1442    } // Finish this component or matrix pass.
1443    return detail::bit_copy<T>(out); // Reverse all 32 bits.
1444} // Finish the bitfieldReverse operation.
1445template <class A> // Accept the matching input types and dimensions.
1446typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1447bitfieldReverse(const A& a) { // Reverse all 32 bits.
1448    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1449    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1450        out[i] = glsl::bitfieldReverse(a[i]); // Store the computed component in the independent result.
1451    return out; // Return the completed result.
1452} // Finish the bitfieldReverse operation.
1453template <class T> // Accept the matching input types and dimensions.
1454typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1455bitfieldExtract(T value, int offset, int bits) { // Extract the requested bit range.
1456    if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1457        return T(0); // Extract the requested bit range.
1458    std::uint32_t mask = detail::bit_mask(bits), // Prepare the mask for the requested bit range.
1459                  out = (static_cast<std::uint32_t>(value) >> offset) & mask; // Shift the selected field down and discard other bits.
1460    if (std::is_signed<T>::value && bits < 32 && (out & (std::uint32_t(1) << (bits - 1)))) // Handle the exceptional or boundary case before continuing.
1461        out |= ~mask; // Add the encoded field to its packed bit position.
1462    return detail::bit_copy<T>(out); // Extract the requested bit range.
1463} // Finish the bitfieldExtract operation.
1464template <class A> // Accept the matching input types and dimensions.
1465typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1466bitfieldExtract(const A& a, int offset, int bits) { // Extract the requested bit range.
1467    typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1468    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1469        out[i] = glsl::bitfieldExtract(a[i], offset, bits); // Store the computed component in the independent result.
1470    return out; // Return the completed result.
1471} // Finish the bitfieldExtract operation.
1472template <class T> // Accept the matching input types and dimensions.
1473typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1474bitfieldInsert(T base, T insert, int offset, int bits) { // Replace the requested bit range.
1475    if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1476        return base; // Replace the requested bit range.
1477    std::uint32_t mask = detail::bit_mask(bits) << offset; // Prepare the mask for the requested bit range.
1478    std::uint32_t out = (static_cast<std::uint32_t>(base) & ~mask) | // Prepare the mask for the requested bit range.
1479                        ((static_cast<std::uint32_t>(insert) << offset) & mask); // Keep only insertion bits that belong to the selected field.
1480    return detail::bit_copy<T>(out); // Replace the requested bit range.
1481} // Finish the bitfieldInsert operation.
1482template <class A, class B> // Accept the matching input types and dimensions.
1483typename std::enable_if<detail::binary<A, B>::valid, typename detail::binary<A, B>::result>::type // Enable this overload only for compatible input types.
1484bitfieldInsert(const A& base, const B& insert, int offset, int bits) { // Replace the requested bit range.
1485    typedef typename detail::binary<A, B>::scalar T; // Keep the chosen component type for the calculation.
1486    typename detail::binary<A, B>::result out; // Allocate an independent result with the correct shape.
1487    for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) // Visit each component needed by this calculation.
1488        out[i] = glsl::bitfieldInsert(static_cast<T>(detail::component(base, i)), // Store the computed component in the independent result.
1489                                      static_cast<T>(detail::component(insert, i)), // Use this component as the replacement bit pattern.
1490                                      offset, // Use the requested first bit position.
1491                                      bits); // Use the requested number of replacement bits.
1492    return out; // Return the completed result.
1493} // Finish the bitfieldInsert operation.
1494inline std::uint32_t uaddCarry(std::uint32_t x, std::uint32_t y, std::uint32_t& carry) { // Add unsigned values and report the carry.
1495    std::uint64_t sum = std::uint64_t(x) + y; // Use a wider integer to retain carry or product bits.
1496    carry = std::uint32_t(sum >> 32); // Publish the extra word after the input values have been copied.
1497    return std::uint32_t(sum); // Add unsigned values and report the carry.
1498} // Finish the uaddCarry operation.
1499inline std::uint32_t usubBorrow(std::uint32_t x, std::uint32_t y, std::uint32_t& borrow) { // Subtract unsigned values and report the borrow.
1500    borrow = x < y ? 1u : 0u; // Publish the extra word after the input values have been copied.
1501    return x - y; // Subtract unsigned values and report the borrow.
1502} // Finish the usubBorrow operation.
1503inline void umulExtended(std::uint32_t x, std::uint32_t y, std::uint32_t& msb, std::uint32_t& lsb) { // Split a full unsigned product into two words.
1504    std::uint64_t product = std::uint64_t(x) * y; // Use a wider integer to retain carry or product bits.
1505    msb = std::uint32_t(product >> 32); // Publish the extra word after the input values have been copied.
1506    lsb = std::uint32_t(product); // Publish the extra word after the input values have been copied.
1507} // Finish the umulExtended operation.
1508inline void imulExtended(std::int32_t x, std::int32_t y, std::int32_t& msb, std::int32_t& lsb) { // Split a full signed product into two words.
1509    std::uint64_t product = static_cast<std::uint64_t>(std::int64_t(x) * y); // Use a wider integer to retain carry or product bits.
1510    msb = detail::bit_copy<std::int32_t>(std::uint32_t(product >> 32)); // Publish the extra word after the input values have been copied.
1511    lsb = detail::bit_copy<std::int32_t>(std::uint32_t(product)); // Publish the extra word after the input values have been copied.
1512} // Finish the imulExtended operation.
1513/** @brief Add unsigned vectors modulo 2^32 and write their carry flags. */
1514template <class A, class B, class C> // Accept the matching input types and dimensions.
1515typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1516                            detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1517                        vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1518uaddCarry(const A& x, const B& y, C&& carry) { // Add unsigned values and report the carry.
1519    static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1520                      detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1521                  "uaddCarry dimensions mismatch"); // Explain the rejected input: uaddCarry dimensions mismatch.
1522    static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1523                      std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1524                      std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1525                  "uaddCarry requires unsigned integer components"); // Explain the rejected input: uaddCarry requires unsigned integer components.
1526    static_assert(detail::writable<C>::value, // Require distinct writable output components.
1527                  "uaddCarry output requires writable unique components"); // Explain the rejected input: uaddCarry output requires writable unique components.
1528    vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1529    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1530        out[i] = glsl::uaddCarry(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1531    carry = flags; // Publish the extra word after the input values have been copied.
1532    return out; // Return the completed result.
1533} // Finish the uaddCarry operation.
1534/** @brief Subtract unsigned vectors modulo 2^32 and write their borrow flags. */
1535template <class A, class B, class C> // Accept the matching input types and dimensions.
1536typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1537                            detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1538                        vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1539usubBorrow(const A& x, const B& y, C&& borrow) { // Subtract unsigned values and report the borrow.
1540    static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1541                      detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1542                  "usubBorrow dimensions mismatch"); // Explain the rejected input: usubBorrow dimensions mismatch.
1543    static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1544                      std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1545                      std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1546                  "usubBorrow requires unsigned integer components"); // Explain the rejected input: usubBorrow requires unsigned integer components.
1547    static_assert(detail::writable<C>::value, // Require distinct writable output components.
1548                  "usubBorrow output requires writable unique components"); // Explain the rejected input: usubBorrow output requires writable unique components.
1549    vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1550    for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1551        out[i] = glsl::usubBorrow(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1552    borrow = flags; // Publish the extra word after the input values have been copied.
1553    return out; // Return the completed result.
1554} // Finish the usubBorrow operation.
1555#define SHDR_DETAIL_EXTENDED(NAME, T) /* Generate the matching scalar and vector overloads. */ \
1556    template <class A, class B, class C, class D> /* Accept the matching input types and dimensions. */ \
1557    typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && /* Enable this overload only for compatible input types. */ \
1558                            detail::traits<C>::vector && detail::traits<D>::vector>::type /* Complete the type and dimension rule for this overload. */ \
1559    NAME(const A& x, const B& y, C&& msb, D&& lsb) { /* Start the matching math overload. */ \
1560        static_assert(detail::traits<A>::size == detail::traits<B>::size && /* Require matching component counts. */ \
1561                          detail::traits<A>::size == detail::traits<C>::size && /* Complete the type and dimension rule for this overload. */ \
1562                          detail::traits<A>::size == detail::traits<D>::size, /* Complete the type and dimension rule for this overload. */ \
1563                      "extended multiplication dimensions mismatch"); /* Explain the rejected input: extended multiplication dimensions mismatch. */ \
1564        static_assert(std::is_same<typename detail::traits<A>::scalar, T>::value && /* Check this type or dimension requirement at compile time. */ \
1565                          std::is_same<typename detail::traits<B>::scalar, T>::value && /* Require the second input to use the selected integer type. */ \
1566                          std::is_same<typename detail::traits<C>::scalar, T>::value && /* Require the high output word to use the selected integer type. */ \
1567                          std::is_same<typename detail::traits<D>::scalar, T>::value, /* Require the low output word to use the selected integer type. */ \
1568                      "extended multiplication component types must match"); /* Explain the rejected input: extended multiplication component types must match. */ \
1569        static_assert(detail::writable<C>::value && detail::writable<D>::value, /* Require distinct writable output components. */ \
1570                      "extended multiplication requires writable unique output components"); /* Explain the rejected input: extended multiplication requires writable unique output components. */ \
1571        vec<T, detail::traits<A>::size> a(x), b(y), high, low; /* Keep an independent value for the result or aliased inputs. */ \
1572        for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { /* Visit each component needed by this calculation. */ \
1573            glsl::NAME(a[i], b[i], high[i], low[i]); /* Compute both words for this pair of copied components. */ \
1574        } /* Finish this component or matrix pass. */ \
1575        msb = high; /* Publish the extra word after the input values have been copied. */ \
1576        lsb = low; /* Publish the extra word after the input values have been copied. */ \
1577    } /* Finish this generated overload. */
1578SHDR_DETAIL_EXTENDED(umulExtended, std::uint32_t) // Split a full unsigned product into two words.
1579SHDR_DETAIL_EXTENDED(imulExtended, std::int32_t) // Split a full signed product into two words.
1580#undef SHDR_DETAIL_EXTENDED // Remove this local code generator macro.
1581/** @} */
1582
1583/** @name Packing
1584 * Normalized packing follows the GLSL clamp-and-round formulas.  unpacking
1585 * places the least significant byte/halfword in x. Half-float encoding rounds
1586 * to nearest even and preserves infinities and a quiet-NaN representation.
1587 * @{ */
1588inline std::uint32_t packUnorm2x16(const vec2& v) { // Pack two normalized values into 16-bit fields.
1589    std::uint32_t x = std::uint32_t(std::round(glsl::clamp(v.x, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1590    std::uint32_t y = std::uint32_t(std::round(glsl::clamp(v.y, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1591    return x | (y << 16); // Pack two normalized values into 16-bit fields.
1592} // Finish the packUnorm2x16 operation.
1593inline vec2 unpackUnorm2x16(std::uint32_t p) { // Decode two unsigned normalized 16-bit fields.
1594    return vec2(float(p & 65535u), float(p >> 16)) / 65535.0f; // Decode two unsigned normalized 16-bit fields.
1595} // Finish the unpackUnorm2x16 operation.
1596inline std::uint32_t packSnorm2x16(const vec2& v) { // Pack two signed normalized values into 16-bit fields.
1597    std::int32_t x = std::int32_t(std::round(glsl::clamp(v.x, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1598    std::int32_t y = std::int32_t(std::round(glsl::clamp(v.y, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1599    return (std::uint32_t(x) & 65535u) | (std::uint32_t(y) << 16); // Pack two signed normalized values into 16-bit fields.
1600} // Finish the packSnorm2x16 operation.
1601inline vec2 unpackSnorm2x16(std::uint32_t p) { // Decode two signed normalized 16-bit fields.
1602    std::int32_t x = std::int32_t(p & 65535u), y = std::int32_t(p >> 16); // Hold the exact integer bits used by this operation.
1603    if (x & 32768) // Handle the exceptional or boundary case before continuing.
1604        x -= 65536; // Extend the stored signed field into a signed scalar.
1605    if (y & 32768) // Handle the exceptional or boundary case before continuing.
1606        y -= 65536; // Extend the stored signed field into a signed scalar.
1607    return glsl::clamp(vec2(x, y) / 32767.0f, -1.0f, 1.0f); // Decode two signed normalized 16-bit fields.
1608} // Finish the unpackSnorm2x16 operation.
1609inline std::uint32_t packUnorm4x8(const vec4& v) { // Pack four normalized values into bytes.
1610    std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1611    for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1612        out |= std::uint32_t(std::round(glsl::clamp(v[i], 0.0f, 1.0f) * 255.0f)) << (i * 8); // Add the encoded field to its packed bit position.
1613    return out; // Return the completed result.
1614} // Finish the packUnorm4x8 operation.
1615inline vec4 unpackUnorm4x8(std::uint32_t p) { // Decode four unsigned normalized bytes.
1616    vec4 out; // Allocate four independent unpacked components.
1617    for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1618        out[i] = float((p >> (i * 8)) & 255u) / 255.0f; // Store the computed component in the independent result.
1619    return out; // Return the completed result.
1620} // Finish the unpackUnorm4x8 operation.
1621inline std::uint32_t packSnorm4x8(const vec4& v) { // Pack four signed normalized values into bytes.
1622    std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1623    for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1624        out |= (std::uint32_t(std::int32_t(std::round(glsl::clamp(v[i], -1.0f, 1.0f) * 127.0f))) & // Add the encoded field to its packed bit position.
1625                255u) // Keep only the low byte of the signed normalized encoding.
1626               << (i * 8); // Move that byte into its component position.
1627    return out; // Return the completed result.
1628} // Finish the packSnorm4x8 operation.
1629inline vec4 unpackSnorm4x8(std::uint32_t p) { // Decode four signed normalized bytes.
1630    vec4 out; // Allocate four independent unpacked components.
1631    for (std::size_t i = 0; i < 4; ++i) { // Visit each component needed by this calculation.
1632        int v = int((p >> (i * 8)) & 255u); // Extract this byte into a signed-capable scalar.
1633        if (v & 128) // Handle the exceptional or boundary case before continuing.
1634            v -= 256; // Extend an eight-bit negative value to the scalar type.
1635        out[i] = glsl::max(float(v) / 127.0f, -1.0f); // Store the computed component in the independent result.
1636    } // Finish this component or matrix pass.
1637    return out; // Return the completed result.
1638} // Finish the unpackSnorm4x8 operation.
1639namespace detail { // Keep these names inside the detail namespace.
1640inline std::uint16_t float_to_half(float value) { // Encode an IEEE half with ties rounded to even.
1641    std::uint32_t bits = glsl::floatBitsToUint(value), sign = (bits >> 16) & 32768u; // Separate the sign and payload bits for the conversion.
1642    int exponent = int((bits >> 23) & 255u) - 127 + 15; // Translate the exponent bias to the target float format.
1643    std::uint32_t mantissa = bits & 8388607u; // Keep the floating-point significand bits for encoding.
1644    if (((bits >> 23) & 255u) == 255u) // Handle the exceptional or boundary case before continuing.
1645        return std::uint16_t(sign | 31744u | (mantissa ? 512u : 0u)); // Encode an IEEE half with ties rounded to even.
1646    if (exponent >= 31) // Select the matching half-float exponent range.
1647        return std::uint16_t(sign | 31744u); // Encode an IEEE half with ties rounded to even.
1648    if (exponent <= 0) { // Select the matching half-float exponent range.
1649        if (exponent < -10) // Select the matching half-float exponent range.
1650            return std::uint16_t(sign); // Encode an IEEE half with ties rounded to even.
1651        mantissa |= 8388608u; // Restore the implicit leading significand bit.
1652        unsigned shift = unsigned(14 - exponent); // Choose the right shift for a half-float subnormal.
1653        std::uint32_t truncated = mantissa >> shift, remainder = mantissa & ((1u << shift) - 1u), // Keep the floating-point significand bits for encoding.
1654                      halfway = 1u << (shift - 1); // Identify the exact halfway rounding bit.
1655        if (remainder > halfway || (remainder == halfway && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1656            ++truncated; // Round the retained encoding to the next representable value.
1657        return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1658    } // Finish handling this condition.
1659    std::uint32_t truncated = (std::uint32_t(exponent) << 10) | (mantissa >> 13), // Keep the floating-point significand bits for encoding.
1660                  remainder = mantissa & 8191u; // Retain the discarded low bits for the rounding decision.
1661    if (remainder > 4096u || (remainder == 4096u && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1662        ++truncated; // Round the retained encoding to the next representable value.
1663    return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1664} // Finish the float_to_half operation.
1665inline float half_to_float(std::uint16_t h) { // Expand an IEEE half into a float.
1666    std::uint32_t sign = (std::uint32_t(h) & 32768u) << 16, mantissa = h & 1023u; // Separate the sign and payload bits for the conversion.
1667    int exponent = (h >> 10) & 31; // Translate the exponent bias to the target float format.
1668    if (exponent == 0) { // Select the matching half-float exponent range.
1669        if (!mantissa) // Handle the exceptional or boundary case before continuing.
1670            return glsl::uintBitsToFloat(sign); // Expand an IEEE half into a float.
1671        exponent = -14; // Set the exponent for a subnormal source value.
1672        while (!(mantissa & 1024u)) { // Continue until the remaining bits reach the required form.
1673            mantissa <<= 1; // Move the first significand bit toward the normalized position.
1674            --exponent; // Adjust the exponent while normalizing the significand.
1675        } // Finish this component or matrix pass.
1676        mantissa &= 1023u; // Remove the leading bit before storing the fraction.
1677        return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent + 127) << 23) | // Expand an IEEE half into a float.
1678                                     (mantissa << 13)); // Place the expanded significand in the float fraction field.
1679    } // Finish handling this condition.
1680    if (exponent == 31) // Select the matching half-float exponent range.
1681        return glsl::uintBitsToFloat(sign | 2139095040u | (mantissa << 13)); // Expand an IEEE half into a float.
1682    return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent - 15 + 127) << 23) | // Expand an IEEE half into a float.
1683                                 (mantissa << 13)); // Place the expanded significand in the float fraction field.
1684} // Finish the half_to_float operation.
1685} // namespace detail
1686inline std::uint32_t packHalf2x16(const vec2& v) { // Pack two IEEE half encodings into one word.
1687    return std::uint32_t(detail::float_to_half(v.x)) | // Pack two IEEE half encodings into one word.
1688           (std::uint32_t(detail::float_to_half(v.y)) << 16); // Place the second half encoding in the upper word.
1689} // Finish the packHalf2x16 operation.
1690inline vec2 unpackHalf2x16(std::uint32_t v) { // Expand the two IEEE half encodings.
1691    return vec2(detail::half_to_float(std::uint16_t(v)), // Expand the two IEEE half encodings.
1692                detail::half_to_float(std::uint16_t(v >> 16))); // Expand the upper half encoding into the second component.
1693} // Finish the unpackHalf2x16 operation.
1694/** @} */
1695} // namespace glsl
1696} // namespace shdr
1697#endif // Finish the math layer include guard.
1698
1699// ---- runtime.hpp ----
1700#ifndef SHDR_RUNTIME_HPP // Skip this section if it was already included.
1701#define SHDR_RUNTIME_HPP /* Mark this section as included. */
1702
1703/** @brief Major version of shdr. */
1704#define SHDR_VERSION_MAJOR 1 // Identify the public API's major release series.
1705/** @brief Minor version within the current major release. */
1706#define SHDR_VERSION_MINOR 0 // Identify additions within the public API's release series.
1707/** @brief Patch version within the current minor release. */
1708#define SHDR_VERSION_PATCH 0 // Identify corrections within this minor release.
1709/** @brief The library release version as a string. */
1710#define SHDR_VERSION "1.0.0" // Expose the library release as a compile-time string.
1711
1712#include <algorithm> // Use standard searches, bounds, and resource copying.
1713#include <cstddef> // Use portable pointer sizes and offsets.
1714#include <cstdint> // Use integer widths that match GLSL values.
1715#include <cctype> // Recognize characters in embedded shader declarations.
1716#include <cstring> // Copy bytes and function addresses with std::memcpy.
1717#include <functional> // Store GL resolvers and deferred cleanup callbacks.
1718#include <initializer_list> // Accept concise resource initialization from application values.
1719#include <limits> // Check arithmetic against the type limits.
1720#include <map> // Find registered shader factories and shared kernel snapshots.
1721#include <memory> // Retain resources while pipelines and queued jobs use them.
1722#include <mutex> // Protect shared work queues and deferred deletion.
1723#include <thread> // Track the context thread and start CPU workers.
1724#include <sstream> // Build readable shader and driver diagnostics.
1725#include <stdexcept> // Report invalid resources and failed execution.
1726#include <string> // Keep embedded shader text and named interfaces.
1727#include <type_traits> // Check shader storage and port types at compile time.
1728#include <vector> // Store ordered stages, ports, and resource values.
1729
1730/** @brief Portable, header-only CPU/OpenGL compute pipelines. */
1731namespace shdr { // Group these definitions in the shdr namespace.
1732/** @brief A shader, resource, context or dispatch validation failure. */
1733struct error : std::runtime_error { // Keep the error values and operations together.
1734    explicit error(const std::string& s) : std::runtime_error(s) { // Preserve the supplied validation or driver diagnostic.
1735    } // End this scope in runtime.
1736}; // End this scope in runtime.
1737
1738/** @brief Three unsigned dimensions. dispatch dimensions count work groups. */
1739struct extent { // Keep the extent values and operations together.
1740    unsigned x, y, z; // Keep the three unsigned dispatch or local dimensions.
1741    /** @brief Construct three workgroup counts, defaulting each dimension to one. */
1742    explicit extent(unsigned x_ = 1, unsigned y_ = 1, unsigned z_ = 1) : x(x_), y(y_), z(z_) { // Initialize all three positive-or-zero dimensions supplied by the caller.
1743    } // End this scope in runtime.
1744}; // End this scope in runtime.
1745/** @brief Minimum shader language selected independently of the context's actual version. */
1746enum class profile { es31, es32, gl43, gl45, gl46 }; // Name the supported shader language profiles.
1747/** @brief Automatic uses CPU execution for run() and GPU execution for run(device). */
1748enum class backend { automatic, cpu, gpu }; // Select automatic, explicit CPU or explicit GPU execution.
1749/** @brief Resource access qualifiers. readonly also prevents CPU writes at compile time. */
1750enum class access { readonly, writeonly, readwrite }; // Express how a shader may access a bound resource.
1751
1752namespace detail { // Group these definitions in the detail namespace.
1753inline bool identifier_char(char c) { // Recognize the letters, digits, and underscore allowed in an identifier.
1754    return std::isalnum(static_cast<unsigned char>(c)) || c == '_'; // Recognize the letters, digits, and underscore allowed in an identifier.
1755} // End this scope in identifier char.
1756inline std::string trim(const std::string& text) { // Remove surrounding whitespace from one resource argument.
1757    const std::size_t first = text.find_first_not_of(" \t\r\n"); // Set the first non-space character.
1758    return first == std::string::npos // Remove surrounding whitespace from one resource argument.
1759               ? std::string() // Select the value for this branch of the condition.
1760               : text.substr(first, text.find_last_not_of(" \t\r\n") - first + 1); // Copy only the non-whitespace portion of this argument.
1761} // End this scope in trim.
1762 // ESSL forbids token-pasting macros. Expand only resource declarations in the host,
1763 // preserving comments, string literals, shader statements and original line numbers.
1764inline std::string expand_declarations(const std::string& source, bool es) { // Expand host resource declarations into native GLSL interfaces.
1765    std::string out; // Keep the assembled shader text.
1766    for (std::size_t i = 0; i < source.size();) { // Walk the embedded shader text while respecting its token boundaries.
1767        const std::size_t start = i; // Set the beginning of the current token or range.
1768        if (source.compare(i, 2, "//") == 0) { // Copy the line comment verbatim.
1769            const std::size_t end = source.find('\n', i); // Set the end of the current range.
1770            i = end == std::string::npos ? source.size() : end + 1; // Advance beyond the preserved comment or declaration.
1771        } else if (source.compare(i, 2, "/*") == 0) { // Copy the block comment verbatim.
1772            const std::size_t end = source.find("*/", i + 2); // Set the end of the current range.
1773            i = end == std::string::npos ? source.size() : end + 2; // Advance beyond the preserved comment or declaration.
1774        } else if (source[i] == '\"' || source[i] == '\'') { // Copy quoted shader text as one lexical unit.
1775            const char quote = source[i++]; // Remember which quote terminates this shader literal.
1776            while (i < source.size()) { // Walk the embedded shader text while respecting its token boundaries.
1777                if (source[i] == '\\') { // Treat an escaped character as part of the quoted shader text.
1778                    i = (std::min)(i + 2, source.size()); // Advance past the escaped character within the source bounds.
1779                    continue; // Continue with the next token or work item.
1780                } // End this scope in expand declarations.
1781                if (source[i++] == quote) // Choose this branch when source[i++] equals quote.
1782                    break; // Stop this search or loop once its current item is complete.
1783            } // End this scope in expand declarations.
1784        } else if (identifier_char(source[i])) { // Recognize the letters, digits, and underscore allowed in an identifier.
1785            while (i < source.size() && identifier_char(source[i])) // Walk the embedded shader text while respecting its token boundaries.
1786                ++i; // Expand host resource declarations into native GLSL interfaces.
1787            const std::string token = source.substr(start, i - start); // Set the current shader identifier.
1788            if (token == "SHDR_BUFFER" || token == "SHDR_IMAGE2D") { // Choose this branch when token equals "SHDR BUFFER" or token equals "SHDR IMAGE2D".
1789                std::size_t open = i; // Set the opening parenthesis of a resource declaration.
1790                while (open < source.size() && // Walk the embedded shader text while respecting its token boundaries.
1791                       std::isspace(static_cast<unsigned char>(source[open]))) // Keep the opening parenthesis of a resource declaration.
1792                    ++open; // Keep the opening parenthesis of a resource declaration.
1793                if (open >= source.size() || source[open] != '(') // Check resource size or driver limits before accessing storage.
1794                    throw error("resource declaration requires parentheses: " + token); // Report resource declaration requires parentheses: .
1795                std::size_t end = open + 1, argument = end; // Set the end of the current range.
1796                unsigned depth = 1; // Set the current parenthesis nesting.
1797                std::vector<std::string> args; // Keep the parsed declaration arguments.
1798                for (; end < source.size(); ++end) { // Walk the embedded shader text while respecting its token boundaries.
1799                    if (source[end] == '(') // Choose this branch when source[end] equals '('.
1800                        ++depth; // Keep the current parenthesis nesting.
1801                    if (source[end] == ')') // Choose this branch when source[end] equals ')'.
1802                        --depth; // Keep the current parenthesis nesting.
1803                    if ((source[end] == ',' && depth == 1) || depth == 0) { // Choose this branch when (source[end] equals ',' and depth equals 1) or depth equals 0.
1804                        args.push_back(trim(source.substr(argument, end - argument))); // Retain this entry in the ordered resource or work collection.
1805                        argument = end + 1; // Set the beginning of the next resource argument.
1806                    } // End this scope in expand declarations.
1807                    if (!depth) // Finish the argument list at its matching closing parenthesis.
1808                        break; // Stop this search or loop once its current item is complete.
1809                } // End this scope in expand declarations.
1810                const bool image = token == "SHDR_IMAGE2D"; // Choose image or storage-buffer declaration syntax.
1811                if (depth || args.size() != (image ? 5u : 4u)) // Check resource size or driver limits before accessing storage.
1812                    throw error("invalid resource declaration: " + token); // Report invalid resource declaration: .
1813                const std::string mode = args.back(); // Set the declared shader resource access.
1814                if (mode != "readonly" && mode != "writeonly" && mode != "readwrite") // Choose the branch matching this interface or resource access.
1815                    throw error("invalid resource access: " + mode); // Report invalid resource access: .
1816                const std::string qualifier = mode == "readwrite" ? "" : mode + " "; // Set the access qualifier emitted into GLSL.
1817                if (image) { // Choose this branch when image.
1818                    if (es && mode == "readwrite" && args[1].compare(0, 4, "rgba") == 0) // Choose the branch matching this interface or resource access.
1819                        throw error( // Report the invalid operation.
1820                            "GLES RGBA images require readonly or writeonly declarations: " + // Append this literal GLSL source fragment.
1821                            args[3]); // Expand host resource declarations into native GLSL interfaces.
1822                    out += "layout(" + args[1] + ",binding=" + args[0] + ") " + qualifier + // Set the assembled shader text.
1823                           "uniform highp " + args[2] + " " + args[3] + ";"; // Append this literal GLSL source fragment.
1824                } else // Handle the alternative resource or completion case.
1825                    out += "layout(std430,binding=" + args[0] + ") " + qualifier + // Set the assembled shader text.
1826                           "buffer shdr_block_" + args[2] + " { " + args[1] + " " + args[2] + // Append this literal GLSL source fragment.
1827                           "[]; };"; // Append this literal GLSL source fragment.
1828                out.append(static_cast<std::size_t>( // Restore the original declaration's line count after expansion.
1829                               std::count(source.begin() + static_cast<std::ptrdiff_t>(start), // Keep the beginning of the current token or range.
1830                                          source.begin() + static_cast<std::ptrdiff_t>(end + 1), // Stop counting at the end of the replaced resource declaration.
1831                                          '\n')), // Count the newlines originally present in this declaration.
1832                           '\n'); // Append one newline for each removed original newline.
1833                i = end + 1; // Advance beyond the preserved comment or declaration.
1834                continue; // Continue with the next token or work item.
1835            } // End this scope in expand declarations.
1836        } else // Handle the alternative resource or completion case.
1837            ++i; // Expand host resource declarations into native GLSL interfaces.
1838        out.append(source, start, i - start); // Preserve this untouched token or comment in the exported GLSL.
1839    } // End this scope in expand declarations.
1840    return out; // Return the assembled shader text.
1841} // End this scope in expand declarations.
1842} // namespace detail
1843
1844/** @internal Export an embedded shader as standard GLSL, with version and declaration macros.
1845 * This function supplies the version directive. Guard the body's C++ include
1846 * with #ifdef __cplusplus. The exported source contains the selected version
1847 * and expanded declarations.
1848 */
1849inline std::string glsl_source(const std::string& source, profile p) { // Add the selected GLSL version and shared-declaration definitions.
1850    std::istringstream lines(source); // Read the embedded shader one line at a time.
1851    std::string line; // Read each embedded source line while checking version directives.
1852    while (std::getline(lines, line)) { // Inspect each source line for an unsupported version directive.
1853        std::size_t start = line.find_first_not_of(" \t\r"); // Set the beginning of the current token or range.
1854        if (start != std::string::npos && line[start] == '#') { // Choose this branch when start differs from std::string::npos and line[start] equals '#'.
1855            start = line.find_first_not_of(" \t", start + 1); // Set the beginning of the current token or range.
1856            if (start != std::string::npos && line.compare(start, 7, "version") == 0) // Choose this branch when start differs from std::string::npos and line.compare(start, 7, "version") equals 0.
1857                throw error("shared shaders must omit #version; glsl_source supplies it"); // Report shared shaders must omit #version. glsl_source supplies it.
1858        } // End this scope in glsl source.
1859    } // End this scope in glsl source.
1860    const char* version = p == profile::es31   ? "310 es" // Set the current GL version text.
1861                          : p == profile::es32 ? "320 es" // Select the version associated with this shader profile.
1862                          : p == profile::gl43 ? "430 core" // Select the version associated with this shader profile.
1863                          : p == profile::gl45 ? "450 core" // Select the version associated with this shader profile.
1864                                               : "460 core"; // Select desktop GLSL 4.60 for the remaining profile.
1865    std::string out = std::string("#version ") + version + "\n"; // Set the assembled shader text.
1866    if (p == profile::es31 || p == profile::es32) // Choose this branch when p equals profile::es31 or p equals profile::es32.
1867        out += "precision highp float;\nprecision highp int;\n"; // Set the assembled shader text.
1868    out += // Set the assembled shader text.
1869        "#define SHDR_BEGIN(name,x,y,z) layout(local_size_x=x,local_size_y=y,local_size_z=z) in;\n" // Emit a native workgroup declaration for this shader.
1870        "#define SHDR_END()\n" // Remove the host-only shader wrapper terminator.
1871        "#define SHDR_MAIN() void main()\n" // Map the shared entry-point spelling to native GLSL main.
1872        "#define SHDR_UNIFORM(t,n) uniform t n;\n" // Emit a native typed uniform declaration.
1873        "#define SHDR_SWIZZLE(v,s) (v).s\n" // Map shared swizzle syntax to native GLSL component selection.
1874        "#define SHDR_NOT(v) not(v)\n" // Map shared boolean negation to the native GLSL builtin.
1875        "#define SHDR_IN(t,n) in t n\n" // Emit a native input parameter qualifier.
1876        "#define SHDR_OUT(t,n) out t n\n" // Emit a native output parameter qualifier.
1877        "#define SHDR_INOUT(t,n) inout t n\n" // Emit a native input-output parameter qualifier.
1878        "#line 1\n"; // Restore shader line numbering before appending the original source.
1879 // Desktop GLSL accepts highp precision qualifiers from GLSL 4.10 onward.
1880    return out + detail::expand_declarations(source, p == profile::es31 || p == profile::es32); // Add the selected GLSL version and shared-declaration definitions.
1881} // End this scope in glsl source.
1882
1883namespace detail { // Group these definitions in the detail namespace.
1884 // Private GL types and entry points keep the default header compatible with standard C++11.
1885typedef unsigned int GLenum; // Name the representation used by this GL or shader interface.
1886typedef unsigned int GLuint; // Name the representation used by this GL or shader interface.
1887typedef int GLint; // Name the representation used by this GL or shader interface.
1888typedef int GLsizei; // Name the representation used by this GL or shader interface.
1889typedef unsigned int GLbitfield; // Name the representation used by this GL or shader interface.
1890typedef unsigned char GLboolean; // Name the representation used by this GL or shader interface.
1891typedef std::ptrdiff_t GLsizeiptr; // Name the representation used by this GL or shader interface.
1892typedef std::ptrdiff_t GLintptr; // Name the representation used by this GL or shader interface.
1893typedef std::uint64_t GLuint64; // Name the representation used by this GL or shader interface.
1894typedef void* GLsync; // Name the representation used by this GL or shader interface.
1895#if defined(_WIN32) // Compile this branch only when its platform or backend condition holds.
1896#define SHDR_GL_CALL __stdcall /* Match the calling convention of the GL entry points. */
1897#else // Use the alternative platform or backend definition.
1898#define SHDR_GL_CALL /* Match the calling convention of the GL entry points. */
1899#endif // Finish this conditional section.
1900enum : unsigned { // Name the profile, access, or completion values accepted by this section.
1901    VERSION = 0x1F02, // Use the GL numeric code for version.
1902    MAJOR_VERSION = 0x821B, // Use the GL numeric code for major version.
1903    MINOR_VERSION = 0x821C, // Use the GL numeric code for minor version.
1904    COMPUTE_SHADER = 0x91B9, // Use the GL numeric code for compute shader.
1905    COMPILE_STATUS = 0x8B81, // Use the GL numeric code for compile status.
1906    LINK_STATUS = 0x8B82, // Use the GL numeric code for link status.
1907    INFO_LOG_LENGTH = 0x8B84, // Use the GL numeric code for info log length.
1908    COMPUTE_WORK_GROUP_SIZE = 0x8267, // Use the GL numeric code for compute work group size.
1909    MAX_COMPUTE_WORK_GROUP_COUNT = 0x91BE, // Use the GL numeric code for max compute work group count.
1910    MAX_COMPUTE_WORK_GROUP_SIZE = 0x91BF, // Use the GL numeric code for max compute work group size.
1911    MAX_COMPUTE_WORK_GROUP_INVOCATIONS = 0x90EB, // Use the GL numeric code for max compute work group invocations.
1912    MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD, // Use the GL numeric code for max shader storage buffer bindings.
1913    MAX_IMAGE_UNITS = 0x8F38, // Use the GL numeric code for max image units.
1914    SHADER_STORAGE_BUFFER = 0x90D2, // Use the GL numeric code for shader storage buffer.
1915    DYNAMIC_DRAW = 0x88E8, // Use the GL numeric code for dynamic draw.
1916    MAP_READ_BIT = 1, // Use the GL numeric code for map read bit.
1917    ALL_BARRIER_BITS = 0xFFFFFFFFu, // Use the GL numeric code for all barrier bits.
1918    TEXTURE_2D = 0x0DE1, // Identify a two-dimensional texture target.
1919    FLOAT = 0x1406, // Use the GL numeric code for float.
1920    INT = 0x1404, // Use the GL numeric code for int.
1921    UNSIGNED_INT = 0x1405, // Use the GL numeric code for unsigned int.
1922    RED = 0x1903, // Use the GL numeric code for red.
1923    RGBA = 0x1908, // Use the GL numeric code for rgba.
1924    RED_INTEGER = 0x8D94, // Use the GL numeric code for red integer.
1925    RGBA_INTEGER = 0x8D99, // Use the GL numeric code for rgba integer.
1926    R32F = 0x822E, // Store one 32-bit floating-point component per pixel.
1927    R32I = 0x8235, // Store one signed 32-bit component per pixel.
1928    R32UI = 0x8236, // Store one unsigned 32-bit component per pixel.
1929    RGBA32F = 0x8814, // Store four 32-bit floating-point components per pixel.
1930    RGBA32I = 0x8D82, // Store four signed 32-bit components per pixel.
1931    RGBA32UI = 0x8D70, // Store four unsigned 32-bit components per pixel.
1932    READ_ONLY = 0x88B8, // Use the GL numeric code for read only.
1933    WRITE_ONLY = 0x88B9, // Use the GL numeric code for write only.
1934    READ_WRITE = 0x88BA, // Use the GL numeric code for read write.
1935    UNPACK_ALIGNMENT = 0x0CF5, // Use the GL numeric code for unpack alignment.
1936    UNPACK_ROW_LENGTH = 0x0CF2, // Use the GL numeric code for unpack row length.
1937    UNPACK_SKIP_ROWS = 0x0CF3, // Use the GL numeric code for unpack skip rows.
1938    UNPACK_SKIP_PIXELS = 0x0CF4, // Use the GL numeric code for unpack skip pixels.
1939    PIXEL_UNPACK_BUFFER = 0x88EC, // Use the GL numeric code for pixel unpack buffer.
1940    SYNC_GPU_COMMANDS_COMPLETE = 0x9117, // Use the GL numeric code for sync gpu commands complete.
1941    ALREADY_SIGNALED = 0x911A, // Use the GL numeric code for already signaled.
1942    TIMEOUT_EXPIRED = 0x911B, // Use the GL numeric code for timeout expired.
1943    CONDITION_SATISFIED = 0x911C, // Use the GL numeric code for condition satisfied.
1944    WAIT_FAILED = 0x911D, // Use the GL numeric code for wait failed.
1945    SYNC_FLUSH_COMMANDS_BIT = 1 // Use the GL numeric code for sync flush commands bit.
1946}; // End this scope in runtime.
1947
1948struct gl_api { // Keep the gl api values and operations together.
1949#define SHDR_GL_PROC(ret, n, args) /* Declare a GL function pointer with its exact argument types. */ \
1950    typedef ret(SHDR_GL_CALL* n##_type) args; /* Name the representation used by this GL or shader interface. */ \
1951    n##_type n; /* Store the resolved function pointer for this GL entry point. */
1952    SHDR_GL_PROC(const unsigned char*, GetString, (GLenum)) // Declare a function to read the driver version or renderer text.
1953    SHDR_GL_PROC(void, GetIntegerv, (GLenum, GLint*)) // Declare a function to read a scalar device limit or current binding.
1954    SHDR_GL_PROC(void, GetIntegeri_v, (GLenum, GLuint, GLint*)) // Declare a function to read the limit for a selected compute axis.
1955    SHDR_GL_PROC(GLenum, GetError, ()) // Declare a function to read the pending GL error code.
1956    SHDR_GL_PROC(GLuint, CreateShader, (GLenum)) // Declare a function to allocate a compute shader object.
1957    SHDR_GL_PROC(void, ShaderSource, (GLuint, GLsizei, const char* const*, const GLint*)) // Declare a function to supply the embedded shader text to the driver.
1958    SHDR_GL_PROC(void, CompileShader, (GLuint)) // Declare a function to ask the driver to compile the compute shader.
1959    SHDR_GL_PROC(void, GetShaderiv, (GLuint, GLenum, GLint*)) // Declare a function to read shader compilation status or log length.
1960    SHDR_GL_PROC(void, GetShaderInfoLog, (GLuint, GLsizei, GLsizei*, char*)) // Declare a function to read the driver explanation of a shader compilation failure.
1961    SHDR_GL_PROC(void, DeleteShader, (GLuint)) // Declare a function to release the temporary shader object.
1962    SHDR_GL_PROC(GLuint, CreateProgram, ()) // Declare a function to allocate the linked compute program.
1963    SHDR_GL_PROC(void, AttachShader, (GLuint, GLuint)) // Declare a function to attach the compute shader before linking.
1964    SHDR_GL_PROC(void, LinkProgram, (GLuint)) // Declare a function to link the compiled compute program.
1965    SHDR_GL_PROC(void, GetProgramiv, (GLuint, GLenum, GLint*)) // Declare a function to read linked-program status, log length, or local dimensions.
1966    SHDR_GL_PROC(void, GetProgramInfoLog, (GLuint, GLsizei, GLsizei*, char*)) // Declare a function to read the driver explanation of a program-link failure.
1967    SHDR_GL_PROC(void, DeleteProgram, (GLuint)) // Declare a function to release the GL program after its owners finish using it.
1968    SHDR_GL_PROC(void, UseProgram, (GLuint)) // Declare a function to select the compute program for the next dispatch.
1969    SHDR_GL_PROC(GLint, GetUniformLocation, (GLuint, const char*)) // Declare a function to find a named uniform in the linked program.
1970    SHDR_GL_PROC(void, Uniform1f, (GLint, float)) // Declare a function to assign a float uniform.
1971    SHDR_GL_PROC(void, Uniform1i, (GLint, GLint)) // Declare a function to assign an integer or boolean uniform.
1972    SHDR_GL_PROC(void, Uniform1ui, (GLint, GLuint)) // Declare a function to assign an unsigned integer uniform.
1973#define SHDR_GL_UNIFORM(n) /* Define the SHDR_GL_UNIFORM helper for this group of declarations. */ \
1974    SHDR_GL_PROC(void, Uniform##n##fv, (GLint, GLsizei, const float*)) /* Declare a function to send this typed uniform to GL. */ \
1975    SHDR_GL_PROC(void, Uniform##n##iv, (GLint, GLsizei, const GLint*)) /* Declare a function to send this typed uniform to GL. */ \
1976    SHDR_GL_PROC(void, Uniform##n##uiv, (GLint, GLsizei, const GLuint*)) /* Declare a function to send this typed uniform to GL. */
1977    SHDR_GL_UNIFORM(2) // Declare the GL functions for vectors with this component count.
1978    SHDR_GL_UNIFORM(3) // Declare the GL functions for vectors with this component count.
1979    SHDR_GL_UNIFORM(4) // Declare the GL functions for vectors with this component count.
1980#undef SHDR_GL_UNIFORM // Remove this temporary macro after its declarations are complete.
1981#define SHDR_GL_MATRIX(n) /* Define the SHDR_GL_MATRIX helper for this group of declarations. */ \
1982    SHDR_GL_PROC(void, UniformMatrix##n##fv, (GLint, GLsizei, GLboolean, const float*)) /* Declare a function to send this typed uniform to GL. */
1983    SHDR_GL_MATRIX(2) // Declare the GL function for this column-major matrix shape.
1984    SHDR_GL_MATRIX(3) // Declare the GL function for this column-major matrix shape.
1985    SHDR_GL_MATRIX(4) // Declare the GL function for this column-major matrix shape.
1986    SHDR_GL_MATRIX(2x3) // Declare the GL function for this column-major matrix shape.
1987    SHDR_GL_MATRIX(2x4) // Declare the GL function for this column-major matrix shape.
1988    SHDR_GL_MATRIX(3x2) // Declare the GL function for this column-major matrix shape.
1989    SHDR_GL_MATRIX(3x4) // Declare the GL function for this column-major matrix shape.
1990    SHDR_GL_MATRIX(4x2) // Declare the GL function for this column-major matrix shape.
1991    SHDR_GL_MATRIX(4x3) // Declare the GL function for this column-major matrix shape.
1992#undef SHDR_GL_MATRIX // Remove this temporary macro after its declarations are complete.
1993    SHDR_GL_PROC(void, GenBuffers, (GLsizei, GLuint*)) // Declare a function to allocate names for GL storage buffers.
1994    SHDR_GL_PROC(void, DeleteBuffers, (GLsizei, const GLuint*)) // Declare a function to release owned GL buffer names.
1995    SHDR_GL_PROC(void, BindBuffer, (GLenum, GLuint)) // Declare a function to select a buffer for allocation or transfer.
1996    SHDR_GL_PROC(void, BufferData, (GLenum, GLsizeiptr, const void*, GLenum)) // Declare a function to allocate buffer storage and supply its initial host values.
1997    SHDR_GL_PROC(void, BufferSubData, (GLenum, GLintptr, GLsizeiptr, const void*)) // Declare a function to upload the current host buffer values.
1998    SHDR_GL_PROC(void, BindBufferBase, (GLenum, GLuint, GLuint)) // Declare a function to bind storage to the shader interface index.
1999    SHDR_GL_PROC(void*, MapBufferRange, (GLenum, GLintptr, GLsizeiptr, GLbitfield)) // Declare a function to map completed GPU buffer values for a host readback.
2000    SHDR_GL_PROC(GLboolean, UnmapBuffer, (GLenum)) // Declare a function to finish reading the mapped GPU buffer.
2001    SHDR_GL_PROC(void, DispatchCompute, (GLuint, GLuint, GLuint)) // Declare a function to queue the shader workgroups.
2002    SHDR_GL_PROC(void, MemoryBarrier, (GLbitfield)) // Declare a function to make earlier resource writes visible to following GPU commands.
2003    SHDR_GL_PROC(void, Finish, ()) // Declare a function to explicitly wait until queued GPU commands complete.
2004    SHDR_GL_PROC(GLsync, FenceSync, (GLenum, GLbitfield)) // Declare a function to insert a completion fence after queued compute work.
2005    SHDR_GL_PROC(GLenum, ClientWaitSync, (GLsync, GLbitfield, GLuint64)) // Declare a function to check a GPU fence with the caller-selected timeout.
2006    SHDR_GL_PROC(void, DeleteSync, (GLsync)) // Declare the GL completion-fence deletion entry point.
2007    SHDR_GL_PROC(void, Flush, ()) // Declare the GL command-flush entry point.
2008    SHDR_GL_PROC(void, GenTextures, (GLsizei, GLuint*)) // Declare a function to allocate names for owned GL images.
2009    SHDR_GL_PROC(void, DeleteTextures, (GLsizei, const GLuint*)) // Declare a function to release owned GL image names.
2010    SHDR_GL_PROC(void, BindTexture, (GLenum, GLuint)) // Declare a function to select the image for allocation or upload.
2011    SHDR_GL_PROC(void, TexStorage2D, (GLenum, GLsizei, GLenum, GLsizei, GLsizei)) // Declare a function to allocate immutable two-dimensional image storage.
2012    SHDR_GL_PROC(void, // Declare the next dynamically resolved GL function signature.
2013                 TexSubImage2D, // Name the function that uploads pixels into an existing texture.
2014                 (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void*)) // Match the argument order required by this GL entry point.
2015    SHDR_GL_PROC(void, BindImageTexture, (GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum)) // Declare a function to bind a typed image to its shader interface index.
2016    SHDR_GL_PROC(void, PixelStorei, (GLenum, GLint)) // Declare a function to set or restore the application pixel-transfer layout.
2017#undef SHDR_GL_PROC // Remove this temporary macro after its declarations are complete.
2018    explicit gl_api(const std::function<void*(const char*)>& resolver) { // Resolve the GL calls used by resource transfers and dispatches.
2019#define SHDR_LOAD(n) /* Resolve one GL entry point and reject missing functions. */ \
2020    { /* Begin the protected scope for this operation. */ \
2021        void* p = resolver("gl" #n); /* Resolve the address of this named GL entry point. */ \
2022        if (!p) /* Reject a missing dynamically resolved GL function. */ \
2023            throw error("missing GL entry point: gl" #n); /* Report missing gl entry point: gl. */ \
2024        static_assert(sizeof(p) == sizeof(n), "function pointer size unsupported"); /* Require a representation that matches the shader interface. */ \
2025        std::memcpy(&n, &p, sizeof(n)); /* Copy the representation with the alias-safe byte-copy operation. */ \
2026    } /* End this scope in gl api. */
2027        SHDR_LOAD(GetString) // Load the function to read the driver version or renderer text.
2028        SHDR_LOAD(GetIntegerv) // Load the function to read a scalar device limit or current binding.
2029        SHDR_LOAD(GetIntegeri_v) // Load the function to read the limit for a selected compute axis.
2030        SHDR_LOAD(GetError) // Load the function to read the pending GL error code.
2031        SHDR_LOAD(CreateShader) // Load the function to allocate a compute shader object.
2032        SHDR_LOAD(ShaderSource) // Load the function to supply the embedded shader text to the driver.
2033        SHDR_LOAD(CompileShader) // Load the function to ask the driver to compile the compute shader.
2034        SHDR_LOAD(GetShaderiv) // Load the function to read shader compilation status or log length.
2035        SHDR_LOAD(GetShaderInfoLog) // Load the function to read the driver explanation of a shader compilation failure.
2036        SHDR_LOAD(DeleteShader) // Load the function to release the temporary shader object.
2037        SHDR_LOAD(CreateProgram) // Load the function to allocate the linked compute program.
2038        SHDR_LOAD(AttachShader) // Load the function to attach the compute shader before linking.
2039        SHDR_LOAD(LinkProgram) // Load the function to link the compiled compute program.
2040        SHDR_LOAD(GetProgramiv) // Load the function to read linked-program status, log length, or local dimensions.
2041        SHDR_LOAD(GetProgramInfoLog) // Load the function to read the driver explanation of a program-link failure.
2042        SHDR_LOAD(DeleteProgram) // Load the function to release the GL program after its owners finish using it.
2043        SHDR_LOAD(UseProgram) // Load the function to select the compute program for the next dispatch.
2044        SHDR_LOAD(GetUniformLocation) // Load the function to find a named uniform in the linked program.
2045        SHDR_LOAD(Uniform1f) // Load the function to assign a float uniform.
2046        SHDR_LOAD(Uniform1i) // Load the function to assign an integer or boolean uniform.
2047        SHDR_LOAD(Uniform1ui) // Load the function to assign an unsigned integer uniform.
2048#define SHDR_LOAD_UNIFORM(n) /* Load the float, signed and unsigned uniform functions for this vector width. */ \
2049    SHDR_LOAD(Uniform##n##fv) /* Load the function to send this typed uniform to GL. */ \
2050    SHDR_LOAD(Uniform##n##iv) /* Load the function to send this typed uniform to GL. */ \
2051    SHDR_LOAD(Uniform##n##uiv) /* Load the function to send this typed uniform to GL. */
2052        SHDR_LOAD_UNIFORM(2) // Load the float, signed and unsigned uniform functions for this vector width.
2053        SHDR_LOAD_UNIFORM(3) // Load the float, signed and unsigned uniform functions for this vector width.
2054        SHDR_LOAD_UNIFORM(4) // Load the float, signed and unsigned uniform functions for this vector width.
2055#undef SHDR_LOAD_UNIFORM // Remove this temporary macro after its declarations are complete.
2056        SHDR_LOAD(UniformMatrix2fv) // Load the function to send this typed uniform to GL.
2057        SHDR_LOAD(UniformMatrix3fv) // Load the function to send this typed uniform to GL.
2058        SHDR_LOAD(UniformMatrix4fv) // Load the function to send this typed uniform to GL.
2059        SHDR_LOAD(UniformMatrix2x3fv) // Load the function to send this typed uniform to GL.
2060        SHDR_LOAD(UniformMatrix2x4fv) // Load the function to send this typed uniform to GL.
2061        SHDR_LOAD(UniformMatrix3x2fv) // Load the function to send this typed uniform to GL.
2062        SHDR_LOAD(UniformMatrix3x4fv) // Load the function to send this typed uniform to GL.
2063        SHDR_LOAD(UniformMatrix4x2fv) // Load the function to send this typed uniform to GL.
2064        SHDR_LOAD(UniformMatrix4x3fv) // Load the function to send this typed uniform to GL.
2065        SHDR_LOAD(GenBuffers) // Load the function to allocate names for GL storage buffers.
2066        SHDR_LOAD(DeleteBuffers) // Load the function to release owned GL buffer names.
2067        SHDR_LOAD(BindBuffer) // Load the function to select a buffer for allocation or transfer.
2068        SHDR_LOAD(BufferData) // Load the function to allocate buffer storage and supply its initial host values.
2069        SHDR_LOAD(BufferSubData) // Load the function to upload the current host buffer values.
2070        SHDR_LOAD(BindBufferBase) // Load the function to bind storage to the shader interface index.
2071        SHDR_LOAD(MapBufferRange) // Load the function to map completed GPU buffer values for a host readback.
2072        SHDR_LOAD(UnmapBuffer) // Load the function to finish reading the mapped GPU buffer.
2073        SHDR_LOAD(DispatchCompute) // Load the function to queue the shader workgroups.
2074        SHDR_LOAD(MemoryBarrier) // Load the function to make earlier resource writes visible to following GPU commands.
2075        SHDR_LOAD(Finish) // Load the function to explicitly wait until queued GPU commands complete.
2076        SHDR_LOAD(GenTextures) // Load the function to allocate names for owned GL images.
2077        SHDR_LOAD(DeleteTextures) // Load the function to release owned GL image names.
2078        SHDR_LOAD(FenceSync) // Load the function to insert a completion fence after queued compute work.
2079        SHDR_LOAD(ClientWaitSync) // Load the function to check a GPU fence with the caller-selected timeout.
2080        SHDR_LOAD(DeleteSync) // Resolve the GL completion-fence deletion entry point.
2081        SHDR_LOAD(Flush) // Resolve the GL command-flush entry point.
2082        SHDR_LOAD(BindTexture) // Load the function to select the image for allocation or upload.
2083        SHDR_LOAD(TexStorage2D) // Load the function to allocate immutable two-dimensional image storage.
2084        SHDR_LOAD(TexSubImage2D) // Load the function to upload the current host pixel values.
2085        SHDR_LOAD(BindImageTexture) // Load the function to bind a typed image to its shader interface index.
2086        SHDR_LOAD(PixelStorei) // Load the function to set or restore the application pixel-transfer layout.
2087#undef SHDR_LOAD // Remove this temporary macro after its declarations are complete.
2088    } // End this scope in gl api.
2089    void check(const std::string& operation) const { // Check for a driver error from the preceding GL operation.
2090        const unsigned code = GetError(); // Read the pending GL error code.
2091        if (code) { // Choose this branch when code.
2092            std::ostringstream s; // Build a readable diagnostic containing the operation and GL error.
2093            s << operation << ": GL error 0x" << std::hex << code; // Combine the operation name and hexadecimal driver error.
2094            throw error(s.str()); // Report the invalid operation.
2095        } // End this scope in runtime.
2096    } // End this scope in runtime.
2097}; // End this scope in runtime.
2098#undef SHDR_GL_CALL // Remove this temporary macro after its declarations are complete.
2099
2100struct device_state { // Retain GL functions, context ownership, limits, and pending cleanup.
2101    gl_api gl; // Keep the retained GL function table.
2102    profile language; // Keep the selected shader profile.
2103    unsigned max_groups[3], max_local[3], max_invocations, max_buffers, max_images; // Keep work group dimensions, invocation and resource binding limits.
2104    std::shared_ptr<void> context_keepalive; // Keep the retained headless context.
2105    std::function<void()> activate_context; // Keep the callback that makes this device context current.
2106    std::thread::id context_thread; // Keep the thread allowed to issue GL commands.
2107    std::mutex retirement_mutex; // Keep the lock for deferred resource cleanup.
2108    std::vector<std::function<void(gl_api&)>> retirements; // Keep GL deletions requested by another thread.
2109    struct deferred { // Keep the deferred values and operations together.
2110        std::function<bool(gl_api&)> poll; // Keep the zero-time completion callback.
2111        std::function<void(gl_api&)> cancel; // Keep the fence-deletion callback used at shutdown.
2112    }; // End this scope in runtime.
2113    std::vector<deferred> pending_work; // Keep discarded submissions awaiting completion.
2114    bool retirements_closed; // Keep whether device teardown has stopped retaining submissions.
2115    device_state(const std::function<void*(const char*)>& resolver, profile p) // Load GL entry points and validate the selected compute profile.
2116        : gl(resolver), language(p), context_thread(std::this_thread::get_id()), // Resolve GL functions and record this context's profile and owning thread.
2117          retirements_closed(false) { // Allow pending completion leases until the public device is destroyed.
2118        const unsigned char* version = gl.GetString(VERSION); // Read the current context version before checking the requested profile.
2119        if (!version) // Require a version string from the current context.
2120            throw error("device requires a current GL context"); // Report device requires a current gl context.
2121        const bool es = std::string(reinterpret_cast<const char*>(version)).find("OpenGL ES") != // Set whether the current context uses OpenGL ES.
2122                        std::string::npos; // Detect the GLES marker anywhere in the driver version string.
2123        const bool requested_es = p == profile::es31 || p == profile::es32; // Set whether the requested profile uses GLES.
2124        if (es != requested_es) // Choose this branch when es differs from requested es.
2125            throw error("shader profile does not match current GL/ES context"); // Report a mismatch between the selected profile and the current context.
2126        GLint major = 0, minor = 0; // Prepare both parts of the current GL version query.
2127        gl.GetIntegerv(MAJOR_VERSION, &major); // Read a scalar device limit or current binding.
2128        gl.GetIntegerv(MINOR_VERSION, &minor); // Read a scalar device limit or current binding.
2129        const int required_major = es ? 3 : 4; // Set the minimum GL major version for this profile.
2130        const int required_minor = p == profile::es31   ? 1 // Set the minimum GL minor version for this profile.
2131                                   : p == profile::es32 ? 2 // Select the version associated with this shader profile.
2132                                   : p == profile::gl43 ? 3 // Select the version associated with this shader profile.
2133                                   : p == profile::gl45 ? 5 // Select the version associated with this shader profile.
2134                                                        : 6; // Select minor version six for the desktop GL 4.6 profile.
2135        if (major < required_major || (major == required_major && minor < required_minor)) // Choose this branch when major < required major or (major equals required major and minor < required minor).
2136            throw error("current context is older than requested compute profile"); // Report current context is older than requested compute profile.
2137        for (unsigned i = 0; i < 3; ++i) { // Validate or query each of the three compute dimensions.
2138            GLint n = 0; // Set the queried GL limit or element count.
2139            gl.GetIntegeri_v(MAX_COMPUTE_WORK_GROUP_COUNT, i, &n); // Read the limit for a selected compute axis.
2140            max_groups[i] = static_cast<unsigned>(n); // Set the device workgroup-count limits.
2141            gl.GetIntegeri_v(MAX_COMPUTE_WORK_GROUP_SIZE, i, &n); // Read the limit for a selected compute axis.
2142            max_local[i] = static_cast<unsigned>(n); // Set the device local-size limits.
2143        } // End this scope in device state.
2144        GLint n = 0; // Set the queried GL limit or element count.
2145        gl.GetIntegerv(MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &n); // Read a scalar device limit or current binding.
2146        max_invocations = static_cast<unsigned>(n); // Set the maximum invocations in one workgroup.
2147        gl.GetIntegerv(MAX_SHADER_STORAGE_BUFFER_BINDINGS, &n); // Read a scalar device limit or current binding.
2148        max_buffers = static_cast<unsigned>(n); // Set the storage-buffer binding limit.
2149        gl.GetIntegerv(MAX_IMAGE_UNITS, &n); // Read a scalar device limit or current binding.
2150        max_images = static_cast<unsigned>(n); // Set the image binding limit.
2151        gl.check("query compute capabilities"); // Check for a driver error from the preceding GL operation.
2152    } // End this scope in device state.
2153    void require_thread() { // Require the device context thread and activate its headless context.
2154        if (std::this_thread::get_id() != context_thread) // Check that the operation uses the context or lifecycle thread.
2155            throw error("GL operations require the device's context thread"); // Report gl operations require the device's context thread.
2156        if (activate_context) // Choose this branch when activate context.
2157            activate_context(); // Keep the callback that makes this device context current.
2158    } // End this scope in require thread.
2159    void collect() { // Run queued deletions and zero-time completion checks.
2160        require_thread(); // Require the device context thread and activate its headless context.
2161        std::vector<std::function<void(gl_api&)>> pending; // Keep the queued work or cleanup callbacks awaiting processing.
2162        std::vector<deferred> polls, unfinished; // Keep completion polls that must be checked again.
2163        { // Begin the protected scope for this operation.
2164            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2165            pending.swap(retirements); // Take the shared entries into a local collection for unlocked processing.
2166            polls.swap(pending_work); // Take the shared entries into a local collection for unlocked processing.
2167        } // End this scope in collect.
2168        for (std::size_t i = 0; i < pending.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2169            pending[i](gl); // Keep the retained GL function table.
2170        for (std::size_t i = 0; i < polls.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2171            if (!polls[i].poll(gl)) // Retain a completion callback while its work is pending.
2172                unfinished.push_back(std::move(polls[i])); // Retain this entry in the ordered resource or work collection.
2173        if (!unfinished.empty()) { // Keep the remaining callbacks for the next collection pass.
2174            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2175            pending_work.insert(pending_work.end(), // Retain this entry in the ordered resource or work collection.
2176                                std::make_move_iterator(unfinished.begin()), // Supply the next value for the current call or declaration.
2177                                std::make_move_iterator(unfinished.end())); // Keep the end of the current range.
2178        } // End this scope in collect.
2179    } // End this scope in collect.
2180    void defer_poll(const std::function<bool(gl_api&)>& poll, // Retain a completion check until its fence signals.
2181                    const std::function<void(gl_api&)>& cancel = std::function<void(gl_api&)>()) { // Set the fence-deletion callback used at shutdown.
2182        { // Begin the protected scope for this operation.
2183            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2184            if (!retirements_closed) { // Check whether teardown still allows retained completion callbacks.
2185                pending_work.push_back(deferred{poll, cancel}); // Retain this entry in the ordered resource or work collection.
2186                return; // Finish this operation.
2187            } // End this scope in defer poll.
2188        } // End this scope in defer poll.
2189 // Handles may outlive the public device wrapper. After wrapper teardown,
2190 // schedule their fence deletion directly on the context thread.
2191        if (cancel) // Choose this branch when cancel.
2192            retire(cancel); // Delete on the context thread or defer deletion to that thread.
2193    } // End this scope in defer poll.
2194    void close_retirements() { // Stop retaining new submission bundles during device teardown.
2195        { // Begin the protected scope for this operation.
2196            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2197            retirements_closed = true; // Set whether device teardown has stopped retaining submissions.
2198        } // End this scope in close retirements.
2199        cancel_pending(); // Schedule deferred-fence deletion on the context thread.
2200    } // End this scope in close retirements.
2201    void cancel_pending() { // Schedule deferred-fence deletion on the context thread.
2202        require_thread(); // Require the device context thread and activate its headless context.
2203        std::vector<deferred> pending; // Keep the queued work or cleanup callbacks awaiting processing.
2204        { // Begin the protected scope for this operation.
2205            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2206            pending.swap(pending_work); // Take the shared entries into a local collection for unlocked processing.
2207        } // End this scope in cancel pending.
2208        for (std::size_t i = 0; i < pending.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2209            if (pending[i].cancel) // Check the queue state before accepting or executing work.
2210                pending[i].cancel(gl); // Keep the retained GL function table.
2211        pending.clear(); // Release the retained entries after their work or cleanup is complete.
2212        collect(); // Run queued deletions and zero-time completion checks.
2213    } // End this scope in cancel pending.
2214    void retire(const std::function<void(gl_api&)>& deletion) { // Delete on the context thread or defer deletion to that thread.
2215        if (std::this_thread::get_id() == context_thread) { // Check that the operation uses the context or lifecycle thread.
2216            require_thread(); // Require the device context thread and activate its headless context.
2217            deletion(gl); // Keep the retained GL function table.
2218        } else { // Handle the alternative resource or completion case.
2219            std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2220            retirements.push_back(deletion); // Retain this entry in the ordered resource or work collection.
2221        } // End this scope in retire.
2222    } // End this scope in retire.
2223    ~device_state() noexcept { // Close pending retirement leases on the context thread.
2224        if (std::this_thread::get_id() == context_thread) { // Check that the operation uses the context or lifecycle thread.
2225            try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2226                close_retirements(); // Stop retaining new submission bundles during device teardown.
2227            } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2228            } // End this scope in device state.
2229        } // End this scope in device state.
2230    } // End this scope in device state.
2231    GLuint compile(const std::string& source, const std::string& name) { // Compile and link the embedded compute source with driver diagnostics.
2232        if (source.size() > static_cast<std::size_t>((std::numeric_limits<GLint>::max)())) // Check resource size or driver limits before accessing storage.
2233            throw error("shader source too large"); // Report shader source too large.
2234        GLuint shader = gl.CreateShader(COMPUTE_SHADER), program = 0; // Allocate a compute shader object.
2235        if (!shader) // Check that the driver allocated a shader object.
2236            throw error("cannot create compute shader"); // Report compute-shader allocation failure.
2237        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2238            const char* text = source.c_str(); // Give GL a pointer to the retained shader characters.
2239            GLint len = static_cast<GLint>(source.size()); // Pass the validated shader character count to GL.
2240            gl.ShaderSource(shader, 1, &text, &len); // Supply the embedded shader text to the driver.
2241            gl.CompileShader(shader); // Ask the driver to compile the compute shader.
2242            GLint success = 0; // Prepare the compile or link status returned by GL.
2243            gl.GetShaderiv(shader, COMPILE_STATUS, &success); // Read shader compilation status or log length.
2244            if (!success) { // Read the driver diagnostic for this failed operation.
2245                GLint size = 0; // Prepare the driver diagnostic log length.
2246                gl.GetShaderiv(shader, INFO_LOG_LENGTH, &size); // Read shader compilation status or log length.
2247                std::vector<char> log(static_cast<std::size_t>((std::max)(size, 1)), 0); // Allocate enough characters for the driver diagnostic and terminator.
2248                gl.GetShaderInfoLog(shader, size, 0, log.data()); // Read the driver explanation of a shader compilation failure.
2249                throw error(name + ": shader compilation failed\n" + log.data()); // Report : shader compilation failed\n.
2250            } // End this scope in compile.
2251            program = gl.CreateProgram(); // Allocate the linked compute program.
2252            if (!program) // Check that the driver allocated a program object.
2253                throw error("cannot create compute program"); // Report compute-program allocation failure.
2254            gl.AttachShader(program, shader); // Attach the compute shader before linking.
2255            gl.LinkProgram(program); // Link the compiled compute program.
2256            gl.GetProgramiv(program, LINK_STATUS, &success); // Read linked-program status, log length, or local dimensions.
2257            if (!success) { // Read the driver diagnostic for this failed operation.
2258                GLint size = 0; // Prepare the driver diagnostic log length.
2259                gl.GetProgramiv(program, INFO_LOG_LENGTH, &size); // Read linked-program status, log length, or local dimensions.
2260                std::vector<char> log(static_cast<std::size_t>((std::max)(size, 1)), 0); // Allocate enough characters for the driver diagnostic and terminator.
2261                gl.GetProgramInfoLog(program, size, 0, log.data()); // Read the driver explanation of a program-link failure.
2262                throw error(name + ": program link failed\n" + log.data()); // Report : program link failed\n.
2263            } // End this scope in compile.
2264            gl.DeleteShader(shader); // Release the temporary shader object.
2265            shader = 0; // Set the shader used by this dispatch.
2266            gl.check("link " + name); // Keep the resource or entry-point name.
2267            return program; // Compile and link the embedded compute source with driver diagnostics.
2268        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2269            if (shader) // Choose this branch when shader.
2270                gl.DeleteShader(shader); // Release the temporary shader object.
2271            if (program) // Choose this branch when program.
2272                gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2273            throw; // Rethrow the original failure after arranging the necessary cleanup.
2274        } // End this scope in compile.
2275    } // End this scope in compile.
2276}; // End this scope in runtime.
2277struct program_state { // Keep the program state values and operations together.
2278    std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
2279    GLuint id; // Keep the compiled GL program name.
2280    program_state(const std::shared_ptr<device_state>& d, GLuint id_) : owner(d), id(id_) { // Expose the retained compiled program for asynchronous ownership.
2281    } // End this scope in program state.
2282    ~program_state() { // Release this object's owned resources at teardown.
2283        if (id) { // Choose this branch when id.
2284            const GLuint name = id; // Set the resource or entry-point name.
2285            owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2286                gl.DeleteProgram(name); // Release the GL program after its owners finish using it.
2287            }); // End this scope in program state.
2288        } // End this scope in program state.
2289    } // End this scope in program state.
2290}; // End this scope in runtime.
2291
2292inline std::size_t checked_product(std::size_t a, std::size_t b) { // Reject resource-size multiplication that would overflow.
2293    if (b && a > (std::numeric_limits<std::size_t>::max)() / b) // Check resource size or driver limits before accessing storage.
2294        throw error("resource size overflow"); // Report resource size overflow.
2295    return a * b; // Reject resource-size multiplication that would overflow.
2296} // End this scope in checked product.
2297inline GLsizeiptr gl_size(std::size_t size) { // Require a byte count representable by the GL buffer API.
2298    if (size > static_cast<std::size_t>((std::numeric_limits<GLsizeiptr>::max)())) // Check resource size or driver limits before accessing storage.
2299        throw error("resource exceeds GLsizeiptr"); // Report resource exceeds glsizeiptr.
2300    return static_cast<GLsizeiptr>(size); // Require a byte count representable by the GL buffer API.
2301} // End this scope in gl size.
2302enum class authority { host, gpu, both }; // Name the profile, access, or completion values accepted by this section.
2303enum class resource_kind { buffer, image }; // Name the profile, access, or completion values accepted by this section.
2304struct resource_state { // Track shared storage and which backend has the newest values.
2305    resource_kind kind; // Keep the buffer, image, or uniform interface kind.
2306    authority latest; // Keep which copy contains the latest resource values.
2307    std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
2308    GLuint handle; // Keep the GL buffer or texture name.
2309    bool borrowed; // Keep whether the application owns the supplied GL object.
2310    unsigned width, height, components, format, scalar; // Keep the GL scalar representation.
2311    resource_state(resource_kind k) // Initialize ownership and synchronization for one resource.
2312        : kind(k), latest(authority::host), handle(0), borrowed(false), width(0), height(0), // Start with authoritative host data and allocate GL storage on demand.
2313          components(0), format(0), scalar(0) { // Initialize image layout metadata to zero.
2314    } // End this scope in resource state.
2315    virtual ~resource_state() { // Release this object's owned resources at teardown.
2316        if (handle && !borrowed) { // Delete the resource when its GL handle is owned by this object.
2317            const GLuint name = handle; // Set the resource or entry-point name.
2318            if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2319                owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2320                    gl.DeleteBuffers(1, &name); // Release owned GL buffer names.
2321                }); // End this scope in resource state.
2322            else // Handle the other resource, platform, or completion case.
2323                owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2324                    gl.DeleteTextures(1, &name); // Release owned GL image names.
2325                }); // End this scope in resource state.
2326        } // End this scope in resource state.
2327    } // End this scope in resource state.
2328    virtual void* host_pointer() = 0; // Require each resource type to expose its host storage.
2329    virtual std::size_t bytes() const = 0; // Require each resource type to report its byte count.
2330    void ensure_host(); // Download newer GPU values only when host access needs them.
2331    void ensure_gpu(const std::shared_ptr<device_state>& d) { // Allocate or upload GPU storage when its host copy is newer.
2332        d->collect(); // Run queued deletions and zero-time completion checks.
2333        if (owner && owner != d) // Check that this storage belongs to the requested device.
2334            throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2335        owner = d; // Set the device that owns the GL resource.
2336        const gl_api& gl = d->gl; // Set the retained GL function table.
2337        if (!handle) { // Allocate GPU storage on the first device access.
2338            if (kind == resource_kind::buffer) { // Choose the branch matching this interface or resource access.
2339                gl.GenBuffers(1, &handle); // Allocate names for GL storage buffers.
2340                gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2341                gl.BufferData(SHADER_STORAGE_BUFFER, // Allocate buffer storage and supply its initial host values.
2342                              gl_size(bytes()), // Require a byte count representable by the GL buffer API.
2343                              bytes() ? host_pointer() : 0, // Supply the next value for the current call or declaration.
2344                              DYNAMIC_DRAW); // Require a byte count representable by the GL buffer API.
2345            } else { // Handle the alternative resource or completion case.
2346                gl.GenTextures(1, &handle); // Allocate names for owned GL images.
2347                gl.BindTexture(TEXTURE_2D, handle); // Select the image for allocation or upload.
2348                gl.TexStorage2D(TEXTURE_2D, // Allocate immutable two-dimensional image storage.
2349                                1, // Supply the next value for the current call or declaration.
2350                                format, // Visit the values or interfaces needed by ensure gpu.
2351                                static_cast<GLsizei>(width), // Keep the image width in pixels.
2352                                static_cast<GLsizei>(height)); // Keep the image height in pixels.
2353            } // End this scope in ensure gpu.
2354            gl.check("allocate compute resource"); // Check for a driver error from the preceding GL operation.
2355            if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2356                latest = authority::both; // Record which backend now owns the newest resource values.
2357        } // End this scope in ensure gpu.
2358        if (latest == authority::host) { // Check which resource copy must be synchronized.
2359            if (kind == resource_kind::buffer) { // Choose the branch matching this interface or resource access.
2360                gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2361                if (bytes()) // Check resource size or driver limits before accessing storage.
2362                    gl.BufferSubData(SHADER_STORAGE_BUFFER, 0, gl_size(bytes()), host_pointer()); // Upload the current host buffer values.
2363            } else { // Handle the alternative resource or completion case.
2364 // Make upload independent of caller pixel unpack state and restore that state.
2365                GLint alignment = 0, row = 0, skip_rows = 0, skip_pixels = 0, pbo = 0; // Save the complete pixel-unpack layout and bound transfer buffer.
2366                gl.GetIntegerv(UNPACK_ALIGNMENT, &alignment); // Read a scalar device limit or current binding.
2367                gl.GetIntegerv(UNPACK_ROW_LENGTH, &row); // Read a scalar device limit or current binding.
2368                gl.GetIntegerv(UNPACK_SKIP_ROWS, &skip_rows); // Read a scalar device limit or current binding.
2369                gl.GetIntegerv(UNPACK_SKIP_PIXELS, &skip_pixels); // Read a scalar device limit or current binding.
2370                gl.GetIntegerv(0x88EF, &pbo); // GL_PIXEL_UNPACK_BUFFER_BINDING
2371                gl.BindBuffer(PIXEL_UNPACK_BUFFER, 0); // Select a buffer for allocation or transfer.
2372                gl.PixelStorei(UNPACK_ALIGNMENT, 1); // Set or restore the application pixel-transfer layout.
2373                gl.PixelStorei(UNPACK_ROW_LENGTH, 0); // Set or restore the application pixel-transfer layout.
2374                gl.PixelStorei(UNPACK_SKIP_ROWS, 0); // Set or restore the application pixel-transfer layout.
2375                gl.PixelStorei(UNPACK_SKIP_PIXELS, 0); // Set or restore the application pixel-transfer layout.
2376                gl.BindTexture(TEXTURE_2D, handle); // Select the image for allocation or upload.
2377                const GLenum channels = scalar == FLOAT // Choose the float or integer pixel-transfer channel representation.
2378                                            ? (components == 1 ? RED : RGBA) // Set the number of scalar values per pixel.
2379                                            : (components == 1 ? RED_INTEGER : RGBA_INTEGER); // Choose the upload pixel format matching integer channels.
2380                gl.TexSubImage2D(TEXTURE_2D, // Upload the current host pixel values.
2381                                 0, // Supply the next value for the current call or declaration.
2382                                 0, // Supply the next value for the current call or declaration.
2383                                 0, // Supply the next value for the current call or declaration.
2384                                 static_cast<GLsizei>(width), // Keep the image width in pixels.
2385                                 static_cast<GLsizei>(height), // Keep the image height in pixels.
2386                                 channels, // Supply the next value for the current call or declaration.
2387                                 scalar, // Keep the GL scalar representation.
2388                                 host_pointer()); // Expose this resource's borrowed or owned host storage.
2389                gl.PixelStorei(UNPACK_ALIGNMENT, alignment); // Set or restore the application pixel-transfer layout.
2390                gl.PixelStorei(UNPACK_ROW_LENGTH, row); // Set or restore the application pixel-transfer layout.
2391                gl.PixelStorei(UNPACK_SKIP_ROWS, skip_rows); // Set or restore the application pixel-transfer layout.
2392                gl.PixelStorei(UNPACK_SKIP_PIXELS, skip_pixels); // Set or restore the application pixel-transfer layout.
2393                gl.BindBuffer(PIXEL_UNPACK_BUFFER, static_cast<GLuint>(pbo)); // Select a buffer for allocation or transfer.
2394            } // End this scope in ensure gpu.
2395            gl.check("upload compute resource"); // Check for a driver error from the preceding GL operation.
2396            latest = authority::both; // Record which backend now owns the newest resource values.
2397        } // End this scope in ensure gpu.
2398    } // End this scope in ensure gpu.
2399}; // End this scope in runtime.
2400
2401 // Image readback uses a compute copy on both desktop GL and GLES.
2402inline void resource_state::ensure_host() { // Download newer GPU values only when host access needs them.
2403    if (latest != authority::gpu) // Check which resource copy must be synchronized.
2404        return; // Finish this operation.
2405    owner->collect(); // Run queued deletions and zero-time completion checks.
2406    const gl_api& gl = owner->gl; // Set the retained GL function table.
2407    if (!bytes()) { // Check resource size or driver limits before accessing storage.
2408        latest = authority::both; // Record which backend now owns the newest resource values.
2409        return; // Finish this operation.
2410    } // End this scope in ensure host.
2411    GLuint staging = 0, program = 0; // Track the temporary readback buffer and copy program for cleanup.
2412    try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2413        gl.MemoryBarrier(ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
2414        if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2415            gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2416        else { // Handle the other resource, platform, or completion case.
2417            const char* scalar_name = scalar == FLOAT ? "float" : scalar == INT ? "int" : "uint"; // Choose the GLSL scalar spelling matching these image pixels.
2418            const char* vector_name = scalar == FLOAT ? "vec4" : scalar == INT ? "ivec4" : "uvec4"; // Choose the four-component GLSL value used by imageLoad.
2419            const char* image_name = scalar == FLOAT ? "image2D" // Choose the matching float, signed or unsigned storage-image type.
2420                                     : scalar == INT ? "iimage2D" // Choose the shader image type matching the resource's scalar representation.
2421                                                     : "uimage2D"; // Choose the shader image type matching the resource's scalar representation.
2422            const char* format_name = components == 1 ? (scalar == FLOAT ? "r32f" // Choose the declared storage-image format for the copy shader.
2423                                                         : scalar == INT ? "r32i" // Choose the shader format matching scalar type and channel count.
2424                                                                         : "r32ui") // Choose the shader format matching scalar type and channel count.
2425                                                      : (scalar == FLOAT ? "rgba32f" // Choose the shader format matching scalar type and channel count.
2426                                                         : scalar == INT ? "rgba32i" // Choose the shader format matching scalar type and channel count.
2427                                                                         : "rgba32ui"); // Choose the shader format matching scalar type and channel count.
2428            std::ostringstream body; // Download newer GPU values only when host access needs them.
2429            body << "SHDR_BEGIN(shdr_readback,8,8,1)\nSHDR_IMAGE2D(0," << format_name << ',' // Download newer GPU values only when host access needs them.
2430                 << image_name << ",src,readonly)\n" // Download newer GPU values only when host access needs them.
2431                 << "SHDR_BUFFER(0," << scalar_name // Download newer GPU values only when host access needs them.
2432                 << ",dst,writeonly)\nSHDR_MAIN(){uvec2 p=gl_GlobalInvocationID.xy;" // Download newer GPU values only when host access needs them.
2433                 << "ivec2 s=imageSize(src);if(p.x>=uint(s.x)||p.y>=uint(s.y))return;" // Download newer GPU values only when host access needs them.
2434                 << vector_name << " v=imageLoad(src,ivec2(p));uint i=(p.y*uint(s.x)+p.x)*" // Download newer GPU values only when host access needs them.
2435                 << components << "u;"; // Download newer GPU values only when host access needs them.
2436            for (unsigned c = 0; c < components; ++c) // Visit the values or interfaces needed by ensure host.
2437                body << "dst[i+" << c << "u]=v[" << c << "];"; // Download newer GPU values only when host access needs them.
2438            body << "} SHDR_END()\n"; // Download newer GPU values only when host access needs them.
2439            program = owner->compile(glsl_source(body.str(), owner->language), "image readback"); // Compile the portable image-to-buffer readback shader.
2440            gl.GenBuffers(1, &staging); // Allocate names for GL storage buffers.
2441            gl.BindBuffer(SHADER_STORAGE_BUFFER, staging); // Select a buffer for allocation or transfer.
2442            gl.BufferData(SHADER_STORAGE_BUFFER, gl_size(bytes()), 0, DYNAMIC_DRAW); // Allocate buffer storage and supply its initial host values.
2443            gl.UseProgram(program); // Select the compute program for the next dispatch.
2444            gl.BindBufferBase(SHADER_STORAGE_BUFFER, 0, staging); // Bind storage to the shader interface index.
2445            gl.BindImageTexture(0, handle, 0, 0, 0, READ_ONLY, format); // Bind a typed image to its shader interface index.
2446            gl.DispatchCompute((width + 7) / 8, (height + 7) / 8, 1); // Queue the shader workgroups.
2447            gl.MemoryBarrier(ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
2448            gl.check("copy image to host staging buffer"); // Check for a driver error from the preceding GL operation.
2449            gl.BindBuffer(SHADER_STORAGE_BUFFER, staging); // Select a buffer for allocation or transfer.
2450        } // End this scope in ensure host.
2451        void* mapped = gl.MapBufferRange(SHADER_STORAGE_BUFFER, 0, gl_size(bytes()), MAP_READ_BIT); // Map completed GPU buffer values for a host readback.
2452        if (!mapped) { // Check that GL returned a readable mapped range.
2453            gl.check("map compute readback"); // Check for a driver error from the preceding GL operation.
2454            throw error("cannot map compute readback"); // Report readback mapping failure.
2455        } // End this scope in ensure host.
2456        std::memcpy(host_pointer(), mapped, bytes()); // Copy the representation with the alias-safe byte-copy operation.
2457        if (!gl.UnmapBuffer(SHADER_STORAGE_BUFFER)) // Finish reading the mapped GPU buffer.
2458            throw error("compute readback buffer contents corrupted"); // Report compute readback buffer contents corrupted.
2459        gl.check("read back compute resource"); // Check for a driver error from the preceding GL operation.
2460        latest = authority::both; // Record which backend now owns the newest resource values.
2461        if (staging) // Choose this branch when staging.
2462            gl.DeleteBuffers(1, &staging); // Release owned GL buffer names.
2463        if (program) // Choose this branch when program.
2464            gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2465    } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2466        if (staging) // Choose this branch when staging.
2467            gl.DeleteBuffers(1, &staging); // Release owned GL buffer names.
2468        if (program) // Choose this branch when program.
2469            gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2470        throw; // Rethrow the original failure after arranging the necessary cleanup.
2471    } // End this scope in ensure host.
2472} // End this scope in ensure host.
2473
2474 // Only layouts identical to std430 arrays are accepted. vec3, bool and arbitrary structs need explicit packing.
2475template <class T> // Select the scalar, dimension, or access type at compile time.
2476struct storage_type // Keep the storage type values and operations together.
2477    : std::integral_constant<bool, // Expose the following storage-layout checks as a compile-time boolean.
2478                             std::is_same<T, float>::value || std::is_same<T, int>::value || // Accept the supported 32-bit float and signed integer storage types.
2479                                 std::is_same<T, unsigned>::value> {}; // Also accept the supported 32-bit unsigned storage type.
2480template <class T, std::size_t N> // Select the scalar, dimension, or access type at compile time.
2481struct storage_type<glsl::vec<T, N>> // Keep the storage type values and operations together.
2482    : std::integral_constant<bool, // Expose the following storage-layout checks as a compile-time boolean.
2483                             storage_type<T>::value && (N == 2 || N == 4) && // Require a supported scalar and a two- or four-component vector.
2484                                 sizeof(glsl::vec<T, N>) == sizeof(T) * N> {}; // Require a tightly packed vector that matches its std430 array stride.
2485template <class T> struct buffer_state : resource_state { // Select the scalar, dimension, or access type at compile time.
2486    std::vector<T> owned; // Keep host storage allocated by this resource.
2487    T* external; // Point to application-owned host memory.
2488    std::size_t count; // Keep the element or configuration count.
2489    explicit buffer_state(std::size_t n) // Allocate owned host storage for this number of elements.
2490        : resource_state(resource_kind::buffer), owned(n), external(0), count(n) { // Initialize ownership and synchronization for one resource.
2491    } // End this scope in runtime.
2492    buffer_state(T* p, std::size_t n) // Retain a reference to an application-owned host range.
2493        : resource_state(resource_kind::buffer), external(p), count(n) { // Initialize ownership and synchronization for one resource.
2494        if (!p && n) // Require a valid pointer for a nonempty borrowed range.
2495            throw error("null borrowed CPU buffer"); // Report null borrowed cpu buffer.
2496    } // End this scope in runtime.
2497    void* host_pointer() override { // Expose this resource's borrowed or owned host storage.
2498        return external ? external : owned.data(); // Use borrowed host memory when present and owned memory otherwise.
2499    } // End this scope in runtime.
2500    std::size_t bytes() const override { // Report this resource's byte count with overflow checking.
2501        return checked_product(count, sizeof(T)); // Calculate the byte count with checked size arithmetic.
2502    } // End this scope in runtime.
2503}; // End this scope in runtime.
2504template <class T> struct image_state : resource_state { // Select the scalar, dimension, or access type at compile time.
2505    std::vector<T> owned; // Keep host storage allocated by this resource.
2506    image_state(unsigned w, unsigned h, unsigned c) : resource_state(resource_kind::image) { // Initialize ownership and synchronization for one resource.
2507        if (!w || !h || w > static_cast<unsigned>((std::numeric_limits<GLsizei>::max)()) || // Check resource size or driver limits before accessing storage.
2508            h > static_cast<unsigned>((std::numeric_limits<GLsizei>::max)())) // Require the image height to fit the GL signed dimension type.
2509            throw error("image dimensions must be positive GLsizei values"); // Report image dimensions must be positive glsizei values.
2510        width = w; // Set the image width in pixels.
2511        height = h; // Set the image height in pixels.
2512        components = c; // Set the number of scalar values per pixel.
2513        scalar = std::is_same<T, float>::value ? FLOAT // Set the GL scalar representation.
2514                 : std::is_same<T, int>::value ? INT // Choose the GL scalar type matching the host pixel representation.
2515                                               : UNSIGNED_INT; // Choose the GL scalar type matching the host pixel representation.
2516        format = c == 1 ? (scalar == FLOAT ? R32F // Visit the values or interfaces needed by runtime.
2517                           : scalar == INT ? R32I // Choose the GL internal image format matching scalar type and channel count.
2518                                           : R32UI) // Choose the GL internal image format matching scalar type and channel count.
2519                        : (scalar == FLOAT ? RGBA32F // Choose the GL internal image format matching scalar type and channel count.
2520                           : scalar == INT ? RGBA32I // Choose the GL internal image format matching scalar type and channel count.
2521                                           : RGBA32UI); // Choose the GL internal image format matching scalar type and channel count.
2522        owned.resize(checked_product(checked_product(w, h), c)); // Reject resource-size multiplication that would overflow.
2523    } // End this scope in runtime.
2524    void* host_pointer() override { // Expose this resource's borrowed or owned host storage.
2525        return owned.data(); // Expose the contiguous host storage owned by this resource.
2526    } // End this scope in runtime.
2527    std::size_t bytes() const override { // Report this resource's byte count with overflow checking.
2528        return checked_product(owned.size(), sizeof(T)); // Calculate the byte count with checked size arithmetic.
2529    } // End this scope in runtime.
2530}; // End this scope in runtime.
2531} // namespace detail
2532
2533/** @brief An application's current GL context, accessed through its function resolver.
2534 * The context must remain current on this thread during operations and destruction of GL objects.
2535 * The default header uses standard C++11 declarations. The optional
2536 * headless_device supplies EGL context creation when SHDR_ENABLE_EGL is enabled.
2537 */
2538class device { // Keep the device values and operations together.
2539    std::shared_ptr<detail::device_state> state_; // Keep the state shared by this wrapper and its retained owners.
2540
2541  public: // Expose the operations callers can use.
2542    /** @brief Load GL entry points and validate the current context against a profile.
2543     * @param resolver Callable returning the address of a named GL function, or null.
2544     * @param p Minimum GLSL and GL/ES profile. defaults to ES 3.1.
2545     * @throws error If function resolution or current-context validation fails.
2546     */
2547    explicit device(const std::function<void*(const char*)>& resolver, profile p = profile::es31) // Create a compute device using the caller's current context and function resolver.
2548        : state_(std::make_shared<detail::device_state>(resolver, p)) { // Retain the resolved GL functions, profile and device limits.
2549    } // End this scope in device.
2550    /** @brief Release deferred completion handles through context-thread cleanup.
2551     * Destroy devices on their context thread after CPU workers have stopped.
2552     */
2553    virtual ~device() noexcept { // Close pending retirement leases on the context thread.
2554        if (std::this_thread::get_id() == state_->context_thread) { // Check that the operation uses the context or lifecycle thread.
2555            try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2556                state_->close_retirements(); // Stop retaining new submission bundles during device teardown.
2557            } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2558            } // End this scope in device.
2559        } // End this scope in device.
2560    } // End this scope in device.
2561    device(const device&) = delete; // Prevent copying this object and duplicating its retained identity.
2562    device& operator=(const device&) = delete; // Prevent copying this object and duplicating its retained identity.
2563    /** @brief Return the shader language profile selected for this device. */
2564    profile shader_profile() const { // Return the device profile used to generate shader source.
2565        return state_->language; // Return the device profile used to generate shader source.
2566    } // End this scope in shader profile.
2567    /** @brief Wait for submitted GPU work to complete, including for accurate wall-clock benchmarks. */
2568    void synchronize() { // Explicitly wait for completed GPU commands.
2569        state_->collect(); // Run queued deletions and zero-time completion checks.
2570        state_->gl.Finish(); // Explicitly wait until queued GPU commands complete.
2571        state_->gl.check("wait for GPU completion"); // Check for a driver error from the preceding GL operation.
2572    } // End this scope in synchronize.
2573    /** @brief Delete GL objects retired by CPU workers and poll pending completions. */
2574    void collect_garbage() { // Collect deferred GL deletions and poll completion fences.
2575        state_->collect(); // Run queued deletions and zero-time completion checks.
2576    } // End this scope in collect garbage.
2577    /** @brief Current GL renderer name, for diagnostics and reproducible benchmark reports. */
2578    std::string renderer() const { // Read the current renderer name for reproducible diagnostics.
2579        state_->require_thread(); // Require the device context thread and activate its headless context.
2580        const unsigned char* s = state_->gl.GetString(0x1F01); // Read the driver version or renderer text.
2581        if (!s) // Validate the renderer query from the current context.
2582            throw error("no current GL context"); // Report that the renderer query requires a current GL context.
2583        return reinterpret_cast<const char*>(s); // Read the current renderer name for reproducible diagnostics.
2584    } // End this scope in renderer.
2585    /** @internal Runtime access to the retained GL function table and device limits. */
2586    const std::shared_ptr<detail::device_state>& state() const { // Expose retained runtime state to the resource and backend helpers.
2587        return state_; // Return the storage or execution state retained by this wrapper.
2588    } // End this scope in state.
2589}; // End this scope in runtime.
2590
2591/** @brief Shared typed std430 storage, owned or borrowed, with automatic CPU/GPU synchronization.
2592 * Copying a buffer shares its storage. Mutable data() marks host data authoritative.
2593 * Obtain a fresh data() pointer after a GPU dispatch before accessing host values.
2594 * GPU handles belong to one device.
2595 */
2596template <class T> class buffer { // Select the scalar, dimension, or access type at compile time.
2597    static_assert(detail::storage_type<T>::value, // Require a representation that matches the shader interface.
2598                  "buffer requires float/int/uint or matching vec2/vec4 std430 layout"); // Explain which element types match the supported storage-buffer layout.
2599    static_assert(sizeof(float) == 4 && sizeof(int) == 4 && sizeof(unsigned) == 4, // Require a representation that matches the shader interface.
2600                  "shdr requires 32-bit GLSL scalars"); // Require the host scalar representation to match GLSL storage.
2601    std::shared_ptr<detail::buffer_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2602
2603  public: // Expose the operations callers can use.
2604    /** @brief Allocate a zero-initialized host buffer containing n elements.
2605     * GPU storage is allocated lazily. Zero-length buffers are valid on the CPU.
2606     * GPU storage-buffer bindings require at least one element.
2607     */
2608    explicit buffer(std::size_t n = 0) : state_(std::make_shared<detail::buffer_state<T>>(n)) { // Create a typed buffer with owned host storage.
2609        if (n > static_cast<std::size_t>((std::numeric_limits<unsigned>::max)())) // Check resource size or driver limits before accessing storage.
2610            throw error("buffer length exceeds GLSL uint"); // Report buffer length exceeds glsl uint.
2611        detail::gl_size(state_->bytes()); // Require a byte count representable by the GL buffer API.
2612    } // End this scope in buffer.
2613    /** @brief Borrow n elements stored in application-owned host memory.
2614     * Keep the memory alive while any resource copy or shader port retains it.
2615     * Call mark_host_modified() after writing through the original pointer.
2616     */
2617    buffer(T* p, std::size_t n) : state_(std::make_shared<detail::buffer_state<T>>(p, n)) { // Initialize the typed resource storage and validate its size.
2618        if (n > static_cast<std::size_t>((std::numeric_limits<unsigned>::max)())) // Check resource size or driver limits before accessing storage.
2619            throw error("buffer length exceeds GLSL uint"); // Report buffer length exceeds glsl uint.
2620        detail::gl_size(state_->bytes()); // Require a byte count representable by the GL buffer API.
2621    } // End this scope in buffer.
2622    /** @brief Allocate owned host storage and copy an initializer list into it. */
2623    buffer(std::initializer_list<T> values) : buffer(values.size()) { // Initialize the typed resource storage and validate its size.
2624        std::copy(values.begin(), values.end(), data()); // Access host values after bringing their resource copy up to date.
2625    } // End this scope in buffer.
2626    /** @brief Return the stored element count. */
2627    std::size_t size() const { // Read the stored element or stage count.
2628        return state_->count; // Return the result of this check or operation.
2629    } // End this scope in runtime.
2630    /** @brief Synchronize newer GPU contents and return mutable host elements.
2631     * Marks host data modified. Reacquire this pointer after GPU work before using it.
2632     */
2633    T* data() { // Access host values after bringing their resource copy up to date.
2634        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2635        state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2636        return static_cast<T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2637    } // End this scope in data.
2638    /** @brief Synchronize newer GPU contents and return readonly host elements. */
2639    const T* data() const { // Access host values after bringing their resource copy up to date.
2640        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2641        return static_cast<const T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2642    } // End this scope in data.
2643    /** @brief Access one host element after synchronization. reject an out-of-range index. */
2644    T& operator[](std::size_t i) { // Bounds-check this host element before returning its typed reference.
2645        if (i >= size()) // Check resource size or driver limits before accessing storage.
2646            throw error("host buffer index out of range"); // Report host buffer index out of range.
2647        return data()[i]; // Return the result of this check or operation.
2648    } // End this scope in runtime.
2649    /** @brief Read one host element after synchronization. reject an out-of-range index. */
2650    const T& operator[](std::size_t i) const { // Bounds-check this host element before returning its typed reference.
2651        if (i >= size()) // Check resource size or driver limits before accessing storage.
2652            throw error("host buffer index out of range"); // Report host buffer index out of range.
2653        return data()[i]; // Return the result of this check or operation.
2654    } // End this scope in runtime.
2655    /** @brief Ensure this device has the latest contents, allocating or uploading as needed. */
2656    void upload(device& d) { // Explicitly make current host values available to the GPU.
2657        state_->ensure_gpu(d.state()); // Allocate or upload GPU storage when its host copy is newer.
2658    } // End this scope in upload.
2659    /** @brief Download newer GPU contents. reject a different owning device. */
2660    void download(device& d) { // Explicitly bring newer GPU values back to host storage.
2661        if (state_->owner && state_->owner != d.state()) // Check that this storage belongs to the requested device.
2662            throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2663        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2664    } // End this scope in download.
2665    /** @brief Obtain the synchronized GL SSBO handle for application interop. */
2666    unsigned gl_handle(device& d) { // Expose a synchronized GL resource handle for interoperation.
2667        upload(d); // Explicitly make current host values available to the GPU.
2668        return state_->handle; // Expose a synchronized GL resource handle for interoperation.
2669    } // End this scope in gl handle.
2670    /** @brief Notify shdr after the application writes the GL buffer. its context must be current. */
2671    void mark_gpu_modified(device& d) { // Record a write performed by application GL commands.
2672        if (state_->owner != d.state() || !state_->handle) // Check that this storage belongs to the requested device.
2673            throw error("resource has no handle on this device"); // Report a mismatch between the resource handle and the device.
2674        state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2675    } // End this scope in mark gpu modified.
2676    /** @brief Notify shdr after changing previously obtained or borrowed host memory.
2677     * Call data() before editing if GPU data must first be preserved.
2678     */
2679    void mark_host_modified() { // Record a write through retained or borrowed host memory.
2680        state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2681    } // End this scope in mark host modified.
2682    /** @brief Borrow an existing SSBO. Its contents initially belong to the GPU. caller retains ownership. */
2683    static buffer from_gl(device& d, unsigned handle, std::size_t count) { // Borrow an application-owned GL object.
2684        if (!handle) // Validate the resource handle before using it.
2685            throw error("cannot borrow GL buffer zero"); // Require a nonzero GL buffer handle.
2686        buffer result(count); // Keep the element or configuration count.
2687        result.state_->owner = d.state(); // Set the device that owns the GL resource.
2688        result.state_->handle = handle; // Set the GL buffer or texture name.
2689        result.state_->borrowed = true; // Set whether the application owns the supplied GL object.
2690        result.state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2691        return result; // Return the value returned by this operation.
2692    } // End this scope in from gl.
2693    /** @internal Runtime access to shared resource storage and synchronization state. */
2694    const std::shared_ptr<detail::buffer_state<T>>& state() const { // Expose retained runtime state to the resource and backend helpers.
2695        return state_; // Return the storage or execution state retained by this wrapper.
2696    } // End this scope in state.
2697}; // End this scope in runtime.
2698
2699/** @brief Interleaved 32-bit scalar or RGBA image shared between CPU and GPU.
2700 * C is 1 or 4. T is float, int, or unsigned. Use matching r32f/r32i/r32ui or
2701 * rgba32f/rgba32i/rgba32ui GLSL declarations. Copies and bound ports alias storage.
2702 */
2703template <class T, unsigned C = 1> class image2d { // Select the scalar, dimension, or access type at compile time.
2704    static_assert(detail::storage_type<T>::value && std::is_arithmetic<T>::value, // Require a representation that matches the shader interface.
2705                  "image requires float/int/uint"); // Require an image scalar type supported by the runtime.
2706    static_assert(C == 1 || C == 4, "portable image formats have one or four components"); // Require a representation that matches the shader interface.
2707    std::shared_ptr<detail::image_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2708
2709  public: // Expose the operations callers can use.
2710    /** @brief Allocate a zero-initialized image with positive width and height in pixels. */
2711    image2d(unsigned w, unsigned h) : state_(std::make_shared<detail::image_state<T>>(w, h, C)) { // Initialize the image geometry and typed pixel storage.
2712    } // End this scope in image2d.
2713    /** @brief Return the stored number of pixels in each row. */
2714    unsigned width() const { // Return the image width in pixels.
2715        return state_->width; // Return the result of this check or operation.
2716    } // End this scope in runtime.
2717    /** @brief Return the stored number of pixel rows. */
2718    unsigned height() const { // Return the image height in pixels.
2719        return state_->height; // Return the result of this check or operation.
2720    } // End this scope in runtime.
2721    /** @brief Synchronize newer GPU contents and return mutable interleaved host pixels.
2722     * Index component c at (x,y) as data()[(y*width()+x)*C+c]. Marks host data
2723     * modified. reacquire the pointer after GPU work before using it.
2724     */
2725    T* data() { // Access host values after bringing their resource copy up to date.
2726        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2727        state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2728        return static_cast<T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2729    } // End this scope in data.
2730    /** @brief Synchronize newer GPU contents and return readonly interleaved host pixels. */
2731    const T* data() const { // Access host values after bringing their resource copy up to date.
2732        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2733        return static_cast<const T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2734    } // End this scope in data.
2735    /** @brief Ensure this device has the latest pixels, allocating or uploading as needed. */
2736    void upload(device& d) { // Explicitly make current host values available to the GPU.
2737        state_->ensure_gpu(d.state()); // Allocate or upload GPU storage when its host copy is newer.
2738    } // End this scope in upload.
2739    /** @brief Download newer GPU pixels through a portable compute-to-buffer copy. */
2740    void download(device& d) { // Explicitly bring newer GPU values back to host storage.
2741        if (state_->owner && state_->owner != d.state()) // Check that this storage belongs to the requested device.
2742            throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2743        state_->ensure_host(); // Download newer GPU values only when host access needs them.
2744    } // End this scope in download.
2745    /** @brief Obtain the synchronized level-zero GL texture handle for application interop. */
2746    unsigned gl_handle(device& d) { // Expose a synchronized GL resource handle for interoperation.
2747        upload(d); // Explicitly make current host values available to the GPU.
2748        return state_->handle; // Expose a synchronized GL resource handle for interoperation.
2749    } // End this scope in gl handle.
2750    /** @brief Notify shdr after the application writes the GL texture. its context must be current. */
2751    void mark_gpu_modified(device& d) { // Record a write performed by application GL commands.
2752        if (state_->owner != d.state() || !state_->handle) // Check that this storage belongs to the requested device.
2753            throw error("resource has no handle on this device"); // Report a mismatch between the resource handle and the device.
2754        state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2755    } // End this scope in mark gpu modified.
2756    /** @brief Notify shdr after changing a retained host pixel pointer. */
2757    void mark_host_modified() { // Record a write through retained or borrowed host memory.
2758        state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2759    } // End this scope in mark host modified.
2760    /** @brief Borrow a matching immutable-format, level-zero 2D GL texture. caller retains ownership. */
2761    static image2d from_gl(device& d, unsigned handle, unsigned w, unsigned h) { // Borrow an application-owned GL object.
2762        if (!handle) // Validate the resource handle before using it.
2763            throw error("cannot borrow GL texture zero"); // Require a nonzero GL texture handle.
2764        image2d result(w, h); // Allocate host pixel storage before attaching the borrowed texture.
2765        result.state_->owner = d.state(); // Set the device that owns the GL resource.
2766        result.state_->handle = handle; // Set the GL buffer or texture name.
2767        result.state_->borrowed = true; // Set whether the application owns the supplied GL object.
2768        result.state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2769        return result; // Return the value returned by this operation.
2770    } // End this scope in from gl.
2771    /** @internal Runtime access to shared image storage and synchronization state. */
2772    const std::shared_ptr<detail::image_state<T>>& state() const { // Expose retained runtime state to the resource and backend helpers.
2773        return state_; // Return the storage or execution state retained by this wrapper.
2774    } // End this scope in state.
2775}; // End this scope in runtime.
2776
2777class kernel; // Keep the kernel values and operations together.
2778namespace detail { // Group these definitions in the detail namespace.
2779enum class port_kind { buffer, image, uniform }; // Name the profile, access, or completion values accepted by this section.
2780struct port_base { // Keep the port base values and operations together.
2781    kernel& parent; // Keep the shader instance that owns this interface.
2782    std::string name; // Keep the resource or entry-point name.
2783    unsigned binding; // Keep the numeric shader resource binding.
2784    access mode; // Keep the declared shader resource access.
2785    port_kind kind; // Keep the buffer, image, or uniform interface kind.
2786    port_base(kernel&, const char*, unsigned, access, port_kind); // Register the named interface with its owning shader.
2787    virtual ~port_base() { // Allow typed interfaces to be destroyed through this base interface.
2788    } // End this scope in runtime.
2789    virtual std::shared_ptr<resource_state> resource() const { // Expose the retained storage used by this port.
2790        return std::shared_ptr<resource_state>(); // Represent a uniform-only interface with an empty resource reference.
2791    } // End this scope in runtime.
2792    virtual void bind_gpu(device_state&, GLuint) { // Bind this interface or assign its uniform before dispatch.
2793    } // End this scope in bind gpu.
2794    virtual void validate() const { // Check that this resource binding satisfies the shader declaration.
2795    } // End this scope in validate.
2796    virtual void copy_to(port_base&) const { // Copy the typed port into a matching snapshot interface.
2797        throw error("shader port does not support snapshots"); // Report that this port requires snapshot support.
2798    } // End this scope in copy to.
2799}; // End this scope in runtime.
2800} // namespace detail
2801
2802/** @brief Base for compiled shader objects, owning resource declarations and invocation builtins.
2803 * Shader objects are neither copyable nor movable because their ports refer to their instance.
2804 * CMake-generated adapters embed their native GLSL source automatically.
2805 */
2806class kernel { // Keep the kernel values and operations together.
2807    std::string name_, source_; // Keep the diagnostic shader name and its embedded GLSL text.
2808    extent local_; // Keep the fixed workgroup dimensions.
2809    std::vector<detail::port_base*> ports_; // Keep the registered resource and uniform interfaces.
2810    std::shared_ptr<detail::program_state> program_; // Keep the retained compiled compute program.
2811
2812  protected: // Allow derived kernels to initialize their embedded source.
2813 // Generated shader constructors install their build-embedded GLSL through this method.
2814    void set_embedded_source(const char* text) { // Retain the build-generated GLSL text inside the shader.
2815        source_ = text; // Set the automatically embedded shader text.
2816    } // End this scope in runtime.
2817
2818  public: // Expose the operations callers can use.
2819    glsl::uvec3 gl_GlobalInvocationID, gl_LocalInvocationID, gl_WorkGroupID, gl_NumWorkGroups, // Keep CPU global, local, group and dispatch coordinates for GLSL builtins.
2820        gl_WorkGroupSize; // Keep the fixed local dimensions exposed to CPU shader code.
2821    unsigned gl_LocalInvocationIndex; // Keep the flattened index within the current CPU work group.
2822    /** @brief Construct a kernel identity and positive local workgroup dimensions.
2823     * SHDR_BEGIN emits this constructor for shared shader classes.
2824     */
2825    kernel(const std::string& name, extent local) // Initialize the shader name, local dimensions, and invocation values.
2826        : name_(name), local_(local), gl_LocalInvocationIndex(0) { // Remember the shader name and local size with initially zero CPU invocation state.
2827        if (!local.x || !local.y || !local.z) // Require positive local dimensions on every axis.
2828            throw error("local work group dimensions must be positive"); // Report local work group dimensions must be positive.
2829        gl_WorkGroupSize = glsl::uvec3(local.x, local.y, local.z); // Publish the fixed local dimensions to CPU shader builtins.
2830    } // End this scope in kernel.
2831    virtual ~kernel() { // Allow derived shader instances to be destroyed through the base interface.
2832    } // End this scope in kernel.
2833    kernel(const kernel&) = delete; // Prevent copying this object and duplicating its retained identity.
2834    kernel& operator=(const kernel&) = delete; // Prevent copying this object and duplicating its retained identity.
2835    /** @brief Execute one CPU invocation. SHDR_MAIN supplies the override.
2836     * Dispatch through a stage or pipeline to initialize builtins and synchronize resources.
2837     */
2838    virtual void main() = 0; // Require a compiled shader to supply its CPU invocation method.
2839    /** @brief Make an independent shader instance with a snapshot of its resource bindings and uniforms. */
2840    virtual std::unique_ptr<kernel> clone() const { // Create an independent shader instance for deferred CPU execution.
2841        throw error("shader does not support snapshots"); // Report that this shader requires snapshot support.
2842    } // End this scope in runtime.
2843    /** @internal Copy registered interfaces into a newly constructed instance. */
2844    void copy_interfaces(kernel& destination) const { // Copy resource bindings and uniforms into a fresh shader clone.
2845        if (ports_.size() != destination.ports_.size()) // Check resource size or driver limits before accessing storage.
2846            throw error("shader snapshot interface mismatch"); // Report shader snapshot interface mismatch.
2847        for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
2848            ports_[i]->copy_to(*destination.ports_[i]); // Copy the typed port into a matching snapshot interface.
2849    } // End this scope in copy interfaces.
2850    /** @internal Retain all resources used by an enqueued dispatch. */
2851    std::vector<std::shared_ptr<detail::resource_state>> resources() const { // Collect the shared storage used by this shader.
2852        std::vector<std::shared_ptr<detail::resource_state>> result; // Keep the value returned by this operation.
2853        for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
2854            auto r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
2855            if (r) // Choose this branch when r.
2856                result.push_back(r); // Retain this entry in the ordered resource or work collection.
2857        } // End this scope in resources.
2858        return result; // Return the value returned by this operation.
2859    } // End this scope in resources.
2860    /** @internal Retain a compiled program during asynchronous execution. */
2861    const std::shared_ptr<detail::program_state>& program_state() const { // Expose the retained compiled program for asynchronous ownership.
2862        return program_; // Return the retained compiled compute program.
2863    } // End this scope in program state.
2864    /** @brief Return the kernel's diagnostic name. */
2865    const std::string& name() const { // Return the diagnostic shader name.
2866        return name_; // Return the kernel or registration name.
2867    } // End this scope in runtime.
2868    /** @brief Return the fixed local workgroup dimensions declared by SHDR_BEGIN. */
2869    extent local_size() const { // Return the fixed local work group dimensions.
2870        return local_; // Return the fixed workgroup dimensions.
2871    } // End this scope in runtime.
2872    /** @brief Export this shader's automatically embedded source for compiler diagnostics or tooling. */
2873    std::string glsl(profile p) const { // Export the embedded shader for the requested language profile.
2874        if (source_.empty()) // Choose this branch when source .empty().
2875            throw error("shader has no embedded GPU source: " + name_); // Report that this shader requires an embedded GPU program.
2876        return glsl_source(source_, p); // Return the result of this check or operation.
2877    } // End this scope in runtime.
2878    /** @internal Register declarations emitted by the shared shader macros. */
2879    void register_port(detail::port_base& port) { // Register one named resource or uniform with duplicate checks.
2880        for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
2881            if (ports_[i]->name == port.name) // Choose this branch when ports [i]->name equals port.name.
2882                throw error("duplicate shader port: " + port.name); // Report duplicate shader port: .
2883            if (port.kind != detail::port_kind::uniform && ports_[i]->kind == port.kind && // Choose the branch matching this interface or resource access.
2884                ports_[i]->binding == port.binding) // Set the numeric shader resource binding.
2885                throw error("duplicate shader resource binding: " + port.name); // Report duplicate shader resource binding: .
2886        } // End this scope in register port.
2887        ports_.push_back(&port); // Retain this entry in the ordered resource or work collection.
2888    } // End this scope in register port.
2889    /** @brief Bind by name, for runtime-selected shader modules. Type mismatches throw error. */
2890    template <class T> kernel& bind(const std::string& name, const buffer<T>& resource); // Select the scalar, dimension, or access type at compile time.
2891    /** @brief Bind an image by name. scalar type and component count must match its port. */
2892    template <class T, unsigned C> // Select the scalar, dimension, or access type at compile time.
2893    kernel& bind(const std::string& name, const image2d<T, C>& resource); // Rebind a named resource port while preserving its declared type.
2894    /** @brief Assign a uniform by name. T must exactly match its declared shader type. */
2895    template <class T> kernel& set(const std::string& name, const T& value); // Select the scalar, dimension, or access type at compile time.
2896    /** @internal Find a registered port for runtime binding and uniform assignment. */
2897    detail::port_base& find_port(const std::string& name) { // Resolve the named shader interface.
2898        for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
2899            if (ports_[i]->name == name) // Choose this branch when ports [i]->name equals name.
2900                return *ports_[i]; // Resolve the named shader interface.
2901        throw error("unknown shader port: " + name); // Report unknown shader port: .
2902    } // End this scope in find port.
2903    /** @brief Execute one dispatch with workgroup counts on a device, or on the CPU if null.
2904     * Normally called by pipeline.run(). GPU work uses the embedded shader and a current context.
2905     */
2906    void run(extent groups, device* d); // Keep the target device.
2907    /** @brief Compile and allocate GPU resources before entering a latency-sensitive dispatch loop. */
2908    void prepare(device& d); // Compile the program and prepare its bound GPU resources.
2909}; // End this scope in runtime.
2910
2911namespace detail { // Group these definitions in the detail namespace.
2912inline port_base::port_base(kernel& p, const char* n, unsigned b, access a, port_kind k) // Register the named interface with its owning shader.
2913    : parent(p), name(n), binding(b), mode(a), kind(k) { // Record the owning kernel, interface name, binding, access and resource kind.
2914    parent.register_port(*this); // Register one named resource or uniform with duplicate checks.
2915} // End this scope in runtime.
2916} // namespace detail
2917
2918/** @brief Typed shader SSBO declaration. assign a buffer to bind or rebind it. */
2919template <class T, access A = access::readwrite> class buffer_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
2920    std::shared_ptr<detail::buffer_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2921    unsigned fixed_length_; // Keep the fixed array length declared by the shader.
2922
2923  public: // Expose the operations callers can use.
2924    /** @brief Declare a typed buffer port on a kernel, usually through SHDR_BUFFER. */
2925    buffer_port(kernel& p, unsigned b, const char* n, unsigned fixed = 0) // Register a typed buffer interface and any fixed shader array length.
2926        : port_base(p, n, b, A, detail::port_kind::buffer), fixed_length_(fixed) { // Record the buffer interface and its optional fixed shader length.
2927    } // End this scope in runtime.
2928    /** @brief Bind or rebind this port to the buffer's retained shared storage. */
2929    buffer_port& operator=(const buffer<T>& b) { // Retain the newly bound typed resource in this shader interface.
2930        state_ = b.state(); // Set the state shared by this wrapper and its retained owners.
2931        return *this; // Allow another operation to follow in the same expression.
2932    } // End this scope in runtime.
2933    void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
2934        buffer_port* p = dynamic_cast<buffer_port*>(&destination); // Require a snapshot port with the same buffer type and access qualifier.
2935        if (!p) // Validate the typed interface pointer before accessing it.
2936            throw error("buffer snapshot type mismatch: " + name); // Report buffer snapshot type mismatch: .
2937        p->state_ = state_; // Set the state shared by this wrapper and its retained owners.
2938    } // End this scope in copy to.
2939    /** @brief Return the bound buffer's element count, matching GLSL array length(). */
2940    unsigned length() const { // Return the GLSL-visible array length after validating its binding.
2941        validate(); // Check that this resource binding satisfies the shader declaration.
2942        return fixed_length_ ? fixed_length_ : static_cast<unsigned>(state_->count); // Return the GLSL-visible array length after validating its binding.
2943    } // End this scope in length.
2944    /** @brief Access an element during CPU execution, checking bounds and declared access.
2945     * Readonly ports return const references. Pipeline execution synchronizes host contents.
2946     */
2947    typename std::conditional<A == access::readonly, const T&, T&>::type operator[](std::size_t i) { // Expose a const component for readonly ports and a mutable one otherwise.
2948        validate(); // Check that this resource binding satisfies the shader declaration.
2949        const std::size_t limit = fixed_length_ ? fixed_length_ : state_->count; // Use the declared array size or the full bound buffer length.
2950        if (i >= limit) // Choose this branch when i >= limit.
2951            throw error("CPU SSBO index out of bounds: " + name); // Report cpu ssbo index out of bounds: .
2952        return static_cast<T*>(state_->host_pointer())[i]; // Return the result of this check or operation.
2953    } // End this scope in runtime.
2954    void validate() const override { // Check that this resource binding satisfies the shader declaration.
2955        if (!state_) // Require retained storage for this interface.
2956            throw error("unbound shader buffer: " + name); // Report unbound shader buffer: .
2957        if (fixed_length_ && state_->count < fixed_length_) // Check resource size or driver limits before accessing storage.
2958            throw error("buffer is smaller than the shader's fixed array: " + name); // Report buffer is smaller than the shader's fixed array: .
2959    } // End this scope in validate.
2960    std::shared_ptr<detail::resource_state> resource() const override { // Expose the retained storage used by this port.
2961        return state_; // Return the storage or execution state retained by this wrapper.
2962    } // End this scope in runtime.
2963    void bind_gpu(detail::device_state& d, unsigned) override { // Bind this interface or assign its uniform before dispatch.
2964        if (binding >= d.max_buffers) // Choose this branch when binding >= d.max buffers.
2965            throw error("SSBO binding exceeds device limit: " + name); // Report ssbo binding exceeds device limit: .
2966        if (!state_->bytes()) // Check resource size or driver limits before accessing storage.
2967            throw error("GPU SSBO bindings require a nonempty buffer: " + name); // Report gpu ssbo bindings require a nonempty buffer: .
2968        d.gl.BindBufferBase(detail::SHADER_STORAGE_BUFFER, binding, state_->handle); // Bind storage to the shader interface index.
2969    } // End this scope in bind gpu.
2970}; // End this scope in runtime.
2971
2972namespace detail { // Group these definitions in the detail namespace.
2973inline void uniform_value(gl_api& gl, GLint loc, float v) { // Send the typed uniform value through its matching GL call.
2974    gl.Uniform1f(loc, v); // Assign a float uniform.
2975} // End this scope in uniform value.
2976inline void uniform_value(gl_api& gl, GLint loc, int v) { // Send the typed uniform value through its matching GL call.
2977    gl.Uniform1i(loc, v); // Assign an integer or boolean uniform.
2978} // End this scope in uniform value.
2979inline void uniform_value(gl_api& gl, GLint loc, unsigned v) { // Send the typed uniform value through its matching GL call.
2980    gl.Uniform1ui(loc, v); // Assign an unsigned integer uniform.
2981} // End this scope in uniform value.
2982inline void uniform_value(gl_api& gl, GLint loc, bool v) { // Send the typed uniform value through its matching GL call.
2983    gl.Uniform1i(loc, v ? 1 : 0); // Assign an integer or boolean uniform.
2984} // End this scope in uniform value.
2985#define SHDR_UNIFORM_VEC(n, t, suffix) /* Define the SHDR_UNIFORM_VEC helper for this group of declarations. */ \
2986    inline void uniform_value(gl_api& gl, GLint loc, const glsl::vec<t, n>& v) { /* Send the typed uniform value through its matching GL call. */ \
2987        t packed[n]; /* Pack the vector components contiguously for the GL uniform call. */ \
2988        for (unsigned i = 0; i < n; ++i) /* Visit the values or interfaces needed by uniform value. */ \
2989            packed[i] = v[i]; /* Copy the component into the contiguous GL uniform payload. */ \
2990        gl.Uniform##n##suffix(loc, 1, packed); /* Send the packed vector components through their matching GL function. */ \
2991    } /* End this scope in uniform value. */
2992SHDR_UNIFORM_VEC(2, float, fv) // Define the listed float, signed or unsigned vector uniform overloads.
2993SHDR_UNIFORM_VEC(3, float, fv) SHDR_UNIFORM_VEC(4, float, fv) SHDR_UNIFORM_VEC(2, int, iv) // Define the listed float, signed or unsigned vector uniform overloads.
2994    SHDR_UNIFORM_VEC(3, int, iv) SHDR_UNIFORM_VEC(4, int, iv) SHDR_UNIFORM_VEC(2, unsigned, uiv) // Define the listed float, signed or unsigned vector uniform overloads.
2995        SHDR_UNIFORM_VEC(3, unsigned, uiv) SHDR_UNIFORM_VEC(4, unsigned, uiv) // Define the listed float, signed or unsigned vector uniform overloads.
2996#undef SHDR_UNIFORM_VEC // Remove this temporary macro after its declarations are complete.
2997            template <std::size_t N> // Select the scalar, dimension, or access type at compile time.
2998            inline void uniform_value(gl_api& gl, GLint loc, const glsl::vec<bool, N>& v) { // Send the typed uniform value through its matching GL call.
2999    GLint packed[N]; // Pack boolean components as the integer values expected by GL.
3000    for (unsigned i = 0; i < N; ++i) // Visit the values or interfaces needed by uniform value.
3001        packed[i] = v[i] ? 1 : 0; // Represent a boolean uniform component as a GL integer.
3002    if (N == 2) // Choose this branch when N equals 2.
3003        gl.Uniform2iv(loc, 1, packed); // Send two integer-represented boolean components to GL.
3004    else if (N == 3) // Choose this branch when N equals 3.
3005        gl.Uniform3iv(loc, 1, packed); // Send three integer-represented boolean components to GL.
3006    else // Handle the other resource, platform, or completion case.
3007        gl.Uniform4iv(loc, 1, packed); // Send four integer-represented boolean components to GL.
3008} // End this scope in uniform value.
3009#define SHDR_UNIFORM_MATRIX(c, r, n) /* Define the SHDR_UNIFORM_MATRIX helper for this group of declarations. */ \
3010    inline void uniform_value(gl_api& gl, GLint loc, const glsl::mat<float, c, r>& m) { /* Send the typed uniform value through its matching GL call. */ \
3011        float packed[c * r]; /* Send the typed uniform value through its matching GL call. */ \
3012        for (unsigned i = 0; i < c; ++i) /* Visit the values or interfaces needed by uniform value. */ \
3013            for (unsigned j = 0; j < r; ++j) /* Visit the values or interfaces needed by uniform value. */ \
3014                packed[i * r + j] = m[i][j]; /* Flatten the matrix in GLSL column order. */ \
3015        gl.UniformMatrix##n##fv(loc, 1, 0, packed); /* Upload the column-major matrix with the transpose flag set to false. */ \
3016    } /* End this scope in uniform value. */
3017SHDR_UNIFORM_MATRIX(2, 2, 2) // Define the listed column-major matrix uniform overloads.
3018SHDR_UNIFORM_MATRIX(3, 3, 3) SHDR_UNIFORM_MATRIX(4, 4, 4) SHDR_UNIFORM_MATRIX(2, 3, 2x3) // Define the listed column-major matrix uniform overloads.
3019    SHDR_UNIFORM_MATRIX(2, 4, 2x4) SHDR_UNIFORM_MATRIX(3, 2, 3x2) SHDR_UNIFORM_MATRIX(3, 4, 3x4) // Define the listed column-major matrix uniform overloads.
3020        SHDR_UNIFORM_MATRIX(4, 2, 4x2) SHDR_UNIFORM_MATRIX(4, 3, 4x3) // Define the listed column-major matrix uniform overloads.
3021#undef SHDR_UNIFORM_MATRIX // Remove this temporary macro after its declarations are complete.
3022} // namespace detail
3023
3024/** @brief A zero-initialized typed shader uniform, assigned with ordinary C++ syntax. */
3025template <class T> class uniform_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
3026    T owned_; // Keep the uniform value stored by the port.
3027    T* value_; // Keep the current uniform field.
3028
3029  public: // Expose the operations callers can use.
3030    /** @brief Declare a zero-initialized uniform backed by this port's own value. */
3031    uniform_port(kernel& p, const char* n) // Register a typed uniform backed by this port's own zero-initialized value.
3032        : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(), // Keep the uniform value stored by the port.
3033          value_(&owned_) { // Keep the uniform value stored by the port.
3034    } // End this scope in runtime.
3035    /** @brief Register an existing typed kernel field as a uniform. emitted by SHDR_UNIFORM. */
3036    uniform_port(kernel& p, const char* n, T& value) // Register a uniform and refer to its shader member value.
3037        : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(), // Keep the uniform value stored by the port.
3038          value_(&value) { // Refer to the uniform member owned by this shader instance.
3039    } // End this scope in runtime.
3040    /** @brief Set the uniform value uploaded at the next dispatch. */
3041    uniform_port& operator=(const T& value) { // Assign the shader member referred to by this uniform interface.
3042        *value_ = value; // Set the current uniform field.
3043        return *this; // Allow another operation to follow in the same expression.
3044    } // End this scope in runtime.
3045    /** @brief Read the uniform as its declared shader type during CPU execution. */
3046    operator T() const { // Read the uniform member as an ordinary value of its declared type.
3047        return *value_; // Return the result of this check or operation.
3048    } // End this scope in runtime.
3049    /** @brief Return the stored uniform value. */
3050    const T& value() const { // Read the shader member referred to by this uniform port.
3051        return *value_; // Return the result of this check or operation.
3052    } // End this scope in runtime.
3053    void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
3054        uniform_port* p = dynamic_cast<uniform_port*>(&destination); // Require a snapshot port with the same uniform type.
3055        if (!p) // Validate the typed interface pointer before accessing it.
3056            throw error("uniform snapshot type mismatch: " + name); // Report uniform snapshot type mismatch: .
3057        *p->value_ = *value_; // Set the current uniform field.
3058    } // End this scope in copy to.
3059    void bind_gpu(detail::device_state& d, unsigned program) override { // Bind this interface or assign its uniform before dispatch.
3060        const int loc = d.gl.GetUniformLocation(program, name.c_str()); // Find a named uniform in the linked program.
3061        if (loc >= 0) // Choose this branch when loc >= 0.
3062            detail::uniform_value(d.gl, loc, *value_); // Send the typed uniform value through its matching GL call.
3063    } // End this scope in bind gpu.
3064}; // End this scope in runtime.
3065
3066/** @brief A typed image declaration with format/access matching its shared shader. */
3067template <class T, unsigned C, access A> class image_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
3068    std::shared_ptr<detail::image_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
3069
3070  public: // Expose the operations callers can use.
3071    /** @brief Declare an image port, usually through SHDR_IMAGE2D. */
3072    image_port(kernel& p, unsigned b, const char* n) // Register a typed image interface at the specified binding.
3073        : port_base(p, n, b, A, detail::port_kind::image) { // Record the image interface and its declared access qualifier.
3074    } // End this scope in runtime.
3075    /** @brief Bind or rebind this port to the image's retained shared storage. */
3076    image_port& operator=(const image2d<T, C>& image) { // Retain the newly bound typed resource in this shader interface.
3077        state_ = image.state(); // Set the state shared by this wrapper and its retained owners.
3078        return *this; // Allow another operation to follow in the same expression.
3079    } // End this scope in runtime.
3080    void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
3081        image_port* p = dynamic_cast<image_port*>(&destination); // Require a snapshot port with the same image type and access qualifier.
3082        if (!p) // Validate the typed interface pointer before accessing it.
3083            throw error("image snapshot type mismatch: " + name); // Report image snapshot type mismatch: .
3084        p->state_ = state_; // Set the state shared by this wrapper and its retained owners.
3085    } // End this scope in copy to.
3086    void validate() const override { // Check that this resource binding satisfies the shader declaration.
3087        if (!state_) // Require retained storage for this interface.
3088            throw error("unbound shader image: " + name); // Report unbound shader image: .
3089    } // End this scope in validate.
3090    std::shared_ptr<detail::resource_state> resource() const override { // Expose the retained storage used by this port.
3091        return state_; // Return the storage or execution state retained by this wrapper.
3092    } // End this scope in runtime.
3093    /** @internal Read image state for the CPU imageLoad/imageStore/imageSize helpers. */
3094    const std::shared_ptr<detail::image_state<T>>& image_state() const { // Expose the validated image storage to CPU image helpers.
3095        validate(); // Check that this resource binding satisfies the shader declaration.
3096        return state_; // Return the storage or execution state retained by this wrapper.
3097    } // End this scope in runtime.
3098    void bind_gpu(detail::device_state& d, unsigned) override { // Bind this interface or assign its uniform before dispatch.
3099        if (binding >= d.max_images) // Choose this branch when binding >= d.max images.
3100            throw error("image binding exceeds device limit: " + name); // Report image binding exceeds device limit: .
3101        d.gl.BindImageTexture(binding, // Bind a typed image to its shader interface index.
3102                              state_->handle, // Keep the GL buffer or texture name.
3103                              0, // Supply the next value for the current call or declaration.
3104                              0, // Supply the next value for the current call or declaration.
3105                              0, // Supply the next value for the current call or declaration.
3106                              A == access::readonly    ? detail::READ_ONLY // Select the GL read or write qualifier matching this typed image port.
3107                              : A == access::writeonly ? detail::WRITE_ONLY // Choose the GL image access matching the shader qualifier.
3108                                                       : detail::READ_WRITE, // Choose the GL image access matching the shader qualifier.
3109                              state_->format); // Keep the image storage format.
3110    } // End this scope in bind gpu.
3111}; // End this scope in runtime.
3112
3113/** @brief GLSL image dimensions in pixels. */
3114template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3115inline glsl::ivec2 imageSize(const image_port<T, C, A>& image) { // Return the bound image dimensions as GLSL integers.
3116    return glsl::ivec2(image.image_state()->width, image.image_state()->height); // Return the bound image dimensions as GLSL integers.
3117} // End this scope in imageSize.
3118/** @brief Load one texel. Missing RGB components are zero and missing alpha is one.
3119 * Out-of-range coordinates return zero. loading a writeonly image is a compile error.
3120 */
3121template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3122inline glsl::vec<T, 4> imageLoad(const image_port<T, C, A>& image, glsl::ivec2 pos) { // Load one pixel while enforcing readonly access and image bounds.
3123    static_assert(A != access::writeonly, "cannot imageLoad a writeonly image"); // Require a representation that matches the shader interface.
3124    const std::shared_ptr<detail::image_state<T>>& s = image.image_state(); // Access the retained image geometry and host pixel storage.
3125    if (pos.x < 0 || pos.y < 0 || static_cast<unsigned>(pos.x) >= s->width || // Choose this branch when pos.x < 0 or pos.y < 0 or static cast<unsigned>(pos.x) >= s->width or .
3126        static_cast<unsigned>(pos.y) >= s->height) // Reject an image row outside the allocated pixel storage.
3127        return glsl::vec<T, 4>(T(0)); // Load one pixel while enforcing readonly access and image bounds.
3128    glsl::vec<T, 4> result(T(0)); // Start the loaded texel with zero components before filling its channels.
3129    result[3] = T(1); // Set the value returned by this operation.
3130    const std::size_t start = // Set the beginning of the current token or range.
3131        (static_cast<std::size_t>(pos.y) * s->width + static_cast<unsigned>(pos.x)) * C; // Load one pixel while enforcing readonly access and image bounds.
3132    for (unsigned c = 0; c < C; ++c) // Visit the values or interfaces needed by imageLoad.
3133        result[c] = s->owned[start + c]; // Set the value returned by this operation.
3134    return result; // Return the value returned by this operation.
3135} // End this scope in imageLoad.
3136/** @brief Store a texel, ignoring out-of-range coordinates. Readonly stores are a compile error. */
3137template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3138inline void imageStore(image_port<T, C, A>& image, glsl::ivec2 pos, const glsl::vec<T, 4>& value) { // Store one pixel while enforcing writable access and image bounds.
3139    static_assert(A != access::readonly, "cannot imageStore a readonly image"); // Require a representation that matches the shader interface.
3140    const std::shared_ptr<detail::image_state<T>>& s = image.image_state(); // Access the retained image geometry and host pixel storage.
3141    if (pos.x < 0 || pos.y < 0 || static_cast<unsigned>(pos.x) >= s->width || // Choose this branch when pos.x < 0 or pos.y < 0 or static cast<unsigned>(pos.x) >= s->width or .
3142        static_cast<unsigned>(pos.y) >= s->height) // Reject an image row outside the allocated pixel storage.
3143        return; // Finish this operation.
3144    const std::size_t start = // Set the beginning of the current token or range.
3145        (static_cast<std::size_t>(pos.y) * s->width + static_cast<unsigned>(pos.x)) * C; // Store one pixel while enforcing writable access and image bounds.
3146    for (unsigned c = 0; c < C; ++c) // Visit the values or interfaces needed by imageStore.
3147        s->owned[start + c] = value[c]; // Set host storage allocated by this resource.
3148} // End this scope in imageStore.
3149
3150template <class T> inline kernel& kernel::bind(const std::string& name, const buffer<T>& b) { // Select the scalar, dimension, or access type at compile time.
3151    detail::port_base& p = find_port(name); // Find the declared shader interface with this resource name.
3152    if (buffer_port<T, access::readonly>* v = dynamic_cast<buffer_port<T, access::readonly>*>(&p)) // Choose this branch when buffer port<T, access::readonly>* v = dynamic cast<buffer port<T, access::readonly>*>(&p).
3153        *v = b; // Store the current v value for this operation.
3154    else if (buffer_port<T, access::writeonly>* v = // Choose this branch when buffer port<T, access::writeonly>* v =.
3155                 dynamic_cast<buffer_port<T, access::writeonly>*>(&p)) // Try the matching typed write-only buffer interface.
3156        *v = b; // Store the current v value for this operation.
3157    else if (buffer_port<T, access::readwrite>* v = // Choose this branch when buffer port<T, access::readwrite>* v =.
3158                 dynamic_cast<buffer_port<T, access::readwrite>*>(&p)) // Try the matching typed read-write buffer interface.
3159        *v = b; // Store the current v value for this operation.
3160    else // Handle the other resource, platform, or completion case.
3161        throw error("buffer type mismatch: " + name); // Report buffer type mismatch: .
3162    return *this; // Allow another operation to follow in the same expression.
3163} // End this scope in runtime.
3164template <class T, unsigned C> // Select the scalar, dimension, or access type at compile time.
3165inline kernel& kernel::bind(const std::string& name, const image2d<T, C>& b) { // Rebind a named resource port while preserving its declared type.
3166    detail::port_base& p = find_port(name); // Find the declared shader interface with this resource name.
3167    if (image_port<T, C, access::readonly>* v = // Choose this branch when image port<T, C, access::readonly>* v =.
3168            dynamic_cast<image_port<T, C, access::readonly>*>(&p)) // Try the matching typed read-only image interface.
3169        *v = b; // Store the current v value for this operation.
3170    else if (image_port<T, C, access::writeonly>* v = // Choose this branch when image port<T, C, access::writeonly>* v =.
3171                 dynamic_cast<image_port<T, C, access::writeonly>*>(&p)) // Try the matching typed write-only image interface.
3172        *v = b; // Store the current v value for this operation.
3173    else if (image_port<T, C, access::readwrite>* v = // Choose this branch when image port<T, C, access::readwrite>* v =.
3174                 dynamic_cast<image_port<T, C, access::readwrite>*>(&p)) // Try the matching typed read-write image interface.
3175        *v = b; // Store the current v value for this operation.
3176    else // Handle the other resource, platform, or completion case.
3177        throw error("image type mismatch: " + name); // Report image type mismatch: .
3178    return *this; // Allow another operation to follow in the same expression.
3179} // End this scope in runtime.
3180template <class T> inline kernel& kernel::set(const std::string& name, const T& value) { // Select the scalar, dimension, or access type at compile time.
3181    uniform_port<T>* p = dynamic_cast<uniform_port<T>*>(&find_port(name)); // Require the named uniform to have the supplied value's type.
3182    if (!p) // Validate the typed interface pointer before accessing it.
3183        throw error("uniform type mismatch: " + name); // Report uniform type mismatch: .
3184    *p = value; // Update the typed uniform value for subsequent dispatches.
3185    return *this; // Allow another operation to follow in the same expression.
3186} // End this scope in runtime.
3187
3188inline void kernel::prepare(device& d) { // Compile the program and prepare its bound GPU resources.
3189    const auto& state = d.state(); // Set the shared device or worker state.
3190    state->collect(); // Run queued deletions and zero-time completion checks.
3191    for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
3192        ports_[i]->validate(); // Check that this resource binding satisfies the shader declaration.
3193    if (!program_) { // Compile the shader when its cached program is empty.
3194        if (source_.empty()) // Choose this branch when source .empty().
3195            throw error("shader has no embedded GPU source: " + name_); // Report that this shader requires an embedded GPU program.
3196        program_ = std::make_shared<detail::program_state>( // Set the retained compiled compute program.
3197            state, state->compile(glsl_source(source_, state->language), name_)); // Add the selected GLSL version and shared-declaration definitions.
3198        detail::GLint actual[3] = {0, 0, 0}; // Prepare all three local dimensions reported by the linked program.
3199        state->gl.GetProgramiv(program_->id, detail::COMPUTE_WORK_GROUP_SIZE, actual); // Read linked-program status, log length, or local dimensions.
3200        if (actual[0] != static_cast<int>(local_.x) || actual[1] != static_cast<int>(local_.y) || // Choose this branch when actual[0] differs from static cast<int>(local .x) or actual[1] differs from static cast<int>(local .y) or .
3201            actual[2] != static_cast<int>(local_.z)) { // Require the linked program's third local dimension to match the CPU shader.
3202            program_.reset(); // Release or replace the owned object at this lifecycle boundary.
3203            throw error("GPU source and C++ local sizes differ: " + name_); // Report gpu source and c++ local sizes differ: .
3204        } // End this scope in prepare.
3205    } // End this scope in prepare.
3206    if (program_->owner != state) // Check that this storage belongs to the requested device.
3207        throw error("shader program belongs to a different device; create a new shader instance"); // Report shader program belongs to a different device. create a new shader instance.
3208    for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3209        auto r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3210        if (r) // Choose this branch when r.
3211            r->ensure_gpu(state); // Allocate or upload GPU storage when its host copy is newer.
3212    } // End this scope in prepare.
3213} // End this scope in prepare.
3214
3215inline void kernel::run(extent groups, device* d) { // Keep the target device.
3216    if (!groups.x || !groups.y || !groups.z) // Finish an empty dispatch before submitting GL commands.
3217        return; // Finish this operation.
3218    const unsigned g[3] = {groups.x, groups.y, groups.z}, l[3] = {local_.x, local_.y, local_.z}; // Keep dispatch counts and local dimensions for validation and CPU indexing.
3219    for (unsigned i = 0; i < 3; ++i) // Validate or query each of the three compute dimensions.
3220        if (g[i] > (std::numeric_limits<unsigned>::max)() / l[i]) // Choose this branch when g[i] > (std::numeric limits<unsigned>::max)() / l[i].
3221            throw error("global invocation index overflow"); // Report global invocation index overflow.
3222    std::vector<std::shared_ptr<detail::resource_state>> outputs; // Retain the writable resources whose authority changes after this dispatch.
3223    for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3224        ports_[i]->validate(); // Check that this resource binding satisfies the shader declaration.
3225        std::shared_ptr<detail::resource_state> r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3226        if (r && ports_[i]->mode != access::readonly) // Choose the branch matching this interface or resource access.
3227            outputs.push_back(r); // Retain this entry in the ordered resource or work collection.
3228    } // End this scope in runtime.
3229    if (d) { // Choose this branch when d.
3230        const std::shared_ptr<detail::device_state>& state = d->state(); // Set the shared device or worker state.
3231        for (unsigned i = 0; i < 3; ++i) { // Validate or query each of the three compute dimensions.
3232            if (g[i] > state->max_groups[i]) // Choose this branch when g[i] > state->max groups[i].
3233                throw error("dispatch exceeds device work group count"); // Report dispatch exceeds device work group count.
3234            if (l[i] > state->max_local[i]) // Choose this branch when l[i] > state->max local[i].
3235                throw error("local work group dimension exceeds device limit"); // Report local work group dimension exceeds device limit.
3236        } // End this scope in runtime.
3237        const std::size_t invocations = // Count the shader invocations in one local work group.
3238            detail::checked_product(detail::checked_product(l[0], l[1]), l[2]); // Reject resource-size multiplication that would overflow.
3239        if (invocations > state->max_invocations) // Choose this branch when invocations > state->max invocations.
3240            throw error("local invocation count exceeds device limit"); // Report local invocation count exceeds device limit.
3241        prepare(*d); // Compile the program and prepare its bound GPU resources.
3242        state->gl.UseProgram(program_->id); // Select the compute program for the next dispatch.
3243        for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
3244            ports_[i]->bind_gpu(*state, program_->id); // Bind this interface or assign its uniform before dispatch.
3245        state->gl.check("bind shader " + name_); // Keep the kernel or registration name.
3246        state->gl.DispatchCompute(groups.x, groups.y, groups.z); // Queue the shader workgroups.
3247        state->gl.MemoryBarrier(detail::ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
3248 // Conservatively record GPU authority even if an error follows a submitted dispatch.
3249        for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3250            outputs[i]->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
3251        state->gl.check("dispatch shader " + name_); // Keep the kernel or registration name.
3252    } else { // Handle the alternative resource or completion case.
3253        for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3254            std::shared_ptr<detail::resource_state> r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3255            if (r) // Choose this branch when r.
3256                r->ensure_host(); // Download newer GPU values only when host access needs them.
3257        } // End this scope in runtime.
3258        gl_NumWorkGroups = glsl::uvec3(groups.x, groups.y, groups.z); // Publish the dispatch dimensions to CPU shader builtins.
3259        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3260            for (unsigned gz = 0; gz < groups.z; ++gz) // Visit this axis of the dispatch or current workgroup.
3261                for (unsigned gy = 0; gy < groups.y; ++gy) // Visit this axis of the dispatch or current workgroup.
3262                    for (unsigned gx = 0; gx < groups.x; ++gx) { // Visit this axis of the dispatch or current workgroup.
3263                        gl_WorkGroupID = glsl::uvec3(gx, gy, gz); // Publish the CPU work group currently being executed.
3264                        for (unsigned z = 0; z < local_.z; ++z) // Visit this axis of the dispatch or current workgroup.
3265                            for (unsigned y = 0; y < local_.y; ++y) // Visit this axis of the dispatch or current workgroup.
3266                                for (unsigned x = 0; x < local_.x; ++x) { // Visit this axis of the dispatch or current workgroup.
3267                                    gl_LocalInvocationID = glsl::uvec3(x, y, z); // Publish the invocation coordinates inside this work group.
3268                                    gl_GlobalInvocationID = glsl::uvec3( // Combine work group and local coordinates into global indices.
3269                                        gx * local_.x + x, gy * local_.y + y, gz * local_.z + z); // Use the local size to place this invocation in the complete dispatch.
3270                                    gl_LocalInvocationIndex = (z * local_.y + y) * local_.x + x; // Flatten the local coordinates with X changing fastest.
3271                                    main(); // Execute the shader with all CPU invocation builtins initialized.
3272                                } // End this scope in runtime.
3273                    } // End this scope in runtime.
3274        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3275            for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3276                outputs[i]->latest = detail::authority::host; // Record which backend now owns the newest resource values.
3277            throw; // Rethrow the original failure after arranging the necessary cleanup.
3278        } // End this scope in runtime.
3279        for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3280            outputs[i]->latest = detail::authority::host; // Record which backend now owns the newest resource values.
3281    } // End this scope in runtime.
3282} // End this scope in runtime.
3283
3284/** @brief One dispatch retaining a reference to its shader. Keep that shader alive during execution. */
3285struct stage { // Keep the stage values and operations together.
3286    kernel* shader; // Keep the shader used by this dispatch.
3287    extent groups; // Keep the number of workgroups to dispatch.
3288    backend target; // Keep the chosen CPU or GPU backend.
3289    std::shared_ptr<kernel> owner; // Retain an owned kernel while this stage uses it.
3290    /** @brief Retain a kernel reference with workgroup counts and a backend override. */
3291    stage(kernel& k, extent g, backend b) : shader(&k), groups(g), target(b) { // Keep the shader reference, work group counts and backend choice.
3292    } // End this scope in runtime.
3293    stage(std::shared_ptr<kernel> k, extent g, backend b) // Keep the shader reference, work group counts and backend choice.
3294        : shader(k.get()), groups(g), target(b), owner(k) { // Retain the kernel owner together with dispatch dimensions and backend choice.
3295        if (!shader) // Require a retained kernel for this dispatch.
3296            throw error("cannot dispatch a null shader"); // Require a valid kernel for this dispatch.
3297    } // End this scope in runtime.
3298}; // End this scope in runtime.
3299/** @brief Build a dispatch using work group counts, with an optional per-stage backend override. */
3300inline stage dispatch(kernel& shader, extent groups, backend b = backend::automatic) { // Build one ordered dispatch with the requested backend choice.
3301    return stage(shader, groups, b); // Return the result of this check or operation.
3302} // End this scope in runtime.
3303/** @brief Build a dispatch that also retains ownership of its shader. */
3304inline stage // Return a dispatch value that retains its shader owner.
3305dispatch(std::shared_ptr<kernel> shader, extent groups, backend b = backend::automatic) { // Build one ordered dispatch with the requested backend choice.
3306    return stage(shader, groups, b); // Return the result of this check or operation.
3307} // End this scope in runtime.
3308
3309class submission; // Keep the submission values and operations together.
3310
3311/** @brief An ordered pipeline, composed with >> or +=. Resources link stages by shared storage.
3312 * GPU stages issue memory barriers. CPU/GPU transitions transfer authoritative resource contents.
3313 * Running again observes updated uniforms and resource bindings. CPU execution
3314 * completes each stage before returning. GPU execution queues stages in order.
3315 * Request host data or use an explicit wait to observe GPU completion.
3316 */
3317class pipeline { // Keep the pipeline values and operations together.
3318    std::vector<stage> stages_; // Keep the dispatches in execution order.
3319    void execute(device* d) const { // Run stages in order while honoring their backend choices.
3320        for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3321            const stage& s = stages_[i]; // Inspect the next dispatch, its dimensions and backend choice.
3322            if (s.target == backend::gpu && !d) // Require a device for an explicitly GPU stage.
3323                throw error("GPU stage requires a device"); // Report gpu stage requires a device.
3324            s.shader->run(s.groups, s.target == backend::cpu ? 0 : d); // Dispatch this stage on its selected CPU or GPU backend.
3325        } // End this scope in execute.
3326    } // End this scope in execute.
3327
3328  public: // Expose the operations callers can use.
3329    /** @brief Construct an empty pipeline. append dispatches with operator+=. */
3330    pipeline() { // Create the ordered dispatch container.
3331    } // End this scope in runtime.
3332    /** @brief Construct a pipeline containing one dispatch. */
3333    pipeline(stage s) { // Create a pipeline containing this initial dispatch.
3334        stages_.push_back(s); // Keep this dispatch at the end of the processing order.
3335    } // End this scope in runtime.
3336    /** @brief Append a dispatch in execution order and return this pipeline. */
3337    pipeline& operator+=(stage s) { // Append one dispatch while retaining its optional kernel owner.
3338        stages_.push_back(s); // Keep this dispatch at the end of the processing order.
3339        return *this; // Allow another operation to follow in the same expression.
3340    } // End this scope in runtime.
3341    /** @brief Append every dispatch from another pipeline, including a safe copy of this pipeline. */
3342    pipeline& operator+=(const pipeline& other) { // Compose complete processing blocks in their original stage order.
3343        const std::vector<stage> additions(other.stages_); // Preserve the source range before self-append can reallocate it.
3344        stages_.insert(stages_.end(), additions.begin(), additions.end()); // Retain each dispatch's kernel ownership and backend choice.
3345        return *this; // Allow another stage or pipeline to follow in the same expression.
3346    } // Appending copies dispatch references and preserves the stages for later execution.
3347    /** @brief Return the number of stages. */
3348    std::size_t size() const { // Read the stored element or stage count.
3349        return stages_.size(); // Return the result of this check or operation.
3350    } // End this scope in runtime.
3351    /** @brief Run automatic and CPU stages on the CPU. explicit GPU stages need a device. */
3352    void run() const { // Execute the pipeline using the selected CPU or GPU backend.
3353        execute(0); // Run stages in order while honoring their backend choices.
3354    } // End this scope in runtime.
3355    /** @brief Run automatic and GPU stages on the device, respecting explicit CPU stages.
3356     * Host readback completes queued GPU writes when resource data is requested.
3357     */
3358    void run(device& d) const { // Execute the pipeline using the selected CPU or GPU backend.
3359        execute(&d); // Run stages in order while honoring their backend choices.
3360    } // End this scope in runtime.
3361    /** @brief Compile GPU programs and upload resources before steady-state submission. */
3362    void prepare(device& d) const { // Compile the program and prepare its bound GPU resources.
3363        for (std::size_t i = 0; i < stages_.size(); ++i) // Visit every dispatch in processing order.
3364            if (stages_[i].target != backend::cpu) // Precompile and upload stages that can execute on the GPU.
3365                stages_[i].shader->prepare(d); // Compile the program and prepare its bound GPU resources.
3366    } // End this scope in prepare.
3367    /** @brief Enqueue GPU stages and return a fence for zero-timeout completion polls. */
3368    submission submit(device& d) const; // Queue compute work and return its completion handle.
3369    /** @internal Access dispatches for submission and snapshot handling. */
3370    const std::vector<stage>& stages() const { // Expose the ordered dispatches for submission and snapshot handling.
3371        return stages_; // Return the dispatches in execution order.
3372    } // End this scope in runtime.
3373    /** @brief Snapshot shader instances, uniforms and bindings for deferred CPU execution. */
3374    pipeline snapshot() const { // Clone kernels and retain the current binding and uniform values.
3375        pipeline result; // Keep the value returned by this operation.
3376        std::map<kernel*, std::shared_ptr<kernel>> copies; // Keep the shader clones reused by repeated stages.
3377        for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3378            const stage& s = stages_[i]; // Inspect the next dispatch, its dimensions and backend choice.
3379            auto& copy = copies[s.shader]; // Reuse one clone for every occurrence of the same source kernel.
3380            if (!copy) // Create a clone only on the source kernel's first occurrence.
3381                copy = std::shared_ptr<kernel>(s.shader->clone().release()); // Own an isolated clone of this kernel's current interfaces.
3382            result += stage(copy, s.groups, s.target); // Retain the cloned kernel with its original dimensions and backend choice.
3383        } // End this scope in snapshot.
3384        return result; // Return the value returned by this operation.
3385    } // End this scope in snapshot.
3386    /** @brief Validate CPU execution support and current host data for a deferred job. */
3387    void require_host_ready() const { // Validate CPU stages and host-ready resources.
3388        for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3389            if (stages_[i].target == backend::gpu) // Reject GPU-only stages before submitting work to a CPU worker.
3390                throw error("CPU executor cannot execute a GPU-only stage"); // Require CPU-compatible stages for the CPU executor.
3391            auto resources = stages_[i].shader->resources(); // Inspect the resources bound to this stage.
3392            for (std::size_t r = 0; r < resources.size(); ++r) // Check every bound resource for data requiring GPU readback.
3393                if (resources[r]->latest == detail::authority::gpu) // Require the caller to download newer GPU contents on the context thread.
3394                    throw error( // Report the invalid operation.
3395                        "download GPU data on its context thread before submitting CPU work"); // Explain how to make this resource ready for CPU execution.
3396        } // End this scope in require host ready.
3397    } // End this scope in require host ready.
3398}; // End this scope in runtime.
3399/** @brief Compose ordered stages into a reusable pipeline. */
3400inline pipeline operator>>(stage a, stage b) { // Compose these dispatches in their execution order.
3401    pipeline p(a); // Start the pipeline with the first dispatch.
3402    p += b; // Append the following dispatch to the ordered pipeline.
3403    return p; // Return the composed pipeline for later execution.
3404} // End this scope in runtime.
3405/** @brief Append a stage to a pipeline value, retaining references to the same kernels. */
3406inline pipeline operator>>(pipeline p, stage b) { // Compose these dispatches in their execution order.
3407    p += b; // Append the following dispatch to the ordered pipeline.
3408    return p; // Return the composed pipeline for later execution.
3409} // End this scope in runtime.
3410/** @brief Prepend a stage to a pipeline while retaining the same linked shader resources. */
3411inline pipeline operator>>(stage a, const pipeline& b) { // Place the independent dispatch before all existing processing stages.
3412    pipeline result(a); // Start with the supplied dispatch and its retained kernel owner.
3413    result += b; // Append the complete processing block in its original order.
3414    return result; // Return the reusable pipeline for later execution.
3415} // The source pipeline remains available for further composition or execution.
3416/** @brief Join two complete processing pipelines in execution order. */
3417inline pipeline operator>>(pipeline a, const pipeline& b) { // Compose reusable algorithm blocks with ordinary shader dispatches.
3418    a += b; // Append a copy of the second block's dispatch references.
3419    return a; // Return the combined ordered processing plan.
3420} // Resource sharing follows the same rules as individual stage composition.
3421
3422namespace detail { // Group these definitions in the detail namespace.
3423typedef kernel* (*kernel_factory)(); // Name the representation used by this GL or shader interface.
3424inline std::map<std::string, std::vector<kernel_factory>>& shader_registry() { // Share the compiled shader factories discovered during startup.
3425    static std::map<std::string, std::vector<kernel_factory>> registry; // Keep the shared display lifetime registry.
3426    return registry; // Return the shared display lifetime registry.
3427} // End this scope in shader registry.
3428 // Generated shader translation units register factories directly in their target.
3429 // Unregistering makes plugin unload safe for future lookups. existing shader objects
3430 // still require the plugin to stay loaded through destruction.
3431class shader_registration { // Keep the shader registration values and operations together.
3432    std::string name_; // Keep the kernel or registration name.
3433    kernel_factory factory_; // Keep the compiled shader construction callback.
3434
3435  public: // Expose the operations callers can use.
3436    shader_registration(const char* name, kernel_factory factory) : name_(name), factory_(factory) { // Keep the callback used to create a registered shader.
3437        shader_registry()[name_].push_back(factory_); // Retain this entry in the ordered resource or work collection.
3438    } // End this scope in runtime.
3439    ~shader_registration() { // Unregister this factory before its dynamic module is unloaded.
3440        std::vector<kernel_factory>& entries = shader_registry()[name_]; // Find the registered factories using this shader name.
3441        const std::vector<kernel_factory>::iterator it = // Find this module's factory among the registrations.
3442            std::find(entries.begin(), entries.end(), factory_); // Keep the compiled shader construction callback.
3443        if (it != entries.end()) // Choose this branch when it differs from entries.end().
3444            entries.erase(it); // Remove this module's registration and preserve the other factories.
3445        if (entries.empty()) // Choose this branch when entries.empty().
3446            shader_registry().erase(name_); // Share the compiled shader factories discovered during startup.
3447    } // End this scope in runtime.
3448    shader_registration(const shader_registration&) = delete; // Prevent copying this object and duplicating its retained identity.
3449    shader_registration& operator=(const shader_registration&) = delete; // Prevent copying this object and duplicating its retained identity.
3450}; // End this scope in runtime.
3451} // namespace detail
3452
3453/** @brief Create a shader compiled and embedded by shdr_target_shaders during the CMake build.
3454 * A file named scale.cpp registers scale_kernel. The returned instance owns its CPU/GPU program
3455 * and exposes resource binding through bind() and set(). Both programs are part of the binary.
3456 * Unknown or ambiguous names throw error. Call from one application thread after startup.
3457 */
3458inline std::unique_ptr<kernel> make_kernel(const std::string& name) { // Create one automatically registered shader by its build-time name.
3459    const std::map<std::string, std::vector<detail::kernel_factory>>& registry = // Set the shared display lifetime registry.
3460        detail::shader_registry(); // Share the compiled shader factories discovered during startup.
3461    const std::map<std::string, std::vector<detail::kernel_factory>>::const_iterator it = // Find the unique compiled factory requested by the application.
3462        registry.find(name); // Keep the resource or entry-point name.
3463    if (it == registry.end()) // Choose this branch when it equals registry.end().
3464        throw error("unknown compiled shader: " + name); // Report unknown compiled shader: .
3465    if (it->second.size() != 1) // Check resource size or driver limits before accessing storage.
3466        throw error("ambiguous compiled shader name: " + name); // Report ambiguous compiled shader name: .
3467    return std::unique_ptr<kernel>(it->second.front()()); // Create one automatically registered shader by its build-time name.
3468} // End this scope in make kernel.
3469} // namespace shdr
3470
3471 // A short namespace alias keeps host-side mathematical expressions readable.
3472namespace glsl = shdr::glsl; // Group these definitions in the glsl namespace.
3473#endif // SHDR_RUNTIME_HPP
3474
3475// ---- async.hpp ----
3476/** @file async.hpp
3477 * @brief Nonblocking GPU completion handles and bounded CPU work queues.
3478 * Prepare GPU pipelines before a hot loop, keep a ring of independent resource
3479 * sets, and poll completion before reading or recycling a result. GPU calls
3480 * use the device's context thread. CPU workers execute independent snapshots
3481 * and require host-ready resources. Complete GPU readback on the context thread
3482 * before submitting a CPU job.
3483 */
3484#ifndef SHDR_ASYNC_HPP // Skip this section if it was already included.
3485#define SHDR_ASYNC_HPP /* Mark this section as included. */
3486#ifndef SHDR_RUNTIME_HPP // Skip this section if it was already included.
3487#include "math.hpp" // Use the portable GLSL scalar, vector, and matrix types.
3488#include "runtime.hpp" // Use the kernel, resource, and ordered pipeline definitions.
3489#endif // Finish this conditional section.
3490#include <chrono> // Express explicit waits and zero-time completion polls.
3491#include <condition_variable> // Wake CPU workers when jobs arrive or shutdown begins.
3492#include <deque> // Keep pending CPU jobs in submission order.
3493#include <exception> // Pass worker failures back through completion futures.
3494#include <future> // Give callers a completion result for each CPU job.
3495#include <mutex> // Protect shared work queues and deferred deletion.
3496#include <thread> // Track the context thread and start CPU workers.
3497#include <utility> // Move job and resource ownership between runtime objects.
3498
3499namespace shdr { // Group these definitions in the shdr namespace.
3500
3501/** @brief Result of a completion query: completed work or an expired timeout. */
3502enum class wait_status { ready, timeout }; // Name the two outcomes of a GPU completion query.
3503
3504namespace detail { // Group these definitions in the detail namespace.
3505struct submission_resources { // Keep the submission resources values and operations together.
3506    std::vector<std::shared_ptr<resource_state>> resources; // Keep the resource storage retained until queued work completes.
3507    std::vector<std::shared_ptr<program_state>> programs; // Keep the compiled programs retained by a submission.
3508}; // End this scope in async.
3509
3510struct submission_state { // Keep a GPU fence and its resources alive until retirement.
3511    std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
3512    GLsync fence; // Keep the GL completion fence.
3513    std::shared_ptr<submission_resources> retained; // Keep the submission resource bundle.
3514    bool completed; // Cache whether this submission fence has already signaled.
3515    explicit submission_state(const std::shared_ptr<device_state>& d) // Retain the device, fence, and queued resource bundle.
3516        : owner(d), fence(0), retained(std::make_shared<submission_resources>()), completed(false) { // Retain the device and create an empty pending-completion resource bundle.
3517    } // End this scope in submission state.
3518    ~submission_state() noexcept { // Retire completed fences and defer pending fence cleanup.
3519        if (!fence) // Finish immediately for an empty fence.
3520            return; // Finish this operation.
3521        const GLsync sync = fence; // Copy the fence handle into the deferred cleanup callback.
3522        const std::shared_ptr<submission_resources> keep = retained; // Retain buffers and programs until deferred cleanup releases this bundle.
3523        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3524            if (completed) { // Retire a fence whose completion has already been observed.
3525                owner->retire([sync, keep](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
3526                    gl.DeleteSync(sync); // Delete the GL completion fence.
3527                    (void)keep; // Keep the resource references captured for this cleanup.
3528                }); // End this scope in submission state.
3529            } else { // Handle the alternative resource or completion case.
3530 // The context thread checks this retirement entry with a zero timeout.
3531                owner->defer_poll( // Retain a completion check until its fence signals.
3532                    [sync, keep](gl_api& gl) -> bool { // Retain these captures until the queued callback finishes.
3533                        const GLenum status = gl.ClientWaitSync(sync, 0, 0); // Poll the discarded fence with zero flags and a zero timeout.
3534                        if (status == TIMEOUT_EXPIRED) // Check the driver result before marking GPU completion.
3535                            return false; // Keep the discarded submission pending while its fence is unsignaled.
3536                        gl.DeleteSync(sync); // Delete the GL completion fence.
3537                        (void)keep; // Keep the resource references captured for this cleanup.
3538                        return true; // Remove the retired fence and release its retained resource bundle.
3539                    }, // End this scope in submission state.
3540                    [sync](gl_api& gl) { // Keep only the fence handle for nonblocking shutdown cancellation.
3541                        gl.DeleteSync(sync); // Delete the GL completion fence.
3542                    }); // End this scope in submission state.
3543            } // End this scope in submission state.
3544        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3545 // Destruction defers pending fence cleanup. GL command references keep
3546 // already queued operations valid if allocating a retirement entry fails.
3547        } // End this scope in submission state.
3548    } // End this scope in submission state.
3549    wait_status query(GLuint64 timeout) { // Check completion with the requested driver timeout.
3550        owner->require_thread(); // Require the device context thread and activate its headless context.
3551        if (completed) // Reuse the cached completion result after checking the context thread.
3552            return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3553        const GLenum result = owner->gl.ClientWaitSync(fence, 0, timeout); // Check a GPU fence with the caller-selected timeout.
3554        if (result == ALREADY_SIGNALED || result == CONDITION_SATISFIED) { // Check the driver result before marking GPU completion.
3555            completed = true; // Set whether the GPU fence has already signaled.
3556            return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3557        } // End this scope in query.
3558        if (result == TIMEOUT_EXPIRED) // Check the driver result before marking GPU completion.
3559            return wait_status::timeout; // Tell the caller that the explicit wait expired before completion.
3560        owner->gl.check("query GPU submission"); // Check for a driver error from the preceding GL operation.
3561        throw error("GPU completion query failed"); // Report gpu completion query failed.
3562    } // End this scope in query.
3563}; // End this scope in async.
3564} // namespace detail
3565
3566/** @brief A movable handle for one queued GPU pipeline.
3567 * ready() performs a zero-timeout fence query. wait(timeout) bounds the requested
3568 * driver wait. wait() explicitly waits for completion. Destroying a handle
3569 * schedules pending fence and resource cleanup on the device context thread.
3570 * Device garbage collection releases those retained resources after completion.
3571 * Keep the GL context alive until retained work and resources have been retired.
3572 */
3573class submission { // Keep the submission values and operations together.
3574    std::unique_ptr<detail::submission_state> state_; // Own this completion handle and its retained GPU resources.
3575    explicit submission(std::unique_ptr<detail::submission_state> state) // Accept sole ownership of this fence and its retained resource bundle.
3576        : state_(std::move(state)) { // Move the fence state into this completion handle.
3577    } // End this scope in async.
3578    friend class pipeline; // Allow the related pipeline or resource helper to access this retained state.
3579
3580  public: // Expose the operations callers can use.
3581    /** @brief Construct an empty, already-complete handle. */
3582    submission() { // Create an empty handle that is already complete.
3583    } // End this scope in async.
3584    submission(submission&&) noexcept = default; // Move the completion state into the new handle.
3585    submission& operator=(submission&&) noexcept = default; // Retire the old handle and move in the new completion state.
3586    submission(const submission&) = delete; // Prevent copying this object and duplicating its retained identity.
3587    submission& operator=(const submission&) = delete; // Prevent copying this object and duplicating its retained identity.
3588    /** @brief Return whether this handle represents submitted GPU commands. */
3589    bool valid() const { // Check whether this handle represents actual submitted GPU work.
3590        return bool(state_); // Return whether this handle retains a submission state.
3591    } // End this scope in async.
3592    /** @brief Query completion with a zero timeout on the device context thread. */
3593    bool ready() { // Check whether queued work has completed using a zero-timeout poll.
3594        return !state_ || state_->query(0) == wait_status::ready; // Check whether queued work has completed using a zero-timeout poll.
3595    } // End this scope in ready.
3596    /** @brief Request a driver wait with a nonnegative timeout in nanoseconds. */
3597    wait_status wait(std::chrono::nanoseconds timeout) { // Apply the explicit completion wait selected by the caller.
3598        if (timeout.count() < 0) // Require a nonnegative wait duration.
3599            throw error("GPU submission timeout must be nonnegative"); // Report gpu submission timeout must be nonnegative.
3600        if (!state_) // Treat an empty handle as already completed.
3601            return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3602        return state_->query(static_cast<detail::GLuint64>(timeout.count())); // Apply the explicit completion wait selected by the caller.
3603    } // End this scope in wait.
3604    /** @brief Explicitly wait until submitted commands complete. */
3605    wait_status wait() { // Apply the explicit completion wait selected by the caller.
3606        if (!state_) // Treat an empty handle as already completed.
3607            return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3608        while (state_->query((std::numeric_limits<detail::GLuint64>::max)()) == // Use the caller's explicit blocking wait until the fence completes.
3609               wait_status::timeout) { // Repeat only if the implementation still reports an incomplete wait.
3610        } // End this scope in wait.
3611        return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3612    } // End this scope in wait.
3613}; // End this scope in async.
3614
3615/** @brief Enqueue all GPU stages and return a fence for polling or explicit waits.
3616 * Each stage must support GPU execution. Call prepare()
3617 * before entering a latency-sensitive loop to compile shaders and allocate/upload
3618 * resources in advance. Subsequent host edits can still require an upload.
3619 * Uniform and binding changes after return affect subsequent submissions.
3620 */
3621inline submission pipeline::submit(device& d) const { // Queue compute work and return its completion handle.
3622    d.state()->require_thread(); // Require the device context thread and activate its headless context.
3623    const std::vector<stage>& commands = stages(); // Read the ordered stages that this submission will queue.
3624    for (std::size_t i = 0; i < commands.size(); ++i) // Visit each ordered GPU stage in this submission.
3625        if (commands[i].target == backend::cpu) // Reject explicit CPU stages before queueing any GPU commands.
3626            throw error("GPU submission cannot contain CPU stages"); // Require GPU stages for GPU submission.
3627    if (commands.empty()) // Skip fence creation for an empty pipeline.
3628        return submission(); // Represent an empty pipeline with an already completed handle.
3629    std::unique_ptr<detail::submission_state> completion(new detail::submission_state(d.state())); // Retain the device, fence, and queued resource bundle.
3630    completion->retained->programs.reserve(commands.size()); // Reserve room to retain one compiled program per stage.
3631    prepare(d); // Compile the program and prepare its bound GPU resources.
3632    for (std::size_t i = 0; i < commands.size(); ++i) { // Visit each ordered GPU stage in this submission.
3633        const std::vector<std::shared_ptr<detail::resource_state>> resources = // Set the resource storage retained until queued work completes.
3634            commands[i].shader->resources(); // Collect the shared storage used by this shader.
3635        completion->retained->resources.insert( // Retain this entry in the ordered resource or work collection.
3636            completion->retained->resources.end(), resources.begin(), resources.end()); // Keep the end of the current range.
3637        completion->retained->programs.push_back(commands[i].shader->program_state()); // Retain this entry in the ordered resource or work collection.
3638    } // End this scope in submit.
3639    try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3640        run(d); // Queue all validated GPU stages in pipeline order.
3641    } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3642 // A later dispatch can fail after an earlier dispatch was queued.
3643        completion->fence = d.state()->gl.FenceSync(detail::SYNC_GPU_COMMANDS_COMPLETE, 0); // Insert a completion fence after queued compute work.
3644        d.state()->gl.Flush(); // Flush queued GPU commands for driver execution.
3645        throw; // Rethrow the original failure after arranging the necessary cleanup.
3646    } // End this scope in submit.
3647    completion->fence = d.state()->gl.FenceSync(detail::SYNC_GPU_COMMANDS_COMPLETE, 0); // Insert a completion fence after queued compute work.
3648    if (!completion->fence) { // Check that the driver allocated a valid completion fence.
3649        d.state()->gl.check("create GPU submission fence"); // Expose retained runtime state to the resource and backend helpers.
3650        throw error("cannot create GPU submission fence"); // Report completion-fence allocation failure.
3651    } // End this scope in submit.
3652    d.state()->gl.Flush(); // Flush queued GPU commands for driver execution.
3653    d.state()->gl.check("submit GPU pipeline"); // Expose retained runtime state to the resource and backend helpers.
3654    return submission(std::move(completion)); // Queue compute work and return its completion handle.
3655} // End this scope in submit.
3656
3657/** @brief A bounded CPU executor for independent pipeline jobs.
3658 * Each submit() snapshots kernels, uniforms and resource bindings. Snapshots
3659 * have independent invocation state, while buffers and images retain shared
3660 * storage. Give concurrent jobs distinct writable resources, such as ring slots.
3661 * Queue saturation throws immediately. Futures report results or exceptions.
3662 * Destroying a future releases its result handle, while the executor retains
3663 * the job until completion. shutdown() drains accepted jobs and joins workers.
3664 * Executor destruction also drains and joins them.
3665 */
3666class executor { // Keep the executor values and operations together.
3667    struct job { // Keep the job values and operations together.
3668        std::function<void()> function; // Keep the application function executed by a CPU worker.
3669        std::promise<void> completion; // Keep the completion result that the caller will receive.
3670        explicit job(const std::function<void()>& fn) : function(fn) { // Keep the accepted CPU function and its promise result.
3671        } // End this scope in async.
3672    }; // End this scope in async.
3673    struct queue_state { // Share the bounded queue between its producer and workers.
3674        std::mutex mutex; // Keep the lock protecting shared state.
3675        std::condition_variable changed; // Wake sleeping workers when work or shutdown state changes.
3676        std::deque<std::shared_ptr<job>> jobs; // Keep accepted CPU work awaiting an available worker.
3677        std::vector<std::thread::id> worker_ids; // Keep the worker thread identifiers used to reject self-joining.
3678        std::size_t pending, capacity; // Keep the current pending count and the maximum queue size.
3679        bool closing; // Keep whether the CPU executor is draining for shutdown.
3680        explicit queue_state(std::size_t n) : pending(0), capacity(n), closing(false) { // Start an empty queue with the chosen pending-job capacity.
3681        } // End this scope in async.
3682    }; // End this scope in async.
3683    std::shared_ptr<queue_state> state_; // Share the bounded queue between the executor and its workers.
3684    std::vector<std::thread> workers_; // Keep the threads that execute accepted CPU jobs.
3685    std::mutex shutdown_mutex_; // Keep the lock that serializes executor shutdown.
3686
3687    static void consume(const std::shared_ptr<queue_state>& state) { // Take accepted jobs from the queue and execute them on this worker.
3688        for (;;) { // Keep this worker available until its queue is drained for shutdown.
3689            std::shared_ptr<job> next; // Keep the CPU job selected by this worker.
3690            { // Begin the protected scope for this operation.
3691                std::unique_lock<std::mutex> lock(state->mutex); // Hold the mutex while this shared state is accessed.
3692                state->changed.wait(lock, [&] { // Release the queue lock while sleeping until work or shutdown arrives.
3693                    return state->closing || !state->jobs.empty(); // Wake the worker for a queued job or an explicit shutdown.
3694                }); // End this scope in consume.
3695                if (state->jobs.empty()) // Exit only when shutdown has awakened an empty queue.
3696                    return; // Finish this operation.
3697                next = state->jobs.front(); // Set the CPU job selected by this worker.
3698                state->jobs.pop_front(); // Remove this accepted job from the pending queue.
3699                --state->pending; // Release its pending slot before executing the job.
3700            } // End this scope in consume.
3701            try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3702                next->function(); // Execute the selected application function or CPU pipeline snapshot.
3703                next->function = std::function<void()>(); // Release kernel and resource captures before publishing completion.
3704                next->completion.set_value(); // Publish successful completion after the job releases its captures.
3705            } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3706                const std::exception_ptr failure = std::current_exception(); // Set the exception captured from a CPU job.
3707                next->function = std::function<void()>(); // Release kernel and resource captures before publishing completion.
3708                next->completion.set_exception(failure); // Deliver the worker failure through the caller completion future.
3709            } // End this scope in consume.
3710        } // End this scope in consume.
3711    } // End this scope in consume.
3712    void reserve() { // Reserve capacity and report a full queue immediately.
3713        std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3714        if (state_->closing) // Check the queue state before accepting or executing work.
3715            throw error("CPU executor is shut down"); // Report cpu executor is shut down.
3716        if (state_->pending == state_->capacity) // Check the queue state before accepting or executing work.
3717            throw error("CPU executor queue is full"); // Report cpu executor queue is full.
3718        ++state_->pending; // Count the accepted job against the pending queue capacity.
3719    } // End this scope in reserve.
3720    void abandon() noexcept { // Release the reserved slot after a submission failure.
3721        std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3722        --state_->pending; // Return the queue slot reserved by an unsuccessful submission.
3723    } // End this scope in abandon.
3724    std::future<void> append_reserved(const std::function<void()>& function) { // Attach the accepted CPU job to its reserved queue slot.
3725        std::shared_ptr<job> work(new job(function)); // Keep the application function executed by a CPU worker.
3726        std::future<void> result = work->completion.get_future(); // Set the value returned by this operation.
3727        { // Begin the protected scope for this operation.
3728            std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3729            if (state_->closing) // Check the queue state before accepting or executing work.
3730                throw error("CPU executor is shut down"); // Report cpu executor is shut down.
3731            state_->jobs.push_back(work); // Retain this entry in the ordered resource or work collection.
3732        } // End this scope in append reserved.
3733        state_->changed.notify_one(); // Wake workers so they can observe new queue or shutdown state.
3734        return result; // Return the value returned by this operation.
3735    } // End this scope in append reserved.
3736
3737  public: // Expose the operations callers can use.
3738    /** @brief Start workers with room for at most capacity pending jobs.
3739     * Capacity counts jobs waiting for a worker. Both arguments must be positive.
3740     */
3741    explicit executor(std::size_t workers = 1, std::size_t capacity = 64) // Start a fixed number of workers with a bounded pending-job queue.
3742        : state_(std::make_shared<queue_state>(capacity)) { // Keep the maximum number of pending CPU jobs.
3743        if (!workers || !capacity) // Require positive worker and queue counts.
3744            throw error("CPU executor requires positive worker and queue counts"); // Report cpu executor requires positive worker and queue counts.
3745        workers_.reserve(workers); // Allocate space for every worker thread handle.
3746        state_->worker_ids.reserve(workers); // Allocate space for every worker thread identifier.
3747        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3748            for (std::size_t i = 0; i < workers; ++i) { // Visit this axis of the dispatch or current workgroup.
3749                const std::shared_ptr<queue_state> state = state_; // Set the shared device or worker state.
3750                workers_.push_back(std::thread([state] { // Retain this entry in the ordered resource or work collection.
3751                    consume(state); // Take accepted jobs from the queue and execute them on this worker.
3752                })); // End this scope in executor.
3753                state_->worker_ids.push_back(workers_.back().get_id()); // Retain this entry in the ordered resource or work collection.
3754            } // End this scope in executor.
3755        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3756            shutdown(); // Drain accepted CPU work and join the workers from an application thread.
3757            throw; // Rethrow the original failure after arranging the necessary cleanup.
3758        } // End this scope in executor.
3759    } // End this scope in executor.
3760    ~executor() { // Drain accepted work and join the CPU workers at explicit pool teardown.
3761        shutdown(); // Drain accepted CPU work and join the workers from an application thread.
3762    } // End this scope in executor.
3763    executor(const executor&) = delete; // Prevent copying this object and duplicating its retained identity.
3764    executor& operator=(const executor&) = delete; // Prevent copying this object and duplicating its retained identity.
3765    /** @brief Snapshot a host-ready CPU pipeline, enqueue it and return a future.
3766     * Each stage must support CPU execution and have current host data.
3767     */
3768    std::future<void> submit(const pipeline& source) { // Queue compute work and return its completion handle.
3769        reserve(); // Reserve capacity and report a full queue immediately.
3770        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3771            source.require_host_ready(); // Validate CPU stages and host-ready resources before queueing.
3772            const pipeline copy = source.snapshot(); // Capture isolated kernel interfaces and the current bindings and uniforms.
3773            return append_reserved([copy] { // Queue compute work and return its completion handle.
3774                copy.run(); // Execute the retained CPU snapshot on its worker thread.
3775            }); // End this scope in submit.
3776        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3777            abandon(); // Release the reserved slot after a submission failure.
3778            throw; // Rethrow the original failure after arranging the necessary cleanup.
3779        } // End this scope in submit.
3780    } // End this scope in submit.
3781    /** @brief Enqueue an application CPU function on the same bounded queue.
3782     * Run host operations in the callback and keep device operations on their context thread.
3783     */
3784    template <class Function> std::future<void> enqueue(Function function) { // Select the scalar, dimension, or access type at compile time.
3785        reserve(); // Reserve capacity and report a full queue immediately.
3786        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3787            return append_reserved(std::function<void()>(function)); // Queue the application callback on the bounded CPU executor.
3788        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3789            abandon(); // Release the reserved slot after a submission failure.
3790            throw; // Rethrow the original failure after arranging the necessary cleanup.
3791        } // End this scope in enqueue.
3792    } // End this scope in enqueue.
3793    /** @brief Return the count of queued or currently being constructed jobs. */
3794    std::size_t pending() const { // Read the count of jobs waiting for a worker.
3795        std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3796        return state_->pending; // Read the count of jobs waiting for a worker.
3797    } // End this scope in pending.
3798    /** @brief Return the maximum number of pending jobs. */
3799    std::size_t capacity() const { // Return the configured pending-job limit.
3800        return state_->capacity; // Return the configured pending-job limit.
3801    } // End this scope in capacity.
3802    /** @brief Return the number of worker threads. */
3803    std::size_t workers() const { // Return the number of worker threads.
3804        return workers_.size(); // Return the number of worker threads.
3805    } // End this scope in workers.
3806    /** @brief Drain accepted jobs and join all workers. later submissions fail.
3807     * Call from an application thread so it can join every worker.
3808     */
3809    void shutdown() { // Drain accepted CPU work and join the workers from an application thread.
3810        if (std::find(state_->worker_ids.begin(), // Choose this branch when std::find(state ->worker ids.begin(),.
3811                      state_->worker_ids.end(), // Keep the end of the current range.
3812                      std::this_thread::get_id()) != state_->worker_ids.end()) // Reject joining the current executor worker from its own job.
3813            throw error("CPU executor shutdown requires an application thread"); // Report cpu executor shutdown requires an application thread.
3814        std::lock_guard<std::mutex> lifecycle(shutdown_mutex_); // Hold the mutex while this shared state is accessed.
3815        { // Begin the protected scope for this operation.
3816            std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3817            state_->closing = true; // Set whether the CPU executor is draining for shutdown.
3818        } // End this scope in shutdown.
3819        state_->changed.notify_all(); // Wake workers so they can observe new queue or shutdown state.
3820        for (std::size_t i = 0; i < workers_.size(); ++i) // Visit each CPU worker during lifecycle handling.
3821            if (workers_[i].joinable()) // Choose this branch when workers [i].joinable().
3822                workers_[i].join(); // Join this CPU worker after accepted work has drained.
3823    } // End this scope in shutdown.
3824}; // End this scope in async.
3825} // namespace shdr
3826#endif // SHDR_ASYNC_HPP
3827
3828// ---- egl.hpp ----
3829#ifndef SHDR_EGL_HPP // Skip this section if it was already included.
3830#define SHDR_EGL_HPP /* Mark this section as included. */
3831
3832 // Enable this optional backend before including shdr.h and link an EGL library.
3833#if defined(SHDR_ENABLE_EGL) && SHDR_ENABLE_EGL // Compile this branch only when its platform or backend condition holds.
3834#include <EGL/egl.h> // Load the EGL display, context, and surface API.
3835#include <EGL/eglext.h> // Use the available EGL context and platform extensions.
3836
3837namespace shdr { // Group these definitions in the shdr namespace.
3838
3839/** @brief The requested graphics backend or context is unavailable.
3840 * This exception identifies display, configuration, context and GL entry-point
3841 * failures. Shader compilation and dispatch errors remain ordinary shdr::error.
3842 */
3843class backend_unavailable : public error { // Keep the backend unavailable values and operations together.
3844  public: // Expose the operations callers can use.
3845    /** @brief Describe the unavailable graphics infrastructure. */
3846    explicit backend_unavailable(const std::string& message) : error(message) { // Keep the graphics initialization failure as an ordinary exception.
3847    } // End this scope in egl.
3848}; // End this scope in egl.
3849
3850namespace detail { // Group these definitions in the detail namespace.
3851
3852inline backend_unavailable egl_failure(const char* operation) { // Build a readable diagnostic from the EGL error code.
3853    const EGLint code = eglGetError(); // Read the EGL error belonging to the failed context operation.
3854    std::ostringstream message; // Build a readable diagnostic from the EGL error code.
3855    message << operation << " unavailable (EGL error 0x" << std::hex << code << ')'; // Build a readable diagnostic from the EGL error code.
3856    return backend_unavailable(message.str()); // Build a readable diagnostic from the EGL error code.
3857} // End this scope in egl failure.
3858
3859 // Initialization and the last termination share a lock, including during weak-pointer expiry.
3860struct egl_display_registry { // Keep the egl display registry values and operations together.
3861    std::mutex mutex; // Keep the lock protecting shared state.
3862    EGLDisplay display; // Keep the initialized EGL display.
3863    std::size_t owners; // Keep the number of contexts retaining this display.
3864    egl_display_registry() : display(EGL_NO_DISPLAY), owners(0) { // Start the initialized-display owner count at zero.
3865    } // End this scope in egl.
3866}; // End this scope in egl.
3867inline egl_display_registry& egl_displays() { // Share the display-lifetime registry among headless devices.
3868    static egl_display_registry registry; // Keep the shared display lifetime registry.
3869    return registry; // Return the shared display lifetime registry.
3870} // End this scope in egl displays.
3871
3872 // Contexts share one initialized display. the last context releases it.
3873struct egl_display_state { // Keep the egl display state values and operations together.
3874    EGLDisplay display; // Keep the initialized EGL display.
3875    egl_display_state() : display(EGL_NO_DISPLAY) { // Retain one initialized EGL display for living contexts.
3876        egl_display_registry& registry = egl_displays(); // Set the shared display lifetime registry.
3877        std::lock_guard<std::mutex> lock(registry.mutex); // Hold the mutex while this shared state is accessed.
3878        if (registry.owners) { // Reuse this display when another context already retains its initialization.
3879            display = registry.display; // Set the initialized EGL display.
3880            ++registry.owners; // Retain the existing initialized display for this new owner.
3881            return; // Finish this operation.
3882        } // End this scope in egl display state.
3883        typedef EGLDisplay(EGLAPIENTRYP platform_display_fn)(EGLenum, void*, const EGLint*); // Name the representation used by this GL or shader interface.
3884        const platform_display_fn platform_display = // Resolve the optional surfaceless display entry point.
3885            reinterpret_cast<platform_display_fn>(eglGetProcAddress("eglGetPlatformDisplayEXT")); // Look up the requested GL entry point through EGL.
3886        if (platform_display) { // Choose this branch when platform display.
3887 // Mesa's surfaceless platform creates an offscreen display on supported drivers.
3888            display = platform_display(0x31DD, EGL_DEFAULT_DISPLAY, 0); // Set the initialized EGL display.
3889            if (display != EGL_NO_DISPLAY && !eglInitialize(display, 0, 0)) // Prepare the default-display fallback if surfaceless initialization fails.
3890                display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3891        } // End this scope in egl display state.
3892        if (display == EGL_NO_DISPLAY) { // Try the default display after the surfaceless path.
3893            display = eglGetDisplay(EGL_DEFAULT_DISPLAY); // Set the initialized EGL display.
3894            if (display == EGL_NO_DISPLAY || !eglInitialize(display, 0, 0)) { // Report failure to acquire and initialize the default display.
3895                display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3896                throw egl_failure("EGL display"); // Report egl display.
3897            } // End this scope in egl display state.
3898        } // End this scope in egl display state.
3899        registry.display = display; // Set the initialized EGL display.
3900        registry.owners = 1; // Set the number of contexts retaining this display.
3901    } // End this scope in egl display state.
3902    ~egl_display_state() { // Release this object's owned resources at teardown.
3903        egl_display_registry& registry = egl_displays(); // Set the shared display lifetime registry.
3904        std::lock_guard<std::mutex> lock(registry.mutex); // Hold the mutex while this shared state is accessed.
3905        if (display != EGL_NO_DISPLAY && --registry.owners == 0) { // Terminate an initialized display after its final context owner releases it.
3906            eglTerminate(display); // Terminate the display after its last context owner is released.
3907            registry.display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3908        } // End this scope in egl display state.
3909    } // End this scope in egl display state.
3910    egl_display_state(const egl_display_state&) = delete; // Prevent copying this object and duplicating its retained identity.
3911    egl_display_state& operator=(const egl_display_state&) = delete; // Prevent copying this object and duplicating its retained identity.
3912}; // End this scope in egl.
3913
3914inline std::shared_ptr<egl_display_state> acquire_egl_display() { // Reuse the initialized display while any context retains it.
3915    static std::mutex mutex; // Keep the lock protecting shared state.
3916    static std::weak_ptr<egl_display_state> cached; // Keep the weak reference to the shared EGL display.
3917    std::lock_guard<std::mutex> lock(mutex); // Hold the mutex while this shared state is accessed.
3918    std::shared_ptr<egl_display_state> display = cached.lock(); // Set the initialized EGL display.
3919    if (!display) { // Create the shared display state for its first owner.
3920        display = std::make_shared<egl_display_state>(); // Set the initialized EGL display.
3921        cached = display; // Set the weak reference to the shared EGL display.
3922    } // End this scope in acquire egl display.
3923    return display; // Return the initialized EGL display.
3924} // End this scope in acquire egl display.
3925
3926struct egl_context_state { // Retain one headless EGL display, context, and pbuffer.
3927    std::shared_ptr<egl_display_state> display; // Keep the initialized EGL display.
3928    EGLContext context; // Keep the EGL context used for compute commands.
3929    EGLSurface surface; // Keep the one-pixel EGL pbuffer.
3930    EGLenum api; // Keep the selected desktop GL or GLES API.
3931    std::thread::id thread; // Keep the thread that created this EGL context.
3932
3933    explicit egl_context_state(profile p) // Create a pbuffer context for the requested shader profile.
3934        : display(acquire_egl_display()), context(EGL_NO_CONTEXT), surface(EGL_NO_SURFACE), // Reuse the initialized display while any context retains it.
3935          api(p == profile::es31 || p == profile::es32 ? EGL_OPENGL_ES_API : EGL_OPENGL_API), // Choose the EGL client API matching the requested shader profile.
3936          thread(std::this_thread::get_id()) { // Remember the only thread allowed to use this EGL context.
3937        try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3938            const bool desktop = p != profile::es31 && p != profile::es32; // Select the API family for the requested profile.
3939            if (!eglBindAPI(api)) // Check that EGL accepts the selected graphics API.
3940                throw egl_failure("EGL graphics API"); // Report egl graphics api.
3941            const EGLint config_attributes[] = {EGL_SURFACE_TYPE, // Request a pbuffer configuration with the chosen client API.
3942                                                EGL_PBUFFER_BIT, // Request a configuration capable of creating a small offscreen surface.
3943                                                EGL_RENDERABLE_TYPE, // Select the client API supported by the framebuffer configuration.
3944                                                desktop ? EGL_OPENGL_BIT : 0x0040, // Request desktop GL or an OpenGL ES 3-capable configuration.
3945                                                EGL_RED_SIZE, // Specify the number of red bits in the offscreen surface.
3946                                                8, // Request eight bits for this color component.
3947                                                EGL_GREEN_SIZE, // Specify the number of green bits in the offscreen surface.
3948                                                8, // Request eight bits for this color component.
3949                                                EGL_BLUE_SIZE, // Specify the number of blue bits in the offscreen surface.
3950                                                8, // Request eight bits for this color component.
3951                                                EGL_NONE}; // Create a pbuffer context for the requested shader profile.
3952            EGLConfig config = 0; // Set the selected EGL framebuffer configuration.
3953            EGLint count = 0; // Set the element or configuration count.
3954            if (!eglChooseConfig(display->display, config_attributes, &config, 1, &count) || !count) // Check resource size or driver limits before accessing storage.
3955                throw egl_failure("EGL framebuffer configuration"); // Report egl framebuffer configuration.
3956            const EGLint major = desktop ? 4 : 3; // Set the GL major version.
3957            const EGLint minor = p == profile::es31   ? 1 // Set the GL minor version.
3958                                 : p == profile::es32 ? 2 // Select the version associated with this shader profile.
3959                                 : p == profile::gl43 ? 3 // Select the version associated with this shader profile.
3960                                 : p == profile::gl45 ? 5 // Select the version associated with this shader profile.
3961                                                      : 6; // Select minor version six for the desktop GL 4.6 profile.
3962 // These KHR_create_context attributes are also core in EGL 1.5.
3963            const EGLint desktop_attributes[] = { // Request the selected desktop version and core profile.
3964                0x3098, major, 0x30FB, minor, 0x30FD, 0x00000001, EGL_NONE}; // Create a pbuffer context for the requested shader profile.
3965            const EGLint es_attributes[] = {0x3098, major, 0x30FB, minor, EGL_NONE}; // Request the selected GLES major and minor versions.
3966            context = eglCreateContext(display->display, // Create a compute context for the requested GL or GLES version.
3967                                       config, // Keep the selected EGL framebuffer configuration.
3968                                       EGL_NO_CONTEXT, // Create a context with its own GL object namespace.
3969                                       desktop ? desktop_attributes : es_attributes); // Create a pbuffer context for the requested shader profile.
3970            if (context == EGL_NO_CONTEXT) // Check that the driver created the requested context.
3971                throw egl_failure("Requested GL context"); // Report requested gl context.
3972            const EGLint surface_attributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; // Create a one-pixel offscreen pbuffer for compute commands.
3973            surface = eglCreatePbufferSurface(display->display, config, surface_attributes); // Set the one-pixel EGL pbuffer.
3974            if (surface == EGL_NO_SURFACE) // Check that the driver created the offscreen pbuffer.
3975                throw egl_failure("EGL pbuffer"); // Report egl pbuffer.
3976            make_current(); // Select this context on its creating thread.
3977        } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3978            release(); // Release this surface and context while preserving other active contexts.
3979            throw; // Rethrow the original failure after arranging the necessary cleanup.
3980        } // End this scope in egl context state.
3981    } // End this scope in egl context state.
3982    void make_current() const { // Select this context on its creating thread.
3983        if (std::this_thread::get_id() != thread) // Check that the operation uses the context or lifecycle thread.
3984            throw error("headless EGL operations require the context's creating thread"); // Report headless egl operations require the context's creating thread.
3985        if (!eglBindAPI(api)) // Check that EGL accepts the selected graphics API.
3986            throw egl_failure("EGL graphics API"); // Report egl graphics api.
3987        if (eglGetCurrentContext() == context && eglGetCurrentDisplay() == display->display) // Choose this branch when eglGetCurrentContext() equals context and eglGetCurrentDisplay() equals display->display.
3988            return; // Finish this operation.
3989        if (!eglMakeCurrent(display->display, surface, surface, context)) // Check that EGL activates this context and its pbuffer.
3990            throw egl_failure("Current EGL context"); // Report current egl context.
3991    } // End this scope in make current.
3992    void release() { // Release this surface and context while preserving other active contexts.
3993 // Unbind this context only when it is current on this thread.
3994        const EGLenum previous_api = eglQueryAPI(); // Set the EGL API current before context release.
3995        eglBindAPI(api); // Select the desktop GL or GLES API for this EGL operation.
3996        if (context != EGL_NO_CONTEXT && eglGetCurrentContext() == context) // Unbind this context when it is current.
3997            eglMakeCurrent(display->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // Make this pbuffer context current on its owning thread.
3998        if (surface != EGL_NO_SURFACE) // Destroy the pbuffer allocated by this state.
3999            eglDestroySurface(display->display, surface); // Release the EGL object after its context-thread owners finish.
4000        if (context != EGL_NO_CONTEXT) // Destroy the context allocated by this state.
4001            eglDestroyContext(display->display, context); // Release the EGL object after its context-thread owners finish.
4002        if (previous_api != api) // Choose this branch when previous api differs from api.
4003            eglBindAPI(previous_api); // Restore the API binding that belonged to the other live context.
4004        surface = EGL_NO_SURFACE; // Set the one-pixel EGL pbuffer.
4005        context = EGL_NO_CONTEXT; // Set the EGL context used for compute commands.
4006    } // End this scope in release.
4007    ~egl_context_state() { // Release this object's owned resources at teardown.
4008        release(); // Release this surface and context while preserving other active contexts.
4009    } // End this scope in egl context state.
4010    egl_context_state(const egl_context_state&) = delete; // Prevent copying this object and duplicating its retained identity.
4011    egl_context_state& operator=(const egl_context_state&) = delete; // Prevent copying this object and duplicating its retained identity.
4012}; // End this scope in egl.
4013
4014inline std::shared_ptr<egl_context_state> make_egl_context(profile p) { // Create and retain the headless EGL context.
4015    return std::make_shared<egl_context_state>(p); // Create and retain the headless EGL context.
4016} // End this scope in make egl context.
4017} // namespace detail
4018
4019/** @brief An optional, headless EGL pbuffer context for a selected compute profile.
4020 * Define SHDR_ENABLE_EGL=1 before including shdr.h and link EGL to use this class.
4021 * It prefers a surfaceless display and otherwise uses EGL's default display.
4022 * Create, use and finally release the context on its creating thread. Displays
4023 * are shared among living shdr contexts. Let shdr manage their display lifetime.
4024 */
4025class headless_context { // Keep the headless context values and operations together.
4026    std::shared_ptr<detail::egl_context_state> context_; // Keep the retained headless context state.
4027
4028  public: // Expose the operations callers can use.
4029    /** @brief Create a 1-by-1 pbuffer and make its context current.
4030     * @param p Minimum GL or GLES version. defaults to OpenGL ES 3.1.
4031     * @throws backend_unavailable If backend initialization fails.
4032     */
4033    explicit headless_context(profile p = profile::es31) : context_(detail::make_egl_context(p)) { // Create and retain an EGL context for the requested compute profile.
4034    } // End this scope in egl.
4035    /** @brief Make this context current on its creating thread. */
4036    void make_current() const { // Select this context on its creating thread.
4037        context_->make_current(); // Select this context on its creating thread.
4038    } // End this scope in make current.
4039    /** @brief Resolve a GL entry point through EGL, for shdr::device or external GL calls. */
4040    static void* resolve(const char* name) { // Resolve a named GL function through EGL.
4041        const __eglMustCastToProperFunctionPointerType function = eglGetProcAddress(name); // Look up the requested GL entry point through EGL.
4042        static_assert(sizeof(function) == sizeof(void*), // Require a representation that matches the shader interface.
4043                      "EGL function addresses must fit in void*"); // Require EGL function addresses to fit the portable resolver representation.
4044        void* address = 0; // Set the resolved GL function address.
4045        std::memcpy(&address, &function, sizeof(address)); // Copy the representation with the alias-safe byte-copy operation.
4046        return address; // Return the resolved GL function address.
4047    } // End this scope in resolve.
4048    headless_context(const headless_context&) = delete; // Prevent copying this object and duplicating its retained identity.
4049    headless_context& operator=(const headless_context&) = delete; // Prevent copying this object and duplicating its retained identity.
4050}; // End this scope in egl.
4051
4052/** @brief A compute device that creates and retains its own headless EGL context.
4053 * Define SHDR_ENABLE_EGL=1 and link EGL. Construct this device on the thread that
4054 * performs its GPU operations. Its context remains alive while GPU resources,
4055 * programs and submissions retain the device state. release those objects on
4056 * that thread before shutdown. CPU execution uses host resources.
4057 */
4058class headless_device : public device { // Keep the headless device values and operations together.
4059    std::shared_ptr<detail::egl_context_state> context_; // Keep the retained headless context state.
4060    headless_device(const std::shared_ptr<detail::egl_context_state>& context, profile p) try // Connect the retained EGL context to the GL runtime.
4061        : device(headless_context::resolve, p), context_(context) { // Retain a validated GL device state.
4062        state()->context_keepalive = context; // Set the retained headless context.
4063        state()->activate_context = [context] { // Set the callback that makes this device context current.
4064            context->make_current(); // Select this context on its creating thread.
4065        }; // End this scope in state.
4066    } catch (const backend_unavailable&) { // Clean up objects allocated before the operation failed.
4067        throw; // Rethrow the original failure after arranging the necessary cleanup.
4068    } catch (const error& failure) { // Translate device-initialization failures into an unavailable-backend result.
4069        throw backend_unavailable(failure.what()); // Preserve the initialization diagnostic in the backend exception.
4070    } // End this scope in egl.
4071
4072  public: // Expose the operations callers can use.
4073    /** @brief Create a headless context and initialize its compute device.
4074     * @param p Minimum shader and context profile. defaults to OpenGL ES 3.1.
4075     * @throws backend_unavailable If context creation or entry-point loading fails.
4076     */
4077    explicit headless_device(profile p = profile::es31) // Create a compute device with its own retained EGL context.
4078        : headless_device(detail::make_egl_context(p), p) { // Connect the retained EGL context to the GL runtime.
4079    } // End this scope in headless device.
4080    /** @brief Make the owned context current for external GL interoperability. */
4081    void make_current() const { // Select this context on its creating thread.
4082        context_->make_current(); // Select this context on its creating thread.
4083    } // End this scope in make current.
4084    headless_device(const headless_device&) = delete; // Prevent copying this object and duplicating its retained identity.
4085    headless_device& operator=(const headless_device&) = delete; // Prevent copying this object and duplicating its retained identity.
4086}; // End this scope in egl.
4087
4088} // namespace shdr
4089#endif // SHDR_ENABLE_EGL
4090#endif // SHDR_EGL_HPP
4091
4092// ---- macros.hpp ----
4093#ifndef SHDR_MACROS_HPP // Include these helper macros only once.
4094#define SHDR_MACROS_HPP // Remember that the helper macros are available.
4095
4096/** @brief Begin one shared shader declaration with a fixed local work group size. */
4097#define SHDR_BEGIN(name, x, y, z) /* Start the shared shader type and its CPU snapshot method. */ \
4098    using namespace ::shdr::glsl; /* Make the GLSL math names available inside this shader. */ \
4099    struct name : ::shdr::kernel { /* Give the shared shader the CPU kernel interface. */ \
4100        name() : ::shdr::kernel(#name, ::shdr::extent(x, y, z)) { /* Store the shader name and fixed local work group size. */ \
4101        } /* Close the generated method or shader declaration. */ \
4102        std::unique_ptr<::shdr::kernel> clone() const override { /* Build an independent CPU instance for deferred execution. */ \
4103            std::unique_ptr<name> copy(new name); /* Allocate the shader instance that will hold the snapshot. */ \
4104            copy_interfaces(*copy); /* Copy uniform values and resource bindings into that instance. */ \
4105            return std::unique_ptr<::shdr::kernel>(copy.release()); /* Return ownership through the common kernel interface. */ \
4106        } /* Close the generated method or shader declaration. */
4107/** @brief End a shared shader declaration. */
4108#define SHDR_END() /* Close the shared shader type. */ \
4109    } /* Close the generated method or shader declaration. */ \
4110    ; /* Finish the generated shader type declaration. */
4111/** @brief Declare the shared entry point, executed once per invocation on CPU or GPU. */
4112#define SHDR_MAIN() void main() override // Make the shader entry point override the CPU kernel method.
4113/** @brief Declare a typed std430 SSBO with readonly/writeonly/readwrite access. */
4114#define SHDR_BUFFER(binding, type, name, mode) /* Create a named storage buffer port with the chosen access mode. */ \
4115    ::shdr::buffer_port<type, ::shdr::access::mode> name{*this, binding, #name}; /* Register this typed buffer port with its owning shader. */
4116/** @brief Declare a typed scalar, vector or float matrix uniform. */
4117#define SHDR_UNIFORM(type, name) /* Create a uniform value and its binding descriptor. */ \
4118    type name{}; /* Initialize the uniform value to its default value. */ \
4119    ::shdr::uniform_port<type> shdr_uniform_##name{*this, #name, name}; /* Register the uniform so host code can set it by name. */
4120/** @brief Declare a 2D storage image. Supported formats are r32f/i/ui and rgba32f/i/ui. */
4121#define SHDR_IMAGE2D(binding, format, type, name, mode) /* Choose the matching image scalar type and component count. */ \
4122    SHDR_DETAIL_IMAGE_##type(::shdr::access::mode, SHDR_DETAIL_FORMAT_##format, name, binding) /* Expand the selected image helper with its access and binding. */
4123#define SHDR_DETAIL_IMAGE_image2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4124    ::shdr::image_port<float, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4125#define SHDR_DETAIL_IMAGE_iimage2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4126    ::shdr::image_port<int, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4127#define SHDR_DETAIL_IMAGE_uimage2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4128    ::shdr::image_port<unsigned, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4129#define SHDR_DETAIL_FORMAT_r32f 1 // Use one scalar component for this image format.
4130#define SHDR_DETAIL_FORMAT_r32i 1 // Use one scalar component for this image format.
4131#define SHDR_DETAIL_FORMAT_r32ui 1 // Use one scalar component for this image format.
4132#define SHDR_DETAIL_FORMAT_rgba32f 4 // Use four scalar components for this image format.
4133#define SHDR_DETAIL_FORMAT_rgba32i 4 // Use four scalar components for this image format.
4134#define SHDR_DETAIL_FORMAT_rgba32ui 4 // Use four scalar components for this image format.
4135/** @brief GLSL-style component selection, with safe simultaneous CPU swizzle assignment.
4136 * Use xyzw, rgba or stpq consistently. Duplicate components are read-only.
4137 */
4138#define SHDR_SWIZZLE(value, pattern) (value).template swizzle<SHDR_DETAIL_SWIZZLE_##pattern>() // Translate component letters into a safe CPU component selection.
4139/** @brief Portable spelling of GLSL's boolean vector not builtin. */
4140#define SHDR_NOT(value) ::shdr::glsl::logicalNot(value) // Invert every component of a boolean vector.
4141/** @brief Declare a shared helper function input parameter. */
4142#define SHDR_IN(type, name) const type& name // Pass a helper input through a const reference.
4143/** @brief Declare a shared helper function output parameter. */
4144#define SHDR_OUT(type, name) type& name // Let the helper write its output argument.
4145/** @brief Declare a shared helper function input/output parameter. */
4146#define SHDR_INOUT(type, name) type& name // Let the helper read and update its argument.
4147#define SHDR_DETAIL_SWIZZLE_x 0 // Select the x component.
4148#define SHDR_DETAIL_SWIZZLE_y 1 // Select the y component.
4149#define SHDR_DETAIL_SWIZZLE_z 2 // Select the z component.
4150#define SHDR_DETAIL_SWIZZLE_w 3 // Select the w component.
4151#define SHDR_DETAIL_SWIZZLE_xx 0, 0 // Select x, then x in that order.
4152#define SHDR_DETAIL_SWIZZLE_xy 0, 1 // Select x, then y in that order.
4153#define SHDR_DETAIL_SWIZZLE_xz 0, 2 // Select x, then z in that order.
4154#define SHDR_DETAIL_SWIZZLE_xw 0, 3 // Select x, then w in that order.
4155#define SHDR_DETAIL_SWIZZLE_yx 1, 0 // Select y, then x in that order.
4156#define SHDR_DETAIL_SWIZZLE_yy 1, 1 // Select y, then y in that order.
4157#define SHDR_DETAIL_SWIZZLE_yz 1, 2 // Select y, then z in that order.
4158#define SHDR_DETAIL_SWIZZLE_yw 1, 3 // Select y, then w in that order.
4159#define SHDR_DETAIL_SWIZZLE_zx 2, 0 // Select z, then x in that order.
4160#define SHDR_DETAIL_SWIZZLE_zy 2, 1 // Select z, then y in that order.
4161#define SHDR_DETAIL_SWIZZLE_zz 2, 2 // Select z, then z in that order.
4162#define SHDR_DETAIL_SWIZZLE_zw 2, 3 // Select z, then w in that order.
4163#define SHDR_DETAIL_SWIZZLE_wx 3, 0 // Select w, then x in that order.
4164#define SHDR_DETAIL_SWIZZLE_wy 3, 1 // Select w, then y in that order.
4165#define SHDR_DETAIL_SWIZZLE_wz 3, 2 // Select w, then z in that order.
4166#define SHDR_DETAIL_SWIZZLE_ww 3, 3 // Select w, then w in that order.
4167#define SHDR_DETAIL_SWIZZLE_xxx 0, 0, 0 // Select x, then x, then x in that order.
4168#define SHDR_DETAIL_SWIZZLE_xxy 0, 0, 1 // Select x, then x, then y in that order.
4169#define SHDR_DETAIL_SWIZZLE_xxz 0, 0, 2 // Select x, then x, then z in that order.
4170#define SHDR_DETAIL_SWIZZLE_xxw 0, 0, 3 // Select x, then x, then w in that order.
4171#define SHDR_DETAIL_SWIZZLE_xyx 0, 1, 0 // Select x, then y, then x in that order.
4172#define SHDR_DETAIL_SWIZZLE_xyy 0, 1, 1 // Select x, then y, then y in that order.
4173#define SHDR_DETAIL_SWIZZLE_xyz 0, 1, 2 // Select x, then y, then z in that order.
4174#define SHDR_DETAIL_SWIZZLE_xyw 0, 1, 3 // Select x, then y, then w in that order.
4175#define SHDR_DETAIL_SWIZZLE_xzx 0, 2, 0 // Select x, then z, then x in that order.
4176#define SHDR_DETAIL_SWIZZLE_xzy 0, 2, 1 // Select x, then z, then y in that order.
4177#define SHDR_DETAIL_SWIZZLE_xzz 0, 2, 2 // Select x, then z, then z in that order.
4178#define SHDR_DETAIL_SWIZZLE_xzw 0, 2, 3 // Select x, then z, then w in that order.
4179#define SHDR_DETAIL_SWIZZLE_xwx 0, 3, 0 // Select x, then w, then x in that order.
4180#define SHDR_DETAIL_SWIZZLE_xwy 0, 3, 1 // Select x, then w, then y in that order.
4181#define SHDR_DETAIL_SWIZZLE_xwz 0, 3, 2 // Select x, then w, then z in that order.
4182#define SHDR_DETAIL_SWIZZLE_xww 0, 3, 3 // Select x, then w, then w in that order.
4183#define SHDR_DETAIL_SWIZZLE_yxx 1, 0, 0 // Select y, then x, then x in that order.
4184#define SHDR_DETAIL_SWIZZLE_yxy 1, 0, 1 // Select y, then x, then y in that order.
4185#define SHDR_DETAIL_SWIZZLE_yxz 1, 0, 2 // Select y, then x, then z in that order.
4186#define SHDR_DETAIL_SWIZZLE_yxw 1, 0, 3 // Select y, then x, then w in that order.
4187#define SHDR_DETAIL_SWIZZLE_yyx 1, 1, 0 // Select y, then y, then x in that order.
4188#define SHDR_DETAIL_SWIZZLE_yyy 1, 1, 1 // Select y, then y, then y in that order.
4189#define SHDR_DETAIL_SWIZZLE_yyz 1, 1, 2 // Select y, then y, then z in that order.
4190#define SHDR_DETAIL_SWIZZLE_yyw 1, 1, 3 // Select y, then y, then w in that order.
4191#define SHDR_DETAIL_SWIZZLE_yzx 1, 2, 0 // Select y, then z, then x in that order.
4192#define SHDR_DETAIL_SWIZZLE_yzy 1, 2, 1 // Select y, then z, then y in that order.
4193#define SHDR_DETAIL_SWIZZLE_yzz 1, 2, 2 // Select y, then z, then z in that order.
4194#define SHDR_DETAIL_SWIZZLE_yzw 1, 2, 3 // Select y, then z, then w in that order.
4195#define SHDR_DETAIL_SWIZZLE_ywx 1, 3, 0 // Select y, then w, then x in that order.
4196#define SHDR_DETAIL_SWIZZLE_ywy 1, 3, 1 // Select y, then w, then y in that order.
4197#define SHDR_DETAIL_SWIZZLE_ywz 1, 3, 2 // Select y, then w, then z in that order.
4198#define SHDR_DETAIL_SWIZZLE_yww 1, 3, 3 // Select y, then w, then w in that order.
4199#define SHDR_DETAIL_SWIZZLE_zxx 2, 0, 0 // Select z, then x, then x in that order.
4200#define SHDR_DETAIL_SWIZZLE_zxy 2, 0, 1 // Select z, then x, then y in that order.
4201#define SHDR_DETAIL_SWIZZLE_zxz 2, 0, 2 // Select z, then x, then z in that order.
4202#define SHDR_DETAIL_SWIZZLE_zxw 2, 0, 3 // Select z, then x, then w in that order.
4203#define SHDR_DETAIL_SWIZZLE_zyx 2, 1, 0 // Select z, then y, then x in that order.
4204#define SHDR_DETAIL_SWIZZLE_zyy 2, 1, 1 // Select z, then y, then y in that order.
4205#define SHDR_DETAIL_SWIZZLE_zyz 2, 1, 2 // Select z, then y, then z in that order.
4206#define SHDR_DETAIL_SWIZZLE_zyw 2, 1, 3 // Select z, then y, then w in that order.
4207#define SHDR_DETAIL_SWIZZLE_zzx 2, 2, 0 // Select z, then z, then x in that order.
4208#define SHDR_DETAIL_SWIZZLE_zzy 2, 2, 1 // Select z, then z, then y in that order.
4209#define SHDR_DETAIL_SWIZZLE_zzz 2, 2, 2 // Select z, then z, then z in that order.
4210#define SHDR_DETAIL_SWIZZLE_zzw 2, 2, 3 // Select z, then z, then w in that order.
4211#define SHDR_DETAIL_SWIZZLE_zwx 2, 3, 0 // Select z, then w, then x in that order.
4212#define SHDR_DETAIL_SWIZZLE_zwy 2, 3, 1 // Select z, then w, then y in that order.
4213#define SHDR_DETAIL_SWIZZLE_zwz 2, 3, 2 // Select z, then w, then z in that order.
4214#define SHDR_DETAIL_SWIZZLE_zww 2, 3, 3 // Select z, then w, then w in that order.
4215#define SHDR_DETAIL_SWIZZLE_wxx 3, 0, 0 // Select w, then x, then x in that order.
4216#define SHDR_DETAIL_SWIZZLE_wxy 3, 0, 1 // Select w, then x, then y in that order.
4217#define SHDR_DETAIL_SWIZZLE_wxz 3, 0, 2 // Select w, then x, then z in that order.
4218#define SHDR_DETAIL_SWIZZLE_wxw 3, 0, 3 // Select w, then x, then w in that order.
4219#define SHDR_DETAIL_SWIZZLE_wyx 3, 1, 0 // Select w, then y, then x in that order.
4220#define SHDR_DETAIL_SWIZZLE_wyy 3, 1, 1 // Select w, then y, then y in that order.
4221#define SHDR_DETAIL_SWIZZLE_wyz 3, 1, 2 // Select w, then y, then z in that order.
4222#define SHDR_DETAIL_SWIZZLE_wyw 3, 1, 3 // Select w, then y, then w in that order.
4223#define SHDR_DETAIL_SWIZZLE_wzx 3, 2, 0 // Select w, then z, then x in that order.
4224#define SHDR_DETAIL_SWIZZLE_wzy 3, 2, 1 // Select w, then z, then y in that order.
4225#define SHDR_DETAIL_SWIZZLE_wzz 3, 2, 2 // Select w, then z, then z in that order.
4226#define SHDR_DETAIL_SWIZZLE_wzw 3, 2, 3 // Select w, then z, then w in that order.
4227#define SHDR_DETAIL_SWIZZLE_wwx 3, 3, 0 // Select w, then w, then x in that order.
4228#define SHDR_DETAIL_SWIZZLE_wwy 3, 3, 1 // Select w, then w, then y in that order.
4229#define SHDR_DETAIL_SWIZZLE_wwz 3, 3, 2 // Select w, then w, then z in that order.
4230#define SHDR_DETAIL_SWIZZLE_www 3, 3, 3 // Select w, then w, then w in that order.
4231#define SHDR_DETAIL_SWIZZLE_xxxx 0, 0, 0, 0 // Select x, then x, then x, then x in that order.
4232#define SHDR_DETAIL_SWIZZLE_xxxy 0, 0, 0, 1 // Select x, then x, then x, then y in that order.
4233#define SHDR_DETAIL_SWIZZLE_xxxz 0, 0, 0, 2 // Select x, then x, then x, then z in that order.
4234#define SHDR_DETAIL_SWIZZLE_xxxw 0, 0, 0, 3 // Select x, then x, then x, then w in that order.
4235#define SHDR_DETAIL_SWIZZLE_xxyx 0, 0, 1, 0 // Select x, then x, then y, then x in that order.
4236#define SHDR_DETAIL_SWIZZLE_xxyy 0, 0, 1, 1 // Select x, then x, then y, then y in that order.
4237#define SHDR_DETAIL_SWIZZLE_xxyz 0, 0, 1, 2 // Select x, then x, then y, then z in that order.
4238#define SHDR_DETAIL_SWIZZLE_xxyw 0, 0, 1, 3 // Select x, then x, then y, then w in that order.
4239#define SHDR_DETAIL_SWIZZLE_xxzx 0, 0, 2, 0 // Select x, then x, then z, then x in that order.
4240#define SHDR_DETAIL_SWIZZLE_xxzy 0, 0, 2, 1 // Select x, then x, then z, then y in that order.
4241#define SHDR_DETAIL_SWIZZLE_xxzz 0, 0, 2, 2 // Select x, then x, then z, then z in that order.
4242#define SHDR_DETAIL_SWIZZLE_xxzw 0, 0, 2, 3 // Select x, then x, then z, then w in that order.
4243#define SHDR_DETAIL_SWIZZLE_xxwx 0, 0, 3, 0 // Select x, then x, then w, then x in that order.
4244#define SHDR_DETAIL_SWIZZLE_xxwy 0, 0, 3, 1 // Select x, then x, then w, then y in that order.
4245#define SHDR_DETAIL_SWIZZLE_xxwz 0, 0, 3, 2 // Select x, then x, then w, then z in that order.
4246#define SHDR_DETAIL_SWIZZLE_xxww 0, 0, 3, 3 // Select x, then x, then w, then w in that order.
4247#define SHDR_DETAIL_SWIZZLE_xyxx 0, 1, 0, 0 // Select x, then y, then x, then x in that order.
4248#define SHDR_DETAIL_SWIZZLE_xyxy 0, 1, 0, 1 // Select x, then y, then x, then y in that order.
4249#define SHDR_DETAIL_SWIZZLE_xyxz 0, 1, 0, 2 // Select x, then y, then x, then z in that order.
4250#define SHDR_DETAIL_SWIZZLE_xyxw 0, 1, 0, 3 // Select x, then y, then x, then w in that order.
4251#define SHDR_DETAIL_SWIZZLE_xyyx 0, 1, 1, 0 // Select x, then y, then y, then x in that order.
4252#define SHDR_DETAIL_SWIZZLE_xyyy 0, 1, 1, 1 // Select x, then y, then y, then y in that order.
4253#define SHDR_DETAIL_SWIZZLE_xyyz 0, 1, 1, 2 // Select x, then y, then y, then z in that order.
4254#define SHDR_DETAIL_SWIZZLE_xyyw 0, 1, 1, 3 // Select x, then y, then y, then w in that order.
4255#define SHDR_DETAIL_SWIZZLE_xyzx 0, 1, 2, 0 // Select x, then y, then z, then x in that order.
4256#define SHDR_DETAIL_SWIZZLE_xyzy 0, 1, 2, 1 // Select x, then y, then z, then y in that order.
4257#define SHDR_DETAIL_SWIZZLE_xyzz 0, 1, 2, 2 // Select x, then y, then z, then z in that order.
4258#define SHDR_DETAIL_SWIZZLE_xyzw 0, 1, 2, 3 // Select x, then y, then z, then w in that order.
4259#define SHDR_DETAIL_SWIZZLE_xywx 0, 1, 3, 0 // Select x, then y, then w, then x in that order.
4260#define SHDR_DETAIL_SWIZZLE_xywy 0, 1, 3, 1 // Select x, then y, then w, then y in that order.
4261#define SHDR_DETAIL_SWIZZLE_xywz 0, 1, 3, 2 // Select x, then y, then w, then z in that order.
4262#define SHDR_DETAIL_SWIZZLE_xyww 0, 1, 3, 3 // Select x, then y, then w, then w in that order.
4263#define SHDR_DETAIL_SWIZZLE_xzxx 0, 2, 0, 0 // Select x, then z, then x, then x in that order.
4264#define SHDR_DETAIL_SWIZZLE_xzxy 0, 2, 0, 1 // Select x, then z, then x, then y in that order.
4265#define SHDR_DETAIL_SWIZZLE_xzxz 0, 2, 0, 2 // Select x, then z, then x, then z in that order.
4266#define SHDR_DETAIL_SWIZZLE_xzxw 0, 2, 0, 3 // Select x, then z, then x, then w in that order.
4267#define SHDR_DETAIL_SWIZZLE_xzyx 0, 2, 1, 0 // Select x, then z, then y, then x in that order.
4268#define SHDR_DETAIL_SWIZZLE_xzyy 0, 2, 1, 1 // Select x, then z, then y, then y in that order.
4269#define SHDR_DETAIL_SWIZZLE_xzyz 0, 2, 1, 2 // Select x, then z, then y, then z in that order.
4270#define SHDR_DETAIL_SWIZZLE_xzyw 0, 2, 1, 3 // Select x, then z, then y, then w in that order.
4271#define SHDR_DETAIL_SWIZZLE_xzzx 0, 2, 2, 0 // Select x, then z, then z, then x in that order.
4272#define SHDR_DETAIL_SWIZZLE_xzzy 0, 2, 2, 1 // Select x, then z, then z, then y in that order.
4273#define SHDR_DETAIL_SWIZZLE_xzzz 0, 2, 2, 2 // Select x, then z, then z, then z in that order.
4274#define SHDR_DETAIL_SWIZZLE_xzzw 0, 2, 2, 3 // Select x, then z, then z, then w in that order.
4275#define SHDR_DETAIL_SWIZZLE_xzwx 0, 2, 3, 0 // Select x, then z, then w, then x in that order.
4276#define SHDR_DETAIL_SWIZZLE_xzwy 0, 2, 3, 1 // Select x, then z, then w, then y in that order.
4277#define SHDR_DETAIL_SWIZZLE_xzwz 0, 2, 3, 2 // Select x, then z, then w, then z in that order.
4278#define SHDR_DETAIL_SWIZZLE_xzww 0, 2, 3, 3 // Select x, then z, then w, then w in that order.
4279#define SHDR_DETAIL_SWIZZLE_xwxx 0, 3, 0, 0 // Select x, then w, then x, then x in that order.
4280#define SHDR_DETAIL_SWIZZLE_xwxy 0, 3, 0, 1 // Select x, then w, then x, then y in that order.
4281#define SHDR_DETAIL_SWIZZLE_xwxz 0, 3, 0, 2 // Select x, then w, then x, then z in that order.
4282#define SHDR_DETAIL_SWIZZLE_xwxw 0, 3, 0, 3 // Select x, then w, then x, then w in that order.
4283#define SHDR_DETAIL_SWIZZLE_xwyx 0, 3, 1, 0 // Select x, then w, then y, then x in that order.
4284#define SHDR_DETAIL_SWIZZLE_xwyy 0, 3, 1, 1 // Select x, then w, then y, then y in that order.
4285#define SHDR_DETAIL_SWIZZLE_xwyz 0, 3, 1, 2 // Select x, then w, then y, then z in that order.
4286#define SHDR_DETAIL_SWIZZLE_xwyw 0, 3, 1, 3 // Select x, then w, then y, then w in that order.
4287#define SHDR_DETAIL_SWIZZLE_xwzx 0, 3, 2, 0 // Select x, then w, then z, then x in that order.
4288#define SHDR_DETAIL_SWIZZLE_xwzy 0, 3, 2, 1 // Select x, then w, then z, then y in that order.
4289#define SHDR_DETAIL_SWIZZLE_xwzz 0, 3, 2, 2 // Select x, then w, then z, then z in that order.
4290#define SHDR_DETAIL_SWIZZLE_xwzw 0, 3, 2, 3 // Select x, then w, then z, then w in that order.
4291#define SHDR_DETAIL_SWIZZLE_xwwx 0, 3, 3, 0 // Select x, then w, then w, then x in that order.
4292#define SHDR_DETAIL_SWIZZLE_xwwy 0, 3, 3, 1 // Select x, then w, then w, then y in that order.
4293#define SHDR_DETAIL_SWIZZLE_xwwz 0, 3, 3, 2 // Select x, then w, then w, then z in that order.
4294#define SHDR_DETAIL_SWIZZLE_xwww 0, 3, 3, 3 // Select x, then w, then w, then w in that order.
4295#define SHDR_DETAIL_SWIZZLE_yxxx 1, 0, 0, 0 // Select y, then x, then x, then x in that order.
4296#define SHDR_DETAIL_SWIZZLE_yxxy 1, 0, 0, 1 // Select y, then x, then x, then y in that order.
4297#define SHDR_DETAIL_SWIZZLE_yxxz 1, 0, 0, 2 // Select y, then x, then x, then z in that order.
4298#define SHDR_DETAIL_SWIZZLE_yxxw 1, 0, 0, 3 // Select y, then x, then x, then w in that order.
4299#define SHDR_DETAIL_SWIZZLE_yxyx 1, 0, 1, 0 // Select y, then x, then y, then x in that order.
4300#define SHDR_DETAIL_SWIZZLE_yxyy 1, 0, 1, 1 // Select y, then x, then y, then y in that order.
4301#define SHDR_DETAIL_SWIZZLE_yxyz 1, 0, 1, 2 // Select y, then x, then y, then z in that order.
4302#define SHDR_DETAIL_SWIZZLE_yxyw 1, 0, 1, 3 // Select y, then x, then y, then w in that order.
4303#define SHDR_DETAIL_SWIZZLE_yxzx 1, 0, 2, 0 // Select y, then x, then z, then x in that order.
4304#define SHDR_DETAIL_SWIZZLE_yxzy 1, 0, 2, 1 // Select y, then x, then z, then y in that order.
4305#define SHDR_DETAIL_SWIZZLE_yxzz 1, 0, 2, 2 // Select y, then x, then z, then z in that order.
4306#define SHDR_DETAIL_SWIZZLE_yxzw 1, 0, 2, 3 // Select y, then x, then z, then w in that order.
4307#define SHDR_DETAIL_SWIZZLE_yxwx 1, 0, 3, 0 // Select y, then x, then w, then x in that order.
4308#define SHDR_DETAIL_SWIZZLE_yxwy 1, 0, 3, 1 // Select y, then x, then w, then y in that order.
4309#define SHDR_DETAIL_SWIZZLE_yxwz 1, 0, 3, 2 // Select y, then x, then w, then z in that order.
4310#define SHDR_DETAIL_SWIZZLE_yxww 1, 0, 3, 3 // Select y, then x, then w, then w in that order.
4311#define SHDR_DETAIL_SWIZZLE_yyxx 1, 1, 0, 0 // Select y, then y, then x, then x in that order.
4312#define SHDR_DETAIL_SWIZZLE_yyxy 1, 1, 0, 1 // Select y, then y, then x, then y in that order.
4313#define SHDR_DETAIL_SWIZZLE_yyxz 1, 1, 0, 2 // Select y, then y, then x, then z in that order.
4314#define SHDR_DETAIL_SWIZZLE_yyxw 1, 1, 0, 3 // Select y, then y, then x, then w in that order.
4315#define SHDR_DETAIL_SWIZZLE_yyyx 1, 1, 1, 0 // Select y, then y, then y, then x in that order.
4316#define SHDR_DETAIL_SWIZZLE_yyyy 1, 1, 1, 1 // Select y, then y, then y, then y in that order.
4317#define SHDR_DETAIL_SWIZZLE_yyyz 1, 1, 1, 2 // Select y, then y, then y, then z in that order.
4318#define SHDR_DETAIL_SWIZZLE_yyyw 1, 1, 1, 3 // Select y, then y, then y, then w in that order.
4319#define SHDR_DETAIL_SWIZZLE_yyzx 1, 1, 2, 0 // Select y, then y, then z, then x in that order.
4320#define SHDR_DETAIL_SWIZZLE_yyzy 1, 1, 2, 1 // Select y, then y, then z, then y in that order.
4321#define SHDR_DETAIL_SWIZZLE_yyzz 1, 1, 2, 2 // Select y, then y, then z, then z in that order.
4322#define SHDR_DETAIL_SWIZZLE_yyzw 1, 1, 2, 3 // Select y, then y, then z, then w in that order.
4323#define SHDR_DETAIL_SWIZZLE_yywx 1, 1, 3, 0 // Select y, then y, then w, then x in that order.
4324#define SHDR_DETAIL_SWIZZLE_yywy 1, 1, 3, 1 // Select y, then y, then w, then y in that order.
4325#define SHDR_DETAIL_SWIZZLE_yywz 1, 1, 3, 2 // Select y, then y, then w, then z in that order.
4326#define SHDR_DETAIL_SWIZZLE_yyww 1, 1, 3, 3 // Select y, then y, then w, then w in that order.
4327#define SHDR_DETAIL_SWIZZLE_yzxx 1, 2, 0, 0 // Select y, then z, then x, then x in that order.
4328#define SHDR_DETAIL_SWIZZLE_yzxy 1, 2, 0, 1 // Select y, then z, then x, then y in that order.
4329#define SHDR_DETAIL_SWIZZLE_yzxz 1, 2, 0, 2 // Select y, then z, then x, then z in that order.
4330#define SHDR_DETAIL_SWIZZLE_yzxw 1, 2, 0, 3 // Select y, then z, then x, then w in that order.
4331#define SHDR_DETAIL_SWIZZLE_yzyx 1, 2, 1, 0 // Select y, then z, then y, then x in that order.
4332#define SHDR_DETAIL_SWIZZLE_yzyy 1, 2, 1, 1 // Select y, then z, then y, then y in that order.
4333#define SHDR_DETAIL_SWIZZLE_yzyz 1, 2, 1, 2 // Select y, then z, then y, then z in that order.
4334#define SHDR_DETAIL_SWIZZLE_yzyw 1, 2, 1, 3 // Select y, then z, then y, then w in that order.
4335#define SHDR_DETAIL_SWIZZLE_yzzx 1, 2, 2, 0 // Select y, then z, then z, then x in that order.
4336#define SHDR_DETAIL_SWIZZLE_yzzy 1, 2, 2, 1 // Select y, then z, then z, then y in that order.
4337#define SHDR_DETAIL_SWIZZLE_yzzz 1, 2, 2, 2 // Select y, then z, then z, then z in that order.
4338#define SHDR_DETAIL_SWIZZLE_yzzw 1, 2, 2, 3 // Select y, then z, then z, then w in that order.
4339#define SHDR_DETAIL_SWIZZLE_yzwx 1, 2, 3, 0 // Select y, then z, then w, then x in that order.
4340#define SHDR_DETAIL_SWIZZLE_yzwy 1, 2, 3, 1 // Select y, then z, then w, then y in that order.
4341#define SHDR_DETAIL_SWIZZLE_yzwz 1, 2, 3, 2 // Select y, then z, then w, then z in that order.
4342#define SHDR_DETAIL_SWIZZLE_yzww 1, 2, 3, 3 // Select y, then z, then w, then w in that order.
4343#define SHDR_DETAIL_SWIZZLE_ywxx 1, 3, 0, 0 // Select y, then w, then x, then x in that order.
4344#define SHDR_DETAIL_SWIZZLE_ywxy 1, 3, 0, 1 // Select y, then w, then x, then y in that order.
4345#define SHDR_DETAIL_SWIZZLE_ywxz 1, 3, 0, 2 // Select y, then w, then x, then z in that order.
4346#define SHDR_DETAIL_SWIZZLE_ywxw 1, 3, 0, 3 // Select y, then w, then x, then w in that order.
4347#define SHDR_DETAIL_SWIZZLE_ywyx 1, 3, 1, 0 // Select y, then w, then y, then x in that order.
4348#define SHDR_DETAIL_SWIZZLE_ywyy 1, 3, 1, 1 // Select y, then w, then y, then y in that order.
4349#define SHDR_DETAIL_SWIZZLE_ywyz 1, 3, 1, 2 // Select y, then w, then y, then z in that order.
4350#define SHDR_DETAIL_SWIZZLE_ywyw 1, 3, 1, 3 // Select y, then w, then y, then w in that order.
4351#define SHDR_DETAIL_SWIZZLE_ywzx 1, 3, 2, 0 // Select y, then w, then z, then x in that order.
4352#define SHDR_DETAIL_SWIZZLE_ywzy 1, 3, 2, 1 // Select y, then w, then z, then y in that order.
4353#define SHDR_DETAIL_SWIZZLE_ywzz 1, 3, 2, 2 // Select y, then w, then z, then z in that order.
4354#define SHDR_DETAIL_SWIZZLE_ywzw 1, 3, 2, 3 // Select y, then w, then z, then w in that order.
4355#define SHDR_DETAIL_SWIZZLE_ywwx 1, 3, 3, 0 // Select y, then w, then w, then x in that order.
4356#define SHDR_DETAIL_SWIZZLE_ywwy 1, 3, 3, 1 // Select y, then w, then w, then y in that order.
4357#define SHDR_DETAIL_SWIZZLE_ywwz 1, 3, 3, 2 // Select y, then w, then w, then z in that order.
4358#define SHDR_DETAIL_SWIZZLE_ywww 1, 3, 3, 3 // Select y, then w, then w, then w in that order.
4359#define SHDR_DETAIL_SWIZZLE_zxxx 2, 0, 0, 0 // Select z, then x, then x, then x in that order.
4360#define SHDR_DETAIL_SWIZZLE_zxxy 2, 0, 0, 1 // Select z, then x, then x, then y in that order.
4361#define SHDR_DETAIL_SWIZZLE_zxxz 2, 0, 0, 2 // Select z, then x, then x, then z in that order.
4362#define SHDR_DETAIL_SWIZZLE_zxxw 2, 0, 0, 3 // Select z, then x, then x, then w in that order.
4363#define SHDR_DETAIL_SWIZZLE_zxyx 2, 0, 1, 0 // Select z, then x, then y, then x in that order.
4364#define SHDR_DETAIL_SWIZZLE_zxyy 2, 0, 1, 1 // Select z, then x, then y, then y in that order.
4365#define SHDR_DETAIL_SWIZZLE_zxyz 2, 0, 1, 2 // Select z, then x, then y, then z in that order.
4366#define SHDR_DETAIL_SWIZZLE_zxyw 2, 0, 1, 3 // Select z, then x, then y, then w in that order.
4367#define SHDR_DETAIL_SWIZZLE_zxzx 2, 0, 2, 0 // Select z, then x, then z, then x in that order.
4368#define SHDR_DETAIL_SWIZZLE_zxzy 2, 0, 2, 1 // Select z, then x, then z, then y in that order.
4369#define SHDR_DETAIL_SWIZZLE_zxzz 2, 0, 2, 2 // Select z, then x, then z, then z in that order.
4370#define SHDR_DETAIL_SWIZZLE_zxzw 2, 0, 2, 3 // Select z, then x, then z, then w in that order.
4371#define SHDR_DETAIL_SWIZZLE_zxwx 2, 0, 3, 0 // Select z, then x, then w, then x in that order.
4372#define SHDR_DETAIL_SWIZZLE_zxwy 2, 0, 3, 1 // Select z, then x, then w, then y in that order.
4373#define SHDR_DETAIL_SWIZZLE_zxwz 2, 0, 3, 2 // Select z, then x, then w, then z in that order.
4374#define SHDR_DETAIL_SWIZZLE_zxww 2, 0, 3, 3 // Select z, then x, then w, then w in that order.
4375#define SHDR_DETAIL_SWIZZLE_zyxx 2, 1, 0, 0 // Select z, then y, then x, then x in that order.
4376#define SHDR_DETAIL_SWIZZLE_zyxy 2, 1, 0, 1 // Select z, then y, then x, then y in that order.
4377#define SHDR_DETAIL_SWIZZLE_zyxz 2, 1, 0, 2 // Select z, then y, then x, then z in that order.
4378#define SHDR_DETAIL_SWIZZLE_zyxw 2, 1, 0, 3 // Select z, then y, then x, then w in that order.
4379#define SHDR_DETAIL_SWIZZLE_zyyx 2, 1, 1, 0 // Select z, then y, then y, then x in that order.
4380#define SHDR_DETAIL_SWIZZLE_zyyy 2, 1, 1, 1 // Select z, then y, then y, then y in that order.
4381#define SHDR_DETAIL_SWIZZLE_zyyz 2, 1, 1, 2 // Select z, then y, then y, then z in that order.
4382#define SHDR_DETAIL_SWIZZLE_zyyw 2, 1, 1, 3 // Select z, then y, then y, then w in that order.
4383#define SHDR_DETAIL_SWIZZLE_zyzx 2, 1, 2, 0 // Select z, then y, then z, then x in that order.
4384#define SHDR_DETAIL_SWIZZLE_zyzy 2, 1, 2, 1 // Select z, then y, then z, then y in that order.
4385#define SHDR_DETAIL_SWIZZLE_zyzz 2, 1, 2, 2 // Select z, then y, then z, then z in that order.
4386#define SHDR_DETAIL_SWIZZLE_zyzw 2, 1, 2, 3 // Select z, then y, then z, then w in that order.
4387#define SHDR_DETAIL_SWIZZLE_zywx 2, 1, 3, 0 // Select z, then y, then w, then x in that order.
4388#define SHDR_DETAIL_SWIZZLE_zywy 2, 1, 3, 1 // Select z, then y, then w, then y in that order.
4389#define SHDR_DETAIL_SWIZZLE_zywz 2, 1, 3, 2 // Select z, then y, then w, then z in that order.
4390#define SHDR_DETAIL_SWIZZLE_zyww 2, 1, 3, 3 // Select z, then y, then w, then w in that order.
4391#define SHDR_DETAIL_SWIZZLE_zzxx 2, 2, 0, 0 // Select z, then z, then x, then x in that order.
4392#define SHDR_DETAIL_SWIZZLE_zzxy 2, 2, 0, 1 // Select z, then z, then x, then y in that order.
4393#define SHDR_DETAIL_SWIZZLE_zzxz 2, 2, 0, 2 // Select z, then z, then x, then z in that order.
4394#define SHDR_DETAIL_SWIZZLE_zzxw 2, 2, 0, 3 // Select z, then z, then x, then w in that order.
4395#define SHDR_DETAIL_SWIZZLE_zzyx 2, 2, 1, 0 // Select z, then z, then y, then x in that order.
4396#define SHDR_DETAIL_SWIZZLE_zzyy 2, 2, 1, 1 // Select z, then z, then y, then y in that order.
4397#define SHDR_DETAIL_SWIZZLE_zzyz 2, 2, 1, 2 // Select z, then z, then y, then z in that order.
4398#define SHDR_DETAIL_SWIZZLE_zzyw 2, 2, 1, 3 // Select z, then z, then y, then w in that order.
4399#define SHDR_DETAIL_SWIZZLE_zzzx 2, 2, 2, 0 // Select z, then z, then z, then x in that order.
4400#define SHDR_DETAIL_SWIZZLE_zzzy 2, 2, 2, 1 // Select z, then z, then z, then y in that order.
4401#define SHDR_DETAIL_SWIZZLE_zzzz 2, 2, 2, 2 // Select z, then z, then z, then z in that order.
4402#define SHDR_DETAIL_SWIZZLE_zzzw 2, 2, 2, 3 // Select z, then z, then z, then w in that order.
4403#define SHDR_DETAIL_SWIZZLE_zzwx 2, 2, 3, 0 // Select z, then z, then w, then x in that order.
4404#define SHDR_DETAIL_SWIZZLE_zzwy 2, 2, 3, 1 // Select z, then z, then w, then y in that order.
4405#define SHDR_DETAIL_SWIZZLE_zzwz 2, 2, 3, 2 // Select z, then z, then w, then z in that order.
4406#define SHDR_DETAIL_SWIZZLE_zzww 2, 2, 3, 3 // Select z, then z, then w, then w in that order.
4407#define SHDR_DETAIL_SWIZZLE_zwxx 2, 3, 0, 0 // Select z, then w, then x, then x in that order.
4408#define SHDR_DETAIL_SWIZZLE_zwxy 2, 3, 0, 1 // Select z, then w, then x, then y in that order.
4409#define SHDR_DETAIL_SWIZZLE_zwxz 2, 3, 0, 2 // Select z, then w, then x, then z in that order.
4410#define SHDR_DETAIL_SWIZZLE_zwxw 2, 3, 0, 3 // Select z, then w, then x, then w in that order.
4411#define SHDR_DETAIL_SWIZZLE_zwyx 2, 3, 1, 0 // Select z, then w, then y, then x in that order.
4412#define SHDR_DETAIL_SWIZZLE_zwyy 2, 3, 1, 1 // Select z, then w, then y, then y in that order.
4413#define SHDR_DETAIL_SWIZZLE_zwyz 2, 3, 1, 2 // Select z, then w, then y, then z in that order.
4414#define SHDR_DETAIL_SWIZZLE_zwyw 2, 3, 1, 3 // Select z, then w, then y, then w in that order.
4415#define SHDR_DETAIL_SWIZZLE_zwzx 2, 3, 2, 0 // Select z, then w, then z, then x in that order.
4416#define SHDR_DETAIL_SWIZZLE_zwzy 2, 3, 2, 1 // Select z, then w, then z, then y in that order.
4417#define SHDR_DETAIL_SWIZZLE_zwzz 2, 3, 2, 2 // Select z, then w, then z, then z in that order.
4418#define SHDR_DETAIL_SWIZZLE_zwzw 2, 3, 2, 3 // Select z, then w, then z, then w in that order.
4419#define SHDR_DETAIL_SWIZZLE_zwwx 2, 3, 3, 0 // Select z, then w, then w, then x in that order.
4420#define SHDR_DETAIL_SWIZZLE_zwwy 2, 3, 3, 1 // Select z, then w, then w, then y in that order.
4421#define SHDR_DETAIL_SWIZZLE_zwwz 2, 3, 3, 2 // Select z, then w, then w, then z in that order.
4422#define SHDR_DETAIL_SWIZZLE_zwww 2, 3, 3, 3 // Select z, then w, then w, then w in that order.
4423#define SHDR_DETAIL_SWIZZLE_wxxx 3, 0, 0, 0 // Select w, then x, then x, then x in that order.
4424#define SHDR_DETAIL_SWIZZLE_wxxy 3, 0, 0, 1 // Select w, then x, then x, then y in that order.
4425#define SHDR_DETAIL_SWIZZLE_wxxz 3, 0, 0, 2 // Select w, then x, then x, then z in that order.
4426#define SHDR_DETAIL_SWIZZLE_wxxw 3, 0, 0, 3 // Select w, then x, then x, then w in that order.
4427#define SHDR_DETAIL_SWIZZLE_wxyx 3, 0, 1, 0 // Select w, then x, then y, then x in that order.
4428#define SHDR_DETAIL_SWIZZLE_wxyy 3, 0, 1, 1 // Select w, then x, then y, then y in that order.
4429#define SHDR_DETAIL_SWIZZLE_wxyz 3, 0, 1, 2 // Select w, then x, then y, then z in that order.
4430#define SHDR_DETAIL_SWIZZLE_wxyw 3, 0, 1, 3 // Select w, then x, then y, then w in that order.
4431#define SHDR_DETAIL_SWIZZLE_wxzx 3, 0, 2, 0 // Select w, then x, then z, then x in that order.
4432#define SHDR_DETAIL_SWIZZLE_wxzy 3, 0, 2, 1 // Select w, then x, then z, then y in that order.
4433#define SHDR_DETAIL_SWIZZLE_wxzz 3, 0, 2, 2 // Select w, then x, then z, then z in that order.
4434#define SHDR_DETAIL_SWIZZLE_wxzw 3, 0, 2, 3 // Select w, then x, then z, then w in that order.
4435#define SHDR_DETAIL_SWIZZLE_wxwx 3, 0, 3, 0 // Select w, then x, then w, then x in that order.
4436#define SHDR_DETAIL_SWIZZLE_wxwy 3, 0, 3, 1 // Select w, then x, then w, then y in that order.
4437#define SHDR_DETAIL_SWIZZLE_wxwz 3, 0, 3, 2 // Select w, then x, then w, then z in that order.
4438#define SHDR_DETAIL_SWIZZLE_wxww 3, 0, 3, 3 // Select w, then x, then w, then w in that order.
4439#define SHDR_DETAIL_SWIZZLE_wyxx 3, 1, 0, 0 // Select w, then y, then x, then x in that order.
4440#define SHDR_DETAIL_SWIZZLE_wyxy 3, 1, 0, 1 // Select w, then y, then x, then y in that order.
4441#define SHDR_DETAIL_SWIZZLE_wyxz 3, 1, 0, 2 // Select w, then y, then x, then z in that order.
4442#define SHDR_DETAIL_SWIZZLE_wyxw 3, 1, 0, 3 // Select w, then y, then x, then w in that order.
4443#define SHDR_DETAIL_SWIZZLE_wyyx 3, 1, 1, 0 // Select w, then y, then y, then x in that order.
4444#define SHDR_DETAIL_SWIZZLE_wyyy 3, 1, 1, 1 // Select w, then y, then y, then y in that order.
4445#define SHDR_DETAIL_SWIZZLE_wyyz 3, 1, 1, 2 // Select w, then y, then y, then z in that order.
4446#define SHDR_DETAIL_SWIZZLE_wyyw 3, 1, 1, 3 // Select w, then y, then y, then w in that order.
4447#define SHDR_DETAIL_SWIZZLE_wyzx 3, 1, 2, 0 // Select w, then y, then z, then x in that order.
4448#define SHDR_DETAIL_SWIZZLE_wyzy 3, 1, 2, 1 // Select w, then y, then z, then y in that order.
4449#define SHDR_DETAIL_SWIZZLE_wyzz 3, 1, 2, 2 // Select w, then y, then z, then z in that order.
4450#define SHDR_DETAIL_SWIZZLE_wyzw 3, 1, 2, 3 // Select w, then y, then z, then w in that order.
4451#define SHDR_DETAIL_SWIZZLE_wywx 3, 1, 3, 0 // Select w, then y, then w, then x in that order.
4452#define SHDR_DETAIL_SWIZZLE_wywy 3, 1, 3, 1 // Select w, then y, then w, then y in that order.
4453#define SHDR_DETAIL_SWIZZLE_wywz 3, 1, 3, 2 // Select w, then y, then w, then z in that order.
4454#define SHDR_DETAIL_SWIZZLE_wyww 3, 1, 3, 3 // Select w, then y, then w, then w in that order.
4455#define SHDR_DETAIL_SWIZZLE_wzxx 3, 2, 0, 0 // Select w, then z, then x, then x in that order.
4456#define SHDR_DETAIL_SWIZZLE_wzxy 3, 2, 0, 1 // Select w, then z, then x, then y in that order.
4457#define SHDR_DETAIL_SWIZZLE_wzxz 3, 2, 0, 2 // Select w, then z, then x, then z in that order.
4458#define SHDR_DETAIL_SWIZZLE_wzxw 3, 2, 0, 3 // Select w, then z, then x, then w in that order.
4459#define SHDR_DETAIL_SWIZZLE_wzyx 3, 2, 1, 0 // Select w, then z, then y, then x in that order.
4460#define SHDR_DETAIL_SWIZZLE_wzyy 3, 2, 1, 1 // Select w, then z, then y, then y in that order.
4461#define SHDR_DETAIL_SWIZZLE_wzyz 3, 2, 1, 2 // Select w, then z, then y, then z in that order.
4462#define SHDR_DETAIL_SWIZZLE_wzyw 3, 2, 1, 3 // Select w, then z, then y, then w in that order.
4463#define SHDR_DETAIL_SWIZZLE_wzzx 3, 2, 2, 0 // Select w, then z, then z, then x in that order.
4464#define SHDR_DETAIL_SWIZZLE_wzzy 3, 2, 2, 1 // Select w, then z, then z, then y in that order.
4465#define SHDR_DETAIL_SWIZZLE_wzzz 3, 2, 2, 2 // Select w, then z, then z, then z in that order.
4466#define SHDR_DETAIL_SWIZZLE_wzzw 3, 2, 2, 3 // Select w, then z, then z, then w in that order.
4467#define SHDR_DETAIL_SWIZZLE_wzwx 3, 2, 3, 0 // Select w, then z, then w, then x in that order.
4468#define SHDR_DETAIL_SWIZZLE_wzwy 3, 2, 3, 1 // Select w, then z, then w, then y in that order.
4469#define SHDR_DETAIL_SWIZZLE_wzwz 3, 2, 3, 2 // Select w, then z, then w, then z in that order.
4470#define SHDR_DETAIL_SWIZZLE_wzww 3, 2, 3, 3 // Select w, then z, then w, then w in that order.
4471#define SHDR_DETAIL_SWIZZLE_wwxx 3, 3, 0, 0 // Select w, then w, then x, then x in that order.
4472#define SHDR_DETAIL_SWIZZLE_wwxy 3, 3, 0, 1 // Select w, then w, then x, then y in that order.
4473#define SHDR_DETAIL_SWIZZLE_wwxz 3, 3, 0, 2 // Select w, then w, then x, then z in that order.
4474#define SHDR_DETAIL_SWIZZLE_wwxw 3, 3, 0, 3 // Select w, then w, then x, then w in that order.
4475#define SHDR_DETAIL_SWIZZLE_wwyx 3, 3, 1, 0 // Select w, then w, then y, then x in that order.
4476#define SHDR_DETAIL_SWIZZLE_wwyy 3, 3, 1, 1 // Select w, then w, then y, then y in that order.
4477#define SHDR_DETAIL_SWIZZLE_wwyz 3, 3, 1, 2 // Select w, then w, then y, then z in that order.
4478#define SHDR_DETAIL_SWIZZLE_wwyw 3, 3, 1, 3 // Select w, then w, then y, then w in that order.
4479#define SHDR_DETAIL_SWIZZLE_wwzx 3, 3, 2, 0 // Select w, then w, then z, then x in that order.
4480#define SHDR_DETAIL_SWIZZLE_wwzy 3, 3, 2, 1 // Select w, then w, then z, then y in that order.
4481#define SHDR_DETAIL_SWIZZLE_wwzz 3, 3, 2, 2 // Select w, then w, then z, then z in that order.
4482#define SHDR_DETAIL_SWIZZLE_wwzw 3, 3, 2, 3 // Select w, then w, then z, then w in that order.
4483#define SHDR_DETAIL_SWIZZLE_wwwx 3, 3, 3, 0 // Select w, then w, then w, then x in that order.
4484#define SHDR_DETAIL_SWIZZLE_wwwy 3, 3, 3, 1 // Select w, then w, then w, then y in that order.
4485#define SHDR_DETAIL_SWIZZLE_wwwz 3, 3, 3, 2 // Select w, then w, then w, then z in that order.
4486#define SHDR_DETAIL_SWIZZLE_wwww 3, 3, 3, 3 // Select w, then w, then w, then w in that order.
4487#define SHDR_DETAIL_SWIZZLE_r 0 // Select the r component.
4488#define SHDR_DETAIL_SWIZZLE_g 1 // Select the g component.
4489#define SHDR_DETAIL_SWIZZLE_b 2 // Select the b component.
4490#define SHDR_DETAIL_SWIZZLE_a 3 // Select the a component.
4491#define SHDR_DETAIL_SWIZZLE_rr 0, 0 // Select r, then r in that order.
4492#define SHDR_DETAIL_SWIZZLE_rg 0, 1 // Select r, then g in that order.
4493#define SHDR_DETAIL_SWIZZLE_rb 0, 2 // Select r, then b in that order.
4494#define SHDR_DETAIL_SWIZZLE_ra 0, 3 // Select r, then a in that order.
4495#define SHDR_DETAIL_SWIZZLE_gr 1, 0 // Select g, then r in that order.
4496#define SHDR_DETAIL_SWIZZLE_gg 1, 1 // Select g, then g in that order.
4497#define SHDR_DETAIL_SWIZZLE_gb 1, 2 // Select g, then b in that order.
4498#define SHDR_DETAIL_SWIZZLE_ga 1, 3 // Select g, then a in that order.
4499#define SHDR_DETAIL_SWIZZLE_br 2, 0 // Select b, then r in that order.
4500#define SHDR_DETAIL_SWIZZLE_bg 2, 1 // Select b, then g in that order.
4501#define SHDR_DETAIL_SWIZZLE_bb 2, 2 // Select b, then b in that order.
4502#define SHDR_DETAIL_SWIZZLE_ba 2, 3 // Select b, then a in that order.
4503#define SHDR_DETAIL_SWIZZLE_ar 3, 0 // Select a, then r in that order.
4504#define SHDR_DETAIL_SWIZZLE_ag 3, 1 // Select a, then g in that order.
4505#define SHDR_DETAIL_SWIZZLE_ab 3, 2 // Select a, then b in that order.
4506#define SHDR_DETAIL_SWIZZLE_aa 3, 3 // Select a, then a in that order.
4507#define SHDR_DETAIL_SWIZZLE_rrr 0, 0, 0 // Select r, then r, then r in that order.
4508#define SHDR_DETAIL_SWIZZLE_rrg 0, 0, 1 // Select r, then r, then g in that order.
4509#define SHDR_DETAIL_SWIZZLE_rrb 0, 0, 2 // Select r, then r, then b in that order.
4510#define SHDR_DETAIL_SWIZZLE_rra 0, 0, 3 // Select r, then r, then a in that order.
4511#define SHDR_DETAIL_SWIZZLE_rgr 0, 1, 0 // Select r, then g, then r in that order.
4512#define SHDR_DETAIL_SWIZZLE_rgg 0, 1, 1 // Select r, then g, then g in that order.
4513#define SHDR_DETAIL_SWIZZLE_rgb 0, 1, 2 // Select r, then g, then b in that order.
4514#define SHDR_DETAIL_SWIZZLE_rga 0, 1, 3 // Select r, then g, then a in that order.
4515#define SHDR_DETAIL_SWIZZLE_rbr 0, 2, 0 // Select r, then b, then r in that order.
4516#define SHDR_DETAIL_SWIZZLE_rbg 0, 2, 1 // Select r, then b, then g in that order.
4517#define SHDR_DETAIL_SWIZZLE_rbb 0, 2, 2 // Select r, then b, then b in that order.
4518#define SHDR_DETAIL_SWIZZLE_rba 0, 2, 3 // Select r, then b, then a in that order.
4519#define SHDR_DETAIL_SWIZZLE_rar 0, 3, 0 // Select r, then a, then r in that order.
4520#define SHDR_DETAIL_SWIZZLE_rag 0, 3, 1 // Select r, then a, then g in that order.
4521#define SHDR_DETAIL_SWIZZLE_rab 0, 3, 2 // Select r, then a, then b in that order.
4522#define SHDR_DETAIL_SWIZZLE_raa 0, 3, 3 // Select r, then a, then a in that order.
4523#define SHDR_DETAIL_SWIZZLE_grr 1, 0, 0 // Select g, then r, then r in that order.
4524#define SHDR_DETAIL_SWIZZLE_grg 1, 0, 1 // Select g, then r, then g in that order.
4525#define SHDR_DETAIL_SWIZZLE_grb 1, 0, 2 // Select g, then r, then b in that order.
4526#define SHDR_DETAIL_SWIZZLE_gra 1, 0, 3 // Select g, then r, then a in that order.
4527#define SHDR_DETAIL_SWIZZLE_ggr 1, 1, 0 // Select g, then g, then r in that order.
4528#define SHDR_DETAIL_SWIZZLE_ggg 1, 1, 1 // Select g, then g, then g in that order.
4529#define SHDR_DETAIL_SWIZZLE_ggb 1, 1, 2 // Select g, then g, then b in that order.
4530#define SHDR_DETAIL_SWIZZLE_gga 1, 1, 3 // Select g, then g, then a in that order.
4531#define SHDR_DETAIL_SWIZZLE_gbr 1, 2, 0 // Select g, then b, then r in that order.
4532#define SHDR_DETAIL_SWIZZLE_gbg 1, 2, 1 // Select g, then b, then g in that order.
4533#define SHDR_DETAIL_SWIZZLE_gbb 1, 2, 2 // Select g, then b, then b in that order.
4534#define SHDR_DETAIL_SWIZZLE_gba 1, 2, 3 // Select g, then b, then a in that order.
4535#define SHDR_DETAIL_SWIZZLE_gar 1, 3, 0 // Select g, then a, then r in that order.
4536#define SHDR_DETAIL_SWIZZLE_gag 1, 3, 1 // Select g, then a, then g in that order.
4537#define SHDR_DETAIL_SWIZZLE_gab 1, 3, 2 // Select g, then a, then b in that order.
4538#define SHDR_DETAIL_SWIZZLE_gaa 1, 3, 3 // Select g, then a, then a in that order.
4539#define SHDR_DETAIL_SWIZZLE_brr 2, 0, 0 // Select b, then r, then r in that order.
4540#define SHDR_DETAIL_SWIZZLE_brg 2, 0, 1 // Select b, then r, then g in that order.
4541#define SHDR_DETAIL_SWIZZLE_brb 2, 0, 2 // Select b, then r, then b in that order.
4542#define SHDR_DETAIL_SWIZZLE_bra 2, 0, 3 // Select b, then r, then a in that order.
4543#define SHDR_DETAIL_SWIZZLE_bgr 2, 1, 0 // Select b, then g, then r in that order.
4544#define SHDR_DETAIL_SWIZZLE_bgg 2, 1, 1 // Select b, then g, then g in that order.
4545#define SHDR_DETAIL_SWIZZLE_bgb 2, 1, 2 // Select b, then g, then b in that order.
4546#define SHDR_DETAIL_SWIZZLE_bga 2, 1, 3 // Select b, then g, then a in that order.
4547#define SHDR_DETAIL_SWIZZLE_bbr 2, 2, 0 // Select b, then b, then r in that order.
4548#define SHDR_DETAIL_SWIZZLE_bbg 2, 2, 1 // Select b, then b, then g in that order.
4549#define SHDR_DETAIL_SWIZZLE_bbb 2, 2, 2 // Select b, then b, then b in that order.
4550#define SHDR_DETAIL_SWIZZLE_bba 2, 2, 3 // Select b, then b, then a in that order.
4551#define SHDR_DETAIL_SWIZZLE_bar 2, 3, 0 // Select b, then a, then r in that order.
4552#define SHDR_DETAIL_SWIZZLE_bag 2, 3, 1 // Select b, then a, then g in that order.
4553#define SHDR_DETAIL_SWIZZLE_bab 2, 3, 2 // Select b, then a, then b in that order.
4554#define SHDR_DETAIL_SWIZZLE_baa 2, 3, 3 // Select b, then a, then a in that order.
4555#define SHDR_DETAIL_SWIZZLE_arr 3, 0, 0 // Select a, then r, then r in that order.
4556#define SHDR_DETAIL_SWIZZLE_arg 3, 0, 1 // Select a, then r, then g in that order.
4557#define SHDR_DETAIL_SWIZZLE_arb 3, 0, 2 // Select a, then r, then b in that order.
4558#define SHDR_DETAIL_SWIZZLE_ara 3, 0, 3 // Select a, then r, then a in that order.
4559#define SHDR_DETAIL_SWIZZLE_agr 3, 1, 0 // Select a, then g, then r in that order.
4560#define SHDR_DETAIL_SWIZZLE_agg 3, 1, 1 // Select a, then g, then g in that order.
4561#define SHDR_DETAIL_SWIZZLE_agb 3, 1, 2 // Select a, then g, then b in that order.
4562#define SHDR_DETAIL_SWIZZLE_aga 3, 1, 3 // Select a, then g, then a in that order.
4563#define SHDR_DETAIL_SWIZZLE_abr 3, 2, 0 // Select a, then b, then r in that order.
4564#define SHDR_DETAIL_SWIZZLE_abg 3, 2, 1 // Select a, then b, then g in that order.
4565#define SHDR_DETAIL_SWIZZLE_abb 3, 2, 2 // Select a, then b, then b in that order.
4566#define SHDR_DETAIL_SWIZZLE_aba 3, 2, 3 // Select a, then b, then a in that order.
4567#define SHDR_DETAIL_SWIZZLE_aar 3, 3, 0 // Select a, then a, then r in that order.
4568#define SHDR_DETAIL_SWIZZLE_aag 3, 3, 1 // Select a, then a, then g in that order.
4569#define SHDR_DETAIL_SWIZZLE_aab 3, 3, 2 // Select a, then a, then b in that order.
4570#define SHDR_DETAIL_SWIZZLE_aaa 3, 3, 3 // Select a, then a, then a in that order.
4571#define SHDR_DETAIL_SWIZZLE_rrrr 0, 0, 0, 0 // Select r, then r, then r, then r in that order.
4572#define SHDR_DETAIL_SWIZZLE_rrrg 0, 0, 0, 1 // Select r, then r, then r, then g in that order.
4573#define SHDR_DETAIL_SWIZZLE_rrrb 0, 0, 0, 2 // Select r, then r, then r, then b in that order.
4574#define SHDR_DETAIL_SWIZZLE_rrra 0, 0, 0, 3 // Select r, then r, then r, then a in that order.
4575#define SHDR_DETAIL_SWIZZLE_rrgr 0, 0, 1, 0 // Select r, then r, then g, then r in that order.
4576#define SHDR_DETAIL_SWIZZLE_rrgg 0, 0, 1, 1 // Select r, then r, then g, then g in that order.
4577#define SHDR_DETAIL_SWIZZLE_rrgb 0, 0, 1, 2 // Select r, then r, then g, then b in that order.
4578#define SHDR_DETAIL_SWIZZLE_rrga 0, 0, 1, 3 // Select r, then r, then g, then a in that order.
4579#define SHDR_DETAIL_SWIZZLE_rrbr 0, 0, 2, 0 // Select r, then r, then b, then r in that order.
4580#define SHDR_DETAIL_SWIZZLE_rrbg 0, 0, 2, 1 // Select r, then r, then b, then g in that order.
4581#define SHDR_DETAIL_SWIZZLE_rrbb 0, 0, 2, 2 // Select r, then r, then b, then b in that order.
4582#define SHDR_DETAIL_SWIZZLE_rrba 0, 0, 2, 3 // Select r, then r, then b, then a in that order.
4583#define SHDR_DETAIL_SWIZZLE_rrar 0, 0, 3, 0 // Select r, then r, then a, then r in that order.
4584#define SHDR_DETAIL_SWIZZLE_rrag 0, 0, 3, 1 // Select r, then r, then a, then g in that order.
4585#define SHDR_DETAIL_SWIZZLE_rrab 0, 0, 3, 2 // Select r, then r, then a, then b in that order.
4586#define SHDR_DETAIL_SWIZZLE_rraa 0, 0, 3, 3 // Select r, then r, then a, then a in that order.
4587#define SHDR_DETAIL_SWIZZLE_rgrr 0, 1, 0, 0 // Select r, then g, then r, then r in that order.
4588#define SHDR_DETAIL_SWIZZLE_rgrg 0, 1, 0, 1 // Select r, then g, then r, then g in that order.
4589#define SHDR_DETAIL_SWIZZLE_rgrb 0, 1, 0, 2 // Select r, then g, then r, then b in that order.
4590#define SHDR_DETAIL_SWIZZLE_rgra 0, 1, 0, 3 // Select r, then g, then r, then a in that order.
4591#define SHDR_DETAIL_SWIZZLE_rggr 0, 1, 1, 0 // Select r, then g, then g, then r in that order.
4592#define SHDR_DETAIL_SWIZZLE_rggg 0, 1, 1, 1 // Select r, then g, then g, then g in that order.
4593#define SHDR_DETAIL_SWIZZLE_rggb 0, 1, 1, 2 // Select r, then g, then g, then b in that order.
4594#define SHDR_DETAIL_SWIZZLE_rgga 0, 1, 1, 3 // Select r, then g, then g, then a in that order.
4595#define SHDR_DETAIL_SWIZZLE_rgbr 0, 1, 2, 0 // Select r, then g, then b, then r in that order.
4596#define SHDR_DETAIL_SWIZZLE_rgbg 0, 1, 2, 1 // Select r, then g, then b, then g in that order.
4597#define SHDR_DETAIL_SWIZZLE_rgbb 0, 1, 2, 2 // Select r, then g, then b, then b in that order.
4598#define SHDR_DETAIL_SWIZZLE_rgba 0, 1, 2, 3 // Select r, then g, then b, then a in that order.
4599#define SHDR_DETAIL_SWIZZLE_rgar 0, 1, 3, 0 // Select r, then g, then a, then r in that order.
4600#define SHDR_DETAIL_SWIZZLE_rgag 0, 1, 3, 1 // Select r, then g, then a, then g in that order.
4601#define SHDR_DETAIL_SWIZZLE_rgab 0, 1, 3, 2 // Select r, then g, then a, then b in that order.
4602#define SHDR_DETAIL_SWIZZLE_rgaa 0, 1, 3, 3 // Select r, then g, then a, then a in that order.
4603#define SHDR_DETAIL_SWIZZLE_rbrr 0, 2, 0, 0 // Select r, then b, then r, then r in that order.
4604#define SHDR_DETAIL_SWIZZLE_rbrg 0, 2, 0, 1 // Select r, then b, then r, then g in that order.
4605#define SHDR_DETAIL_SWIZZLE_rbrb 0, 2, 0, 2 // Select r, then b, then r, then b in that order.
4606#define SHDR_DETAIL_SWIZZLE_rbra 0, 2, 0, 3 // Select r, then b, then r, then a in that order.
4607#define SHDR_DETAIL_SWIZZLE_rbgr 0, 2, 1, 0 // Select r, then b, then g, then r in that order.
4608#define SHDR_DETAIL_SWIZZLE_rbgg 0, 2, 1, 1 // Select r, then b, then g, then g in that order.
4609#define SHDR_DETAIL_SWIZZLE_rbgb 0, 2, 1, 2 // Select r, then b, then g, then b in that order.
4610#define SHDR_DETAIL_SWIZZLE_rbga 0, 2, 1, 3 // Select r, then b, then g, then a in that order.
4611#define SHDR_DETAIL_SWIZZLE_rbbr 0, 2, 2, 0 // Select r, then b, then b, then r in that order.
4612#define SHDR_DETAIL_SWIZZLE_rbbg 0, 2, 2, 1 // Select r, then b, then b, then g in that order.
4613#define SHDR_DETAIL_SWIZZLE_rbbb 0, 2, 2, 2 // Select r, then b, then b, then b in that order.
4614#define SHDR_DETAIL_SWIZZLE_rbba 0, 2, 2, 3 // Select r, then b, then b, then a in that order.
4615#define SHDR_DETAIL_SWIZZLE_rbar 0, 2, 3, 0 // Select r, then b, then a, then r in that order.
4616#define SHDR_DETAIL_SWIZZLE_rbag 0, 2, 3, 1 // Select r, then b, then a, then g in that order.
4617#define SHDR_DETAIL_SWIZZLE_rbab 0, 2, 3, 2 // Select r, then b, then a, then b in that order.
4618#define SHDR_DETAIL_SWIZZLE_rbaa 0, 2, 3, 3 // Select r, then b, then a, then a in that order.
4619#define SHDR_DETAIL_SWIZZLE_rarr 0, 3, 0, 0 // Select r, then a, then r, then r in that order.
4620#define SHDR_DETAIL_SWIZZLE_rarg 0, 3, 0, 1 // Select r, then a, then r, then g in that order.
4621#define SHDR_DETAIL_SWIZZLE_rarb 0, 3, 0, 2 // Select r, then a, then r, then b in that order.
4622#define SHDR_DETAIL_SWIZZLE_rara 0, 3, 0, 3 // Select r, then a, then r, then a in that order.
4623#define SHDR_DETAIL_SWIZZLE_ragr 0, 3, 1, 0 // Select r, then a, then g, then r in that order.
4624#define SHDR_DETAIL_SWIZZLE_ragg 0, 3, 1, 1 // Select r, then a, then g, then g in that order.
4625#define SHDR_DETAIL_SWIZZLE_ragb 0, 3, 1, 2 // Select r, then a, then g, then b in that order.
4626#define SHDR_DETAIL_SWIZZLE_raga 0, 3, 1, 3 // Select r, then a, then g, then a in that order.
4627#define SHDR_DETAIL_SWIZZLE_rabr 0, 3, 2, 0 // Select r, then a, then b, then r in that order.
4628#define SHDR_DETAIL_SWIZZLE_rabg 0, 3, 2, 1 // Select r, then a, then b, then g in that order.
4629#define SHDR_DETAIL_SWIZZLE_rabb 0, 3, 2, 2 // Select r, then a, then b, then b in that order.
4630#define SHDR_DETAIL_SWIZZLE_raba 0, 3, 2, 3 // Select r, then a, then b, then a in that order.
4631#define SHDR_DETAIL_SWIZZLE_raar 0, 3, 3, 0 // Select r, then a, then a, then r in that order.
4632#define SHDR_DETAIL_SWIZZLE_raag 0, 3, 3, 1 // Select r, then a, then a, then g in that order.
4633#define SHDR_DETAIL_SWIZZLE_raab 0, 3, 3, 2 // Select r, then a, then a, then b in that order.
4634#define SHDR_DETAIL_SWIZZLE_raaa 0, 3, 3, 3 // Select r, then a, then a, then a in that order.
4635#define SHDR_DETAIL_SWIZZLE_grrr 1, 0, 0, 0 // Select g, then r, then r, then r in that order.
4636#define SHDR_DETAIL_SWIZZLE_grrg 1, 0, 0, 1 // Select g, then r, then r, then g in that order.
4637#define SHDR_DETAIL_SWIZZLE_grrb 1, 0, 0, 2 // Select g, then r, then r, then b in that order.
4638#define SHDR_DETAIL_SWIZZLE_grra 1, 0, 0, 3 // Select g, then r, then r, then a in that order.
4639#define SHDR_DETAIL_SWIZZLE_grgr 1, 0, 1, 0 // Select g, then r, then g, then r in that order.
4640#define SHDR_DETAIL_SWIZZLE_grgg 1, 0, 1, 1 // Select g, then r, then g, then g in that order.
4641#define SHDR_DETAIL_SWIZZLE_grgb 1, 0, 1, 2 // Select g, then r, then g, then b in that order.
4642#define SHDR_DETAIL_SWIZZLE_grga 1, 0, 1, 3 // Select g, then r, then g, then a in that order.
4643#define SHDR_DETAIL_SWIZZLE_grbr 1, 0, 2, 0 // Select g, then r, then b, then r in that order.
4644#define SHDR_DETAIL_SWIZZLE_grbg 1, 0, 2, 1 // Select g, then r, then b, then g in that order.
4645#define SHDR_DETAIL_SWIZZLE_grbb 1, 0, 2, 2 // Select g, then r, then b, then b in that order.
4646#define SHDR_DETAIL_SWIZZLE_grba 1, 0, 2, 3 // Select g, then r, then b, then a in that order.
4647#define SHDR_DETAIL_SWIZZLE_grar 1, 0, 3, 0 // Select g, then r, then a, then r in that order.
4648#define SHDR_DETAIL_SWIZZLE_grag 1, 0, 3, 1 // Select g, then r, then a, then g in that order.
4649#define SHDR_DETAIL_SWIZZLE_grab 1, 0, 3, 2 // Select g, then r, then a, then b in that order.
4650#define SHDR_DETAIL_SWIZZLE_graa 1, 0, 3, 3 // Select g, then r, then a, then a in that order.
4651#define SHDR_DETAIL_SWIZZLE_ggrr 1, 1, 0, 0 // Select g, then g, then r, then r in that order.
4652#define SHDR_DETAIL_SWIZZLE_ggrg 1, 1, 0, 1 // Select g, then g, then r, then g in that order.
4653#define SHDR_DETAIL_SWIZZLE_ggrb 1, 1, 0, 2 // Select g, then g, then r, then b in that order.
4654#define SHDR_DETAIL_SWIZZLE_ggra 1, 1, 0, 3 // Select g, then g, then r, then a in that order.
4655#define SHDR_DETAIL_SWIZZLE_gggr 1, 1, 1, 0 // Select g, then g, then g, then r in that order.
4656#define SHDR_DETAIL_SWIZZLE_gggg 1, 1, 1, 1 // Select g, then g, then g, then g in that order.
4657#define SHDR_DETAIL_SWIZZLE_gggb 1, 1, 1, 2 // Select g, then g, then g, then b in that order.
4658#define SHDR_DETAIL_SWIZZLE_ggga 1, 1, 1, 3 // Select g, then g, then g, then a in that order.
4659#define SHDR_DETAIL_SWIZZLE_ggbr 1, 1, 2, 0 // Select g, then g, then b, then r in that order.
4660#define SHDR_DETAIL_SWIZZLE_ggbg 1, 1, 2, 1 // Select g, then g, then b, then g in that order.
4661#define SHDR_DETAIL_SWIZZLE_ggbb 1, 1, 2, 2 // Select g, then g, then b, then b in that order.
4662#define SHDR_DETAIL_SWIZZLE_ggba 1, 1, 2, 3 // Select g, then g, then b, then a in that order.
4663#define SHDR_DETAIL_SWIZZLE_ggar 1, 1, 3, 0 // Select g, then g, then a, then r in that order.
4664#define SHDR_DETAIL_SWIZZLE_ggag 1, 1, 3, 1 // Select g, then g, then a, then g in that order.
4665#define SHDR_DETAIL_SWIZZLE_ggab 1, 1, 3, 2 // Select g, then g, then a, then b in that order.
4666#define SHDR_DETAIL_SWIZZLE_ggaa 1, 1, 3, 3 // Select g, then g, then a, then a in that order.
4667#define SHDR_DETAIL_SWIZZLE_gbrr 1, 2, 0, 0 // Select g, then b, then r, then r in that order.
4668#define SHDR_DETAIL_SWIZZLE_gbrg 1, 2, 0, 1 // Select g, then b, then r, then g in that order.
4669#define SHDR_DETAIL_SWIZZLE_gbrb 1, 2, 0, 2 // Select g, then b, then r, then b in that order.
4670#define SHDR_DETAIL_SWIZZLE_gbra 1, 2, 0, 3 // Select g, then b, then r, then a in that order.
4671#define SHDR_DETAIL_SWIZZLE_gbgr 1, 2, 1, 0 // Select g, then b, then g, then r in that order.
4672#define SHDR_DETAIL_SWIZZLE_gbgg 1, 2, 1, 1 // Select g, then b, then g, then g in that order.
4673#define SHDR_DETAIL_SWIZZLE_gbgb 1, 2, 1, 2 // Select g, then b, then g, then b in that order.
4674#define SHDR_DETAIL_SWIZZLE_gbga 1, 2, 1, 3 // Select g, then b, then g, then a in that order.
4675#define SHDR_DETAIL_SWIZZLE_gbbr 1, 2, 2, 0 // Select g, then b, then b, then r in that order.
4676#define SHDR_DETAIL_SWIZZLE_gbbg 1, 2, 2, 1 // Select g, then b, then b, then g in that order.
4677#define SHDR_DETAIL_SWIZZLE_gbbb 1, 2, 2, 2 // Select g, then b, then b, then b in that order.
4678#define SHDR_DETAIL_SWIZZLE_gbba 1, 2, 2, 3 // Select g, then b, then b, then a in that order.
4679#define SHDR_DETAIL_SWIZZLE_gbar 1, 2, 3, 0 // Select g, then b, then a, then r in that order.
4680#define SHDR_DETAIL_SWIZZLE_gbag 1, 2, 3, 1 // Select g, then b, then a, then g in that order.
4681#define SHDR_DETAIL_SWIZZLE_gbab 1, 2, 3, 2 // Select g, then b, then a, then b in that order.
4682#define SHDR_DETAIL_SWIZZLE_gbaa 1, 2, 3, 3 // Select g, then b, then a, then a in that order.
4683#define SHDR_DETAIL_SWIZZLE_garr 1, 3, 0, 0 // Select g, then a, then r, then r in that order.
4684#define SHDR_DETAIL_SWIZZLE_garg 1, 3, 0, 1 // Select g, then a, then r, then g in that order.
4685#define SHDR_DETAIL_SWIZZLE_garb 1, 3, 0, 2 // Select g, then a, then r, then b in that order.
4686#define SHDR_DETAIL_SWIZZLE_gara 1, 3, 0, 3 // Select g, then a, then r, then a in that order.
4687#define SHDR_DETAIL_SWIZZLE_gagr 1, 3, 1, 0 // Select g, then a, then g, then r in that order.
4688#define SHDR_DETAIL_SWIZZLE_gagg 1, 3, 1, 1 // Select g, then a, then g, then g in that order.
4689#define SHDR_DETAIL_SWIZZLE_gagb 1, 3, 1, 2 // Select g, then a, then g, then b in that order.
4690#define SHDR_DETAIL_SWIZZLE_gaga 1, 3, 1, 3 // Select g, then a, then g, then a in that order.
4691#define SHDR_DETAIL_SWIZZLE_gabr 1, 3, 2, 0 // Select g, then a, then b, then r in that order.
4692#define SHDR_DETAIL_SWIZZLE_gabg 1, 3, 2, 1 // Select g, then a, then b, then g in that order.
4693#define SHDR_DETAIL_SWIZZLE_gabb 1, 3, 2, 2 // Select g, then a, then b, then b in that order.
4694#define SHDR_DETAIL_SWIZZLE_gaba 1, 3, 2, 3 // Select g, then a, then b, then a in that order.
4695#define SHDR_DETAIL_SWIZZLE_gaar 1, 3, 3, 0 // Select g, then a, then a, then r in that order.
4696#define SHDR_DETAIL_SWIZZLE_gaag 1, 3, 3, 1 // Select g, then a, then a, then g in that order.
4697#define SHDR_DETAIL_SWIZZLE_gaab 1, 3, 3, 2 // Select g, then a, then a, then b in that order.
4698#define SHDR_DETAIL_SWIZZLE_gaaa 1, 3, 3, 3 // Select g, then a, then a, then a in that order.
4699#define SHDR_DETAIL_SWIZZLE_brrr 2, 0, 0, 0 // Select b, then r, then r, then r in that order.
4700#define SHDR_DETAIL_SWIZZLE_brrg 2, 0, 0, 1 // Select b, then r, then r, then g in that order.
4701#define SHDR_DETAIL_SWIZZLE_brrb 2, 0, 0, 2 // Select b, then r, then r, then b in that order.
4702#define SHDR_DETAIL_SWIZZLE_brra 2, 0, 0, 3 // Select b, then r, then r, then a in that order.
4703#define SHDR_DETAIL_SWIZZLE_brgr 2, 0, 1, 0 // Select b, then r, then g, then r in that order.
4704#define SHDR_DETAIL_SWIZZLE_brgg 2, 0, 1, 1 // Select b, then r, then g, then g in that order.
4705#define SHDR_DETAIL_SWIZZLE_brgb 2, 0, 1, 2 // Select b, then r, then g, then b in that order.
4706#define SHDR_DETAIL_SWIZZLE_brga 2, 0, 1, 3 // Select b, then r, then g, then a in that order.
4707#define SHDR_DETAIL_SWIZZLE_brbr 2, 0, 2, 0 // Select b, then r, then b, then r in that order.
4708#define SHDR_DETAIL_SWIZZLE_brbg 2, 0, 2, 1 // Select b, then r, then b, then g in that order.
4709#define SHDR_DETAIL_SWIZZLE_brbb 2, 0, 2, 2 // Select b, then r, then b, then b in that order.
4710#define SHDR_DETAIL_SWIZZLE_brba 2, 0, 2, 3 // Select b, then r, then b, then a in that order.
4711#define SHDR_DETAIL_SWIZZLE_brar 2, 0, 3, 0 // Select b, then r, then a, then r in that order.
4712#define SHDR_DETAIL_SWIZZLE_brag 2, 0, 3, 1 // Select b, then r, then a, then g in that order.
4713#define SHDR_DETAIL_SWIZZLE_brab 2, 0, 3, 2 // Select b, then r, then a, then b in that order.
4714#define SHDR_DETAIL_SWIZZLE_braa 2, 0, 3, 3 // Select b, then r, then a, then a in that order.
4715#define SHDR_DETAIL_SWIZZLE_bgrr 2, 1, 0, 0 // Select b, then g, then r, then r in that order.
4716#define SHDR_DETAIL_SWIZZLE_bgrg 2, 1, 0, 1 // Select b, then g, then r, then g in that order.
4717#define SHDR_DETAIL_SWIZZLE_bgrb 2, 1, 0, 2 // Select b, then g, then r, then b in that order.
4718#define SHDR_DETAIL_SWIZZLE_bgra 2, 1, 0, 3 // Select b, then g, then r, then a in that order.
4719#define SHDR_DETAIL_SWIZZLE_bggr 2, 1, 1, 0 // Select b, then g, then g, then r in that order.
4720#define SHDR_DETAIL_SWIZZLE_bggg 2, 1, 1, 1 // Select b, then g, then g, then g in that order.
4721#define SHDR_DETAIL_SWIZZLE_bggb 2, 1, 1, 2 // Select b, then g, then g, then b in that order.
4722#define SHDR_DETAIL_SWIZZLE_bgga 2, 1, 1, 3 // Select b, then g, then g, then a in that order.
4723#define SHDR_DETAIL_SWIZZLE_bgbr 2, 1, 2, 0 // Select b, then g, then b, then r in that order.
4724#define SHDR_DETAIL_SWIZZLE_bgbg 2, 1, 2, 1 // Select b, then g, then b, then g in that order.
4725#define SHDR_DETAIL_SWIZZLE_bgbb 2, 1, 2, 2 // Select b, then g, then b, then b in that order.
4726#define SHDR_DETAIL_SWIZZLE_bgba 2, 1, 2, 3 // Select b, then g, then b, then a in that order.
4727#define SHDR_DETAIL_SWIZZLE_bgar 2, 1, 3, 0 // Select b, then g, then a, then r in that order.
4728#define SHDR_DETAIL_SWIZZLE_bgag 2, 1, 3, 1 // Select b, then g, then a, then g in that order.
4729#define SHDR_DETAIL_SWIZZLE_bgab 2, 1, 3, 2 // Select b, then g, then a, then b in that order.
4730#define SHDR_DETAIL_SWIZZLE_bgaa 2, 1, 3, 3 // Select b, then g, then a, then a in that order.
4731#define SHDR_DETAIL_SWIZZLE_bbrr 2, 2, 0, 0 // Select b, then b, then r, then r in that order.
4732#define SHDR_DETAIL_SWIZZLE_bbrg 2, 2, 0, 1 // Select b, then b, then r, then g in that order.
4733#define SHDR_DETAIL_SWIZZLE_bbrb 2, 2, 0, 2 // Select b, then b, then r, then b in that order.
4734#define SHDR_DETAIL_SWIZZLE_bbra 2, 2, 0, 3 // Select b, then b, then r, then a in that order.
4735#define SHDR_DETAIL_SWIZZLE_bbgr 2, 2, 1, 0 // Select b, then b, then g, then r in that order.
4736#define SHDR_DETAIL_SWIZZLE_bbgg 2, 2, 1, 1 // Select b, then b, then g, then g in that order.
4737#define SHDR_DETAIL_SWIZZLE_bbgb 2, 2, 1, 2 // Select b, then b, then g, then b in that order.
4738#define SHDR_DETAIL_SWIZZLE_bbga 2, 2, 1, 3 // Select b, then b, then g, then a in that order.
4739#define SHDR_DETAIL_SWIZZLE_bbbr 2, 2, 2, 0 // Select b, then b, then b, then r in that order.
4740#define SHDR_DETAIL_SWIZZLE_bbbg 2, 2, 2, 1 // Select b, then b, then b, then g in that order.
4741#define SHDR_DETAIL_SWIZZLE_bbbb 2, 2, 2, 2 // Select b, then b, then b, then b in that order.
4742#define SHDR_DETAIL_SWIZZLE_bbba 2, 2, 2, 3 // Select b, then b, then b, then a in that order.
4743#define SHDR_DETAIL_SWIZZLE_bbar 2, 2, 3, 0 // Select b, then b, then a, then r in that order.
4744#define SHDR_DETAIL_SWIZZLE_bbag 2, 2, 3, 1 // Select b, then b, then a, then g in that order.
4745#define SHDR_DETAIL_SWIZZLE_bbab 2, 2, 3, 2 // Select b, then b, then a, then b in that order.
4746#define SHDR_DETAIL_SWIZZLE_bbaa 2, 2, 3, 3 // Select b, then b, then a, then a in that order.
4747#define SHDR_DETAIL_SWIZZLE_barr 2, 3, 0, 0 // Select b, then a, then r, then r in that order.
4748#define SHDR_DETAIL_SWIZZLE_barg 2, 3, 0, 1 // Select b, then a, then r, then g in that order.
4749#define SHDR_DETAIL_SWIZZLE_barb 2, 3, 0, 2 // Select b, then a, then r, then b in that order.
4750#define SHDR_DETAIL_SWIZZLE_bara 2, 3, 0, 3 // Select b, then a, then r, then a in that order.
4751#define SHDR_DETAIL_SWIZZLE_bagr 2, 3, 1, 0 // Select b, then a, then g, then r in that order.
4752#define SHDR_DETAIL_SWIZZLE_bagg 2, 3, 1, 1 // Select b, then a, then g, then g in that order.
4753#define SHDR_DETAIL_SWIZZLE_bagb 2, 3, 1, 2 // Select b, then a, then g, then b in that order.
4754#define SHDR_DETAIL_SWIZZLE_baga 2, 3, 1, 3 // Select b, then a, then g, then a in that order.
4755#define SHDR_DETAIL_SWIZZLE_babr 2, 3, 2, 0 // Select b, then a, then b, then r in that order.
4756#define SHDR_DETAIL_SWIZZLE_babg 2, 3, 2, 1 // Select b, then a, then b, then g in that order.
4757#define SHDR_DETAIL_SWIZZLE_babb 2, 3, 2, 2 // Select b, then a, then b, then b in that order.
4758#define SHDR_DETAIL_SWIZZLE_baba 2, 3, 2, 3 // Select b, then a, then b, then a in that order.
4759#define SHDR_DETAIL_SWIZZLE_baar 2, 3, 3, 0 // Select b, then a, then a, then r in that order.
4760#define SHDR_DETAIL_SWIZZLE_baag 2, 3, 3, 1 // Select b, then a, then a, then g in that order.
4761#define SHDR_DETAIL_SWIZZLE_baab 2, 3, 3, 2 // Select b, then a, then a, then b in that order.
4762#define SHDR_DETAIL_SWIZZLE_baaa 2, 3, 3, 3 // Select b, then a, then a, then a in that order.
4763#define SHDR_DETAIL_SWIZZLE_arrr 3, 0, 0, 0 // Select a, then r, then r, then r in that order.
4764#define SHDR_DETAIL_SWIZZLE_arrg 3, 0, 0, 1 // Select a, then r, then r, then g in that order.
4765#define SHDR_DETAIL_SWIZZLE_arrb 3, 0, 0, 2 // Select a, then r, then r, then b in that order.
4766#define SHDR_DETAIL_SWIZZLE_arra 3, 0, 0, 3 // Select a, then r, then r, then a in that order.
4767#define SHDR_DETAIL_SWIZZLE_argr 3, 0, 1, 0 // Select a, then r, then g, then r in that order.
4768#define SHDR_DETAIL_SWIZZLE_argg 3, 0, 1, 1 // Select a, then r, then g, then g in that order.
4769#define SHDR_DETAIL_SWIZZLE_argb 3, 0, 1, 2 // Select a, then r, then g, then b in that order.
4770#define SHDR_DETAIL_SWIZZLE_arga 3, 0, 1, 3 // Select a, then r, then g, then a in that order.
4771#define SHDR_DETAIL_SWIZZLE_arbr 3, 0, 2, 0 // Select a, then r, then b, then r in that order.
4772#define SHDR_DETAIL_SWIZZLE_arbg 3, 0, 2, 1 // Select a, then r, then b, then g in that order.
4773#define SHDR_DETAIL_SWIZZLE_arbb 3, 0, 2, 2 // Select a, then r, then b, then b in that order.
4774#define SHDR_DETAIL_SWIZZLE_arba 3, 0, 2, 3 // Select a, then r, then b, then a in that order.
4775#define SHDR_DETAIL_SWIZZLE_arar 3, 0, 3, 0 // Select a, then r, then a, then r in that order.
4776#define SHDR_DETAIL_SWIZZLE_arag 3, 0, 3, 1 // Select a, then r, then a, then g in that order.
4777#define SHDR_DETAIL_SWIZZLE_arab 3, 0, 3, 2 // Select a, then r, then a, then b in that order.
4778#define SHDR_DETAIL_SWIZZLE_araa 3, 0, 3, 3 // Select a, then r, then a, then a in that order.
4779#define SHDR_DETAIL_SWIZZLE_agrr 3, 1, 0, 0 // Select a, then g, then r, then r in that order.
4780#define SHDR_DETAIL_SWIZZLE_agrg 3, 1, 0, 1 // Select a, then g, then r, then g in that order.
4781#define SHDR_DETAIL_SWIZZLE_agrb 3, 1, 0, 2 // Select a, then g, then r, then b in that order.
4782#define SHDR_DETAIL_SWIZZLE_agra 3, 1, 0, 3 // Select a, then g, then r, then a in that order.
4783#define SHDR_DETAIL_SWIZZLE_aggr 3, 1, 1, 0 // Select a, then g, then g, then r in that order.
4784#define SHDR_DETAIL_SWIZZLE_aggg 3, 1, 1, 1 // Select a, then g, then g, then g in that order.
4785#define SHDR_DETAIL_SWIZZLE_aggb 3, 1, 1, 2 // Select a, then g, then g, then b in that order.
4786#define SHDR_DETAIL_SWIZZLE_agga 3, 1, 1, 3 // Select a, then g, then g, then a in that order.
4787#define SHDR_DETAIL_SWIZZLE_agbr 3, 1, 2, 0 // Select a, then g, then b, then r in that order.
4788#define SHDR_DETAIL_SWIZZLE_agbg 3, 1, 2, 1 // Select a, then g, then b, then g in that order.
4789#define SHDR_DETAIL_SWIZZLE_agbb 3, 1, 2, 2 // Select a, then g, then b, then b in that order.
4790#define SHDR_DETAIL_SWIZZLE_agba 3, 1, 2, 3 // Select a, then g, then b, then a in that order.
4791#define SHDR_DETAIL_SWIZZLE_agar 3, 1, 3, 0 // Select a, then g, then a, then r in that order.
4792#define SHDR_DETAIL_SWIZZLE_agag 3, 1, 3, 1 // Select a, then g, then a, then g in that order.
4793#define SHDR_DETAIL_SWIZZLE_agab 3, 1, 3, 2 // Select a, then g, then a, then b in that order.
4794#define SHDR_DETAIL_SWIZZLE_agaa 3, 1, 3, 3 // Select a, then g, then a, then a in that order.
4795#define SHDR_DETAIL_SWIZZLE_abrr 3, 2, 0, 0 // Select a, then b, then r, then r in that order.
4796#define SHDR_DETAIL_SWIZZLE_abrg 3, 2, 0, 1 // Select a, then b, then r, then g in that order.
4797#define SHDR_DETAIL_SWIZZLE_abrb 3, 2, 0, 2 // Select a, then b, then r, then b in that order.
4798#define SHDR_DETAIL_SWIZZLE_abra 3, 2, 0, 3 // Select a, then b, then r, then a in that order.
4799#define SHDR_DETAIL_SWIZZLE_abgr 3, 2, 1, 0 // Select a, then b, then g, then r in that order.
4800#define SHDR_DETAIL_SWIZZLE_abgg 3, 2, 1, 1 // Select a, then b, then g, then g in that order.
4801#define SHDR_DETAIL_SWIZZLE_abgb 3, 2, 1, 2 // Select a, then b, then g, then b in that order.
4802#define SHDR_DETAIL_SWIZZLE_abga 3, 2, 1, 3 // Select a, then b, then g, then a in that order.
4803#define SHDR_DETAIL_SWIZZLE_abbr 3, 2, 2, 0 // Select a, then b, then b, then r in that order.
4804#define SHDR_DETAIL_SWIZZLE_abbg 3, 2, 2, 1 // Select a, then b, then b, then g in that order.
4805#define SHDR_DETAIL_SWIZZLE_abbb 3, 2, 2, 2 // Select a, then b, then b, then b in that order.
4806#define SHDR_DETAIL_SWIZZLE_abba 3, 2, 2, 3 // Select a, then b, then b, then a in that order.
4807#define SHDR_DETAIL_SWIZZLE_abar 3, 2, 3, 0 // Select a, then b, then a, then r in that order.
4808#define SHDR_DETAIL_SWIZZLE_abag 3, 2, 3, 1 // Select a, then b, then a, then g in that order.
4809#define SHDR_DETAIL_SWIZZLE_abab 3, 2, 3, 2 // Select a, then b, then a, then b in that order.
4810#define SHDR_DETAIL_SWIZZLE_abaa 3, 2, 3, 3 // Select a, then b, then a, then a in that order.
4811#define SHDR_DETAIL_SWIZZLE_aarr 3, 3, 0, 0 // Select a, then a, then r, then r in that order.
4812#define SHDR_DETAIL_SWIZZLE_aarg 3, 3, 0, 1 // Select a, then a, then r, then g in that order.
4813#define SHDR_DETAIL_SWIZZLE_aarb 3, 3, 0, 2 // Select a, then a, then r, then b in that order.
4814#define SHDR_DETAIL_SWIZZLE_aara 3, 3, 0, 3 // Select a, then a, then r, then a in that order.
4815#define SHDR_DETAIL_SWIZZLE_aagr 3, 3, 1, 0 // Select a, then a, then g, then r in that order.
4816#define SHDR_DETAIL_SWIZZLE_aagg 3, 3, 1, 1 // Select a, then a, then g, then g in that order.
4817#define SHDR_DETAIL_SWIZZLE_aagb 3, 3, 1, 2 // Select a, then a, then g, then b in that order.
4818#define SHDR_DETAIL_SWIZZLE_aaga 3, 3, 1, 3 // Select a, then a, then g, then a in that order.
4819#define SHDR_DETAIL_SWIZZLE_aabr 3, 3, 2, 0 // Select a, then a, then b, then r in that order.
4820#define SHDR_DETAIL_SWIZZLE_aabg 3, 3, 2, 1 // Select a, then a, then b, then g in that order.
4821#define SHDR_DETAIL_SWIZZLE_aabb 3, 3, 2, 2 // Select a, then a, then b, then b in that order.
4822#define SHDR_DETAIL_SWIZZLE_aaba 3, 3, 2, 3 // Select a, then a, then b, then a in that order.
4823#define SHDR_DETAIL_SWIZZLE_aaar 3, 3, 3, 0 // Select a, then a, then a, then r in that order.
4824#define SHDR_DETAIL_SWIZZLE_aaag 3, 3, 3, 1 // Select a, then a, then a, then g in that order.
4825#define SHDR_DETAIL_SWIZZLE_aaab 3, 3, 3, 2 // Select a, then a, then a, then b in that order.
4826#define SHDR_DETAIL_SWIZZLE_aaaa 3, 3, 3, 3 // Select a, then a, then a, then a in that order.
4827#define SHDR_DETAIL_SWIZZLE_s 0 // Select the s component.
4828#define SHDR_DETAIL_SWIZZLE_t 1 // Select the t component.
4829#define SHDR_DETAIL_SWIZZLE_p 2 // Select the p component.
4830#define SHDR_DETAIL_SWIZZLE_q 3 // Select the q component.
4831#define SHDR_DETAIL_SWIZZLE_ss 0, 0 // Select s, then s in that order.
4832#define SHDR_DETAIL_SWIZZLE_st 0, 1 // Select s, then t in that order.
4833#define SHDR_DETAIL_SWIZZLE_sp 0, 2 // Select s, then p in that order.
4834#define SHDR_DETAIL_SWIZZLE_sq 0, 3 // Select s, then q in that order.
4835#define SHDR_DETAIL_SWIZZLE_ts 1, 0 // Select t, then s in that order.
4836#define SHDR_DETAIL_SWIZZLE_tt 1, 1 // Select t, then t in that order.
4837#define SHDR_DETAIL_SWIZZLE_tp 1, 2 // Select t, then p in that order.
4838#define SHDR_DETAIL_SWIZZLE_tq 1, 3 // Select t, then q in that order.
4839#define SHDR_DETAIL_SWIZZLE_ps 2, 0 // Select p, then s in that order.
4840#define SHDR_DETAIL_SWIZZLE_pt 2, 1 // Select p, then t in that order.
4841#define SHDR_DETAIL_SWIZZLE_pp 2, 2 // Select p, then p in that order.
4842#define SHDR_DETAIL_SWIZZLE_pq 2, 3 // Select p, then q in that order.
4843#define SHDR_DETAIL_SWIZZLE_qs 3, 0 // Select q, then s in that order.
4844#define SHDR_DETAIL_SWIZZLE_qt 3, 1 // Select q, then t in that order.
4845#define SHDR_DETAIL_SWIZZLE_qp 3, 2 // Select q, then p in that order.
4846#define SHDR_DETAIL_SWIZZLE_qq 3, 3 // Select q, then q in that order.
4847#define SHDR_DETAIL_SWIZZLE_sss 0, 0, 0 // Select s, then s, then s in that order.
4848#define SHDR_DETAIL_SWIZZLE_sst 0, 0, 1 // Select s, then s, then t in that order.
4849#define SHDR_DETAIL_SWIZZLE_ssp 0, 0, 2 // Select s, then s, then p in that order.
4850#define SHDR_DETAIL_SWIZZLE_ssq 0, 0, 3 // Select s, then s, then q in that order.
4851#define SHDR_DETAIL_SWIZZLE_sts 0, 1, 0 // Select s, then t, then s in that order.
4852#define SHDR_DETAIL_SWIZZLE_stt 0, 1, 1 // Select s, then t, then t in that order.
4853#define SHDR_DETAIL_SWIZZLE_stp 0, 1, 2 // Select s, then t, then p in that order.
4854#define SHDR_DETAIL_SWIZZLE_stq 0, 1, 3 // Select s, then t, then q in that order.
4855#define SHDR_DETAIL_SWIZZLE_sps 0, 2, 0 // Select s, then p, then s in that order.
4856#define SHDR_DETAIL_SWIZZLE_spt 0, 2, 1 // Select s, then p, then t in that order.
4857#define SHDR_DETAIL_SWIZZLE_spp 0, 2, 2 // Select s, then p, then p in that order.
4858#define SHDR_DETAIL_SWIZZLE_spq 0, 2, 3 // Select s, then p, then q in that order.
4859#define SHDR_DETAIL_SWIZZLE_sqs 0, 3, 0 // Select s, then q, then s in that order.
4860#define SHDR_DETAIL_SWIZZLE_sqt 0, 3, 1 // Select s, then q, then t in that order.
4861#define SHDR_DETAIL_SWIZZLE_sqp 0, 3, 2 // Select s, then q, then p in that order.
4862#define SHDR_DETAIL_SWIZZLE_sqq 0, 3, 3 // Select s, then q, then q in that order.
4863#define SHDR_DETAIL_SWIZZLE_tss 1, 0, 0 // Select t, then s, then s in that order.
4864#define SHDR_DETAIL_SWIZZLE_tst 1, 0, 1 // Select t, then s, then t in that order.
4865#define SHDR_DETAIL_SWIZZLE_tsp 1, 0, 2 // Select t, then s, then p in that order.
4866#define SHDR_DETAIL_SWIZZLE_tsq 1, 0, 3 // Select t, then s, then q in that order.
4867#define SHDR_DETAIL_SWIZZLE_tts 1, 1, 0 // Select t, then t, then s in that order.
4868#define SHDR_DETAIL_SWIZZLE_ttt 1, 1, 1 // Select t, then t, then t in that order.
4869#define SHDR_DETAIL_SWIZZLE_ttp 1, 1, 2 // Select t, then t, then p in that order.
4870#define SHDR_DETAIL_SWIZZLE_ttq 1, 1, 3 // Select t, then t, then q in that order.
4871#define SHDR_DETAIL_SWIZZLE_tps 1, 2, 0 // Select t, then p, then s in that order.
4872#define SHDR_DETAIL_SWIZZLE_tpt 1, 2, 1 // Select t, then p, then t in that order.
4873#define SHDR_DETAIL_SWIZZLE_tpp 1, 2, 2 // Select t, then p, then p in that order.
4874#define SHDR_DETAIL_SWIZZLE_tpq 1, 2, 3 // Select t, then p, then q in that order.
4875#define SHDR_DETAIL_SWIZZLE_tqs 1, 3, 0 // Select t, then q, then s in that order.
4876#define SHDR_DETAIL_SWIZZLE_tqt 1, 3, 1 // Select t, then q, then t in that order.
4877#define SHDR_DETAIL_SWIZZLE_tqp 1, 3, 2 // Select t, then q, then p in that order.
4878#define SHDR_DETAIL_SWIZZLE_tqq 1, 3, 3 // Select t, then q, then q in that order.
4879#define SHDR_DETAIL_SWIZZLE_pss 2, 0, 0 // Select p, then s, then s in that order.
4880#define SHDR_DETAIL_SWIZZLE_pst 2, 0, 1 // Select p, then s, then t in that order.
4881#define SHDR_DETAIL_SWIZZLE_psp 2, 0, 2 // Select p, then s, then p in that order.
4882#define SHDR_DETAIL_SWIZZLE_psq 2, 0, 3 // Select p, then s, then q in that order.
4883#define SHDR_DETAIL_SWIZZLE_pts 2, 1, 0 // Select p, then t, then s in that order.
4884#define SHDR_DETAIL_SWIZZLE_ptt 2, 1, 1 // Select p, then t, then t in that order.
4885#define SHDR_DETAIL_SWIZZLE_ptp 2, 1, 2 // Select p, then t, then p in that order.
4886#define SHDR_DETAIL_SWIZZLE_ptq 2, 1, 3 // Select p, then t, then q in that order.
4887#define SHDR_DETAIL_SWIZZLE_pps 2, 2, 0 // Select p, then p, then s in that order.
4888#define SHDR_DETAIL_SWIZZLE_ppt 2, 2, 1 // Select p, then p, then t in that order.
4889#define SHDR_DETAIL_SWIZZLE_ppp 2, 2, 2 // Select p, then p, then p in that order.
4890#define SHDR_DETAIL_SWIZZLE_ppq 2, 2, 3 // Select p, then p, then q in that order.
4891#define SHDR_DETAIL_SWIZZLE_pqs 2, 3, 0 // Select p, then q, then s in that order.
4892#define SHDR_DETAIL_SWIZZLE_pqt 2, 3, 1 // Select p, then q, then t in that order.
4893#define SHDR_DETAIL_SWIZZLE_pqp 2, 3, 2 // Select p, then q, then p in that order.
4894#define SHDR_DETAIL_SWIZZLE_pqq 2, 3, 3 // Select p, then q, then q in that order.
4895#define SHDR_DETAIL_SWIZZLE_qss 3, 0, 0 // Select q, then s, then s in that order.
4896#define SHDR_DETAIL_SWIZZLE_qst 3, 0, 1 // Select q, then s, then t in that order.
4897#define SHDR_DETAIL_SWIZZLE_qsp 3, 0, 2 // Select q, then s, then p in that order.
4898#define SHDR_DETAIL_SWIZZLE_qsq 3, 0, 3 // Select q, then s, then q in that order.
4899#define SHDR_DETAIL_SWIZZLE_qts 3, 1, 0 // Select q, then t, then s in that order.
4900#define SHDR_DETAIL_SWIZZLE_qtt 3, 1, 1 // Select q, then t, then t in that order.
4901#define SHDR_DETAIL_SWIZZLE_qtp 3, 1, 2 // Select q, then t, then p in that order.
4902#define SHDR_DETAIL_SWIZZLE_qtq 3, 1, 3 // Select q, then t, then q in that order.
4903#define SHDR_DETAIL_SWIZZLE_qps 3, 2, 0 // Select q, then p, then s in that order.
4904#define SHDR_DETAIL_SWIZZLE_qpt 3, 2, 1 // Select q, then p, then t in that order.
4905#define SHDR_DETAIL_SWIZZLE_qpp 3, 2, 2 // Select q, then p, then p in that order.
4906#define SHDR_DETAIL_SWIZZLE_qpq 3, 2, 3 // Select q, then p, then q in that order.
4907#define SHDR_DETAIL_SWIZZLE_qqs 3, 3, 0 // Select q, then q, then s in that order.
4908#define SHDR_DETAIL_SWIZZLE_qqt 3, 3, 1 // Select q, then q, then t in that order.
4909#define SHDR_DETAIL_SWIZZLE_qqp 3, 3, 2 // Select q, then q, then p in that order.
4910#define SHDR_DETAIL_SWIZZLE_qqq 3, 3, 3 // Select q, then q, then q in that order.
4911#define SHDR_DETAIL_SWIZZLE_ssss 0, 0, 0, 0 // Select s, then s, then s, then s in that order.
4912#define SHDR_DETAIL_SWIZZLE_ssst 0, 0, 0, 1 // Select s, then s, then s, then t in that order.
4913#define SHDR_DETAIL_SWIZZLE_sssp 0, 0, 0, 2 // Select s, then s, then s, then p in that order.
4914#define SHDR_DETAIL_SWIZZLE_sssq 0, 0, 0, 3 // Select s, then s, then s, then q in that order.
4915#define SHDR_DETAIL_SWIZZLE_ssts 0, 0, 1, 0 // Select s, then s, then t, then s in that order.
4916#define SHDR_DETAIL_SWIZZLE_sstt 0, 0, 1, 1 // Select s, then s, then t, then t in that order.
4917#define SHDR_DETAIL_SWIZZLE_sstp 0, 0, 1, 2 // Select s, then s, then t, then p in that order.
4918#define SHDR_DETAIL_SWIZZLE_sstq 0, 0, 1, 3 // Select s, then s, then t, then q in that order.
4919#define SHDR_DETAIL_SWIZZLE_ssps 0, 0, 2, 0 // Select s, then s, then p, then s in that order.
4920#define SHDR_DETAIL_SWIZZLE_sspt 0, 0, 2, 1 // Select s, then s, then p, then t in that order.
4921#define SHDR_DETAIL_SWIZZLE_sspp 0, 0, 2, 2 // Select s, then s, then p, then p in that order.
4922#define SHDR_DETAIL_SWIZZLE_sspq 0, 0, 2, 3 // Select s, then s, then p, then q in that order.
4923#define SHDR_DETAIL_SWIZZLE_ssqs 0, 0, 3, 0 // Select s, then s, then q, then s in that order.
4924#define SHDR_DETAIL_SWIZZLE_ssqt 0, 0, 3, 1 // Select s, then s, then q, then t in that order.
4925#define SHDR_DETAIL_SWIZZLE_ssqp 0, 0, 3, 2 // Select s, then s, then q, then p in that order.
4926#define SHDR_DETAIL_SWIZZLE_ssqq 0, 0, 3, 3 // Select s, then s, then q, then q in that order.
4927#define SHDR_DETAIL_SWIZZLE_stss 0, 1, 0, 0 // Select s, then t, then s, then s in that order.
4928#define SHDR_DETAIL_SWIZZLE_stst 0, 1, 0, 1 // Select s, then t, then s, then t in that order.
4929#define SHDR_DETAIL_SWIZZLE_stsp 0, 1, 0, 2 // Select s, then t, then s, then p in that order.
4930#define SHDR_DETAIL_SWIZZLE_stsq 0, 1, 0, 3 // Select s, then t, then s, then q in that order.
4931#define SHDR_DETAIL_SWIZZLE_stts 0, 1, 1, 0 // Select s, then t, then t, then s in that order.
4932#define SHDR_DETAIL_SWIZZLE_sttt 0, 1, 1, 1 // Select s, then t, then t, then t in that order.
4933#define SHDR_DETAIL_SWIZZLE_sttp 0, 1, 1, 2 // Select s, then t, then t, then p in that order.
4934#define SHDR_DETAIL_SWIZZLE_sttq 0, 1, 1, 3 // Select s, then t, then t, then q in that order.
4935#define SHDR_DETAIL_SWIZZLE_stps 0, 1, 2, 0 // Select s, then t, then p, then s in that order.
4936#define SHDR_DETAIL_SWIZZLE_stpt 0, 1, 2, 1 // Select s, then t, then p, then t in that order.
4937#define SHDR_DETAIL_SWIZZLE_stpp 0, 1, 2, 2 // Select s, then t, then p, then p in that order.
4938#define SHDR_DETAIL_SWIZZLE_stpq 0, 1, 2, 3 // Select s, then t, then p, then q in that order.
4939#define SHDR_DETAIL_SWIZZLE_stqs 0, 1, 3, 0 // Select s, then t, then q, then s in that order.
4940#define SHDR_DETAIL_SWIZZLE_stqt 0, 1, 3, 1 // Select s, then t, then q, then t in that order.
4941#define SHDR_DETAIL_SWIZZLE_stqp 0, 1, 3, 2 // Select s, then t, then q, then p in that order.
4942#define SHDR_DETAIL_SWIZZLE_stqq 0, 1, 3, 3 // Select s, then t, then q, then q in that order.
4943#define SHDR_DETAIL_SWIZZLE_spss 0, 2, 0, 0 // Select s, then p, then s, then s in that order.
4944#define SHDR_DETAIL_SWIZZLE_spst 0, 2, 0, 1 // Select s, then p, then s, then t in that order.
4945#define SHDR_DETAIL_SWIZZLE_spsp 0, 2, 0, 2 // Select s, then p, then s, then p in that order.
4946#define SHDR_DETAIL_SWIZZLE_spsq 0, 2, 0, 3 // Select s, then p, then s, then q in that order.
4947#define SHDR_DETAIL_SWIZZLE_spts 0, 2, 1, 0 // Select s, then p, then t, then s in that order.
4948#define SHDR_DETAIL_SWIZZLE_sptt 0, 2, 1, 1 // Select s, then p, then t, then t in that order.
4949#define SHDR_DETAIL_SWIZZLE_sptp 0, 2, 1, 2 // Select s, then p, then t, then p in that order.
4950#define SHDR_DETAIL_SWIZZLE_sptq 0, 2, 1, 3 // Select s, then p, then t, then q in that order.
4951#define SHDR_DETAIL_SWIZZLE_spps 0, 2, 2, 0 // Select s, then p, then p, then s in that order.
4952#define SHDR_DETAIL_SWIZZLE_sppt 0, 2, 2, 1 // Select s, then p, then p, then t in that order.
4953#define SHDR_DETAIL_SWIZZLE_sppp 0, 2, 2, 2 // Select s, then p, then p, then p in that order.
4954#define SHDR_DETAIL_SWIZZLE_sppq 0, 2, 2, 3 // Select s, then p, then p, then q in that order.
4955#define SHDR_DETAIL_SWIZZLE_spqs 0, 2, 3, 0 // Select s, then p, then q, then s in that order.
4956#define SHDR_DETAIL_SWIZZLE_spqt 0, 2, 3, 1 // Select s, then p, then q, then t in that order.
4957#define SHDR_DETAIL_SWIZZLE_spqp 0, 2, 3, 2 // Select s, then p, then q, then p in that order.
4958#define SHDR_DETAIL_SWIZZLE_spqq 0, 2, 3, 3 // Select s, then p, then q, then q in that order.
4959#define SHDR_DETAIL_SWIZZLE_sqss 0, 3, 0, 0 // Select s, then q, then s, then s in that order.
4960#define SHDR_DETAIL_SWIZZLE_sqst 0, 3, 0, 1 // Select s, then q, then s, then t in that order.
4961#define SHDR_DETAIL_SWIZZLE_sqsp 0, 3, 0, 2 // Select s, then q, then s, then p in that order.
4962#define SHDR_DETAIL_SWIZZLE_sqsq 0, 3, 0, 3 // Select s, then q, then s, then q in that order.
4963#define SHDR_DETAIL_SWIZZLE_sqts 0, 3, 1, 0 // Select s, then q, then t, then s in that order.
4964#define SHDR_DETAIL_SWIZZLE_sqtt 0, 3, 1, 1 // Select s, then q, then t, then t in that order.
4965#define SHDR_DETAIL_SWIZZLE_sqtp 0, 3, 1, 2 // Select s, then q, then t, then p in that order.
4966#define SHDR_DETAIL_SWIZZLE_sqtq 0, 3, 1, 3 // Select s, then q, then t, then q in that order.
4967#define SHDR_DETAIL_SWIZZLE_sqps 0, 3, 2, 0 // Select s, then q, then p, then s in that order.
4968#define SHDR_DETAIL_SWIZZLE_sqpt 0, 3, 2, 1 // Select s, then q, then p, then t in that order.
4969#define SHDR_DETAIL_SWIZZLE_sqpp 0, 3, 2, 2 // Select s, then q, then p, then p in that order.
4970#define SHDR_DETAIL_SWIZZLE_sqpq 0, 3, 2, 3 // Select s, then q, then p, then q in that order.
4971#define SHDR_DETAIL_SWIZZLE_sqqs 0, 3, 3, 0 // Select s, then q, then q, then s in that order.
4972#define SHDR_DETAIL_SWIZZLE_sqqt 0, 3, 3, 1 // Select s, then q, then q, then t in that order.
4973#define SHDR_DETAIL_SWIZZLE_sqqp 0, 3, 3, 2 // Select s, then q, then q, then p in that order.
4974#define SHDR_DETAIL_SWIZZLE_sqqq 0, 3, 3, 3 // Select s, then q, then q, then q in that order.
4975#define SHDR_DETAIL_SWIZZLE_tsss 1, 0, 0, 0 // Select t, then s, then s, then s in that order.
4976#define SHDR_DETAIL_SWIZZLE_tsst 1, 0, 0, 1 // Select t, then s, then s, then t in that order.
4977#define SHDR_DETAIL_SWIZZLE_tssp 1, 0, 0, 2 // Select t, then s, then s, then p in that order.
4978#define SHDR_DETAIL_SWIZZLE_tssq 1, 0, 0, 3 // Select t, then s, then s, then q in that order.
4979#define SHDR_DETAIL_SWIZZLE_tsts 1, 0, 1, 0 // Select t, then s, then t, then s in that order.
4980#define SHDR_DETAIL_SWIZZLE_tstt 1, 0, 1, 1 // Select t, then s, then t, then t in that order.
4981#define SHDR_DETAIL_SWIZZLE_tstp 1, 0, 1, 2 // Select t, then s, then t, then p in that order.
4982#define SHDR_DETAIL_SWIZZLE_tstq 1, 0, 1, 3 // Select t, then s, then t, then q in that order.
4983#define SHDR_DETAIL_SWIZZLE_tsps 1, 0, 2, 0 // Select t, then s, then p, then s in that order.
4984#define SHDR_DETAIL_SWIZZLE_tspt 1, 0, 2, 1 // Select t, then s, then p, then t in that order.
4985#define SHDR_DETAIL_SWIZZLE_tspp 1, 0, 2, 2 // Select t, then s, then p, then p in that order.
4986#define SHDR_DETAIL_SWIZZLE_tspq 1, 0, 2, 3 // Select t, then s, then p, then q in that order.
4987#define SHDR_DETAIL_SWIZZLE_tsqs 1, 0, 3, 0 // Select t, then s, then q, then s in that order.
4988#define SHDR_DETAIL_SWIZZLE_tsqt 1, 0, 3, 1 // Select t, then s, then q, then t in that order.
4989#define SHDR_DETAIL_SWIZZLE_tsqp 1, 0, 3, 2 // Select t, then s, then q, then p in that order.
4990#define SHDR_DETAIL_SWIZZLE_tsqq 1, 0, 3, 3 // Select t, then s, then q, then q in that order.
4991#define SHDR_DETAIL_SWIZZLE_ttss 1, 1, 0, 0 // Select t, then t, then s, then s in that order.
4992#define SHDR_DETAIL_SWIZZLE_ttst 1, 1, 0, 1 // Select t, then t, then s, then t in that order.
4993#define SHDR_DETAIL_SWIZZLE_ttsp 1, 1, 0, 2 // Select t, then t, then s, then p in that order.
4994#define SHDR_DETAIL_SWIZZLE_ttsq 1, 1, 0, 3 // Select t, then t, then s, then q in that order.
4995#define SHDR_DETAIL_SWIZZLE_ttts 1, 1, 1, 0 // Select t, then t, then t, then s in that order.
4996#define SHDR_DETAIL_SWIZZLE_tttt 1, 1, 1, 1 // Select t, then t, then t, then t in that order.
4997#define SHDR_DETAIL_SWIZZLE_tttp 1, 1, 1, 2 // Select t, then t, then t, then p in that order.
4998#define SHDR_DETAIL_SWIZZLE_tttq 1, 1, 1, 3 // Select t, then t, then t, then q in that order.
4999#define SHDR_DETAIL_SWIZZLE_ttps 1, 1, 2, 0 // Select t, then t, then p, then s in that order.
5000#define SHDR_DETAIL_SWIZZLE_ttpt 1, 1, 2, 1 // Select t, then t, then p, then t in that order.
5001#define SHDR_DETAIL_SWIZZLE_ttpp 1, 1, 2, 2 // Select t, then t, then p, then p in that order.
5002#define SHDR_DETAIL_SWIZZLE_ttpq 1, 1, 2, 3 // Select t, then t, then p, then q in that order.
5003#define SHDR_DETAIL_SWIZZLE_ttqs 1, 1, 3, 0 // Select t, then t, then q, then s in that order.
5004#define SHDR_DETAIL_SWIZZLE_ttqt 1, 1, 3, 1 // Select t, then t, then q, then t in that order.
5005#define SHDR_DETAIL_SWIZZLE_ttqp 1, 1, 3, 2 // Select t, then t, then q, then p in that order.
5006#define SHDR_DETAIL_SWIZZLE_ttqq 1, 1, 3, 3 // Select t, then t, then q, then q in that order.
5007#define SHDR_DETAIL_SWIZZLE_tpss 1, 2, 0, 0 // Select t, then p, then s, then s in that order.
5008#define SHDR_DETAIL_SWIZZLE_tpst 1, 2, 0, 1 // Select t, then p, then s, then t in that order.
5009#define SHDR_DETAIL_SWIZZLE_tpsp 1, 2, 0, 2 // Select t, then p, then s, then p in that order.
5010#define SHDR_DETAIL_SWIZZLE_tpsq 1, 2, 0, 3 // Select t, then p, then s, then q in that order.
5011#define SHDR_DETAIL_SWIZZLE_tpts 1, 2, 1, 0 // Select t, then p, then t, then s in that order.
5012#define SHDR_DETAIL_SWIZZLE_tptt 1, 2, 1, 1 // Select t, then p, then t, then t in that order.
5013#define SHDR_DETAIL_SWIZZLE_tptp 1, 2, 1, 2 // Select t, then p, then t, then p in that order.
5014#define SHDR_DETAIL_SWIZZLE_tptq 1, 2, 1, 3 // Select t, then p, then t, then q in that order.
5015#define SHDR_DETAIL_SWIZZLE_tpps 1, 2, 2, 0 // Select t, then p, then p, then s in that order.
5016#define SHDR_DETAIL_SWIZZLE_tppt 1, 2, 2, 1 // Select t, then p, then p, then t in that order.
5017#define SHDR_DETAIL_SWIZZLE_tppp 1, 2, 2, 2 // Select t, then p, then p, then p in that order.
5018#define SHDR_DETAIL_SWIZZLE_tppq 1, 2, 2, 3 // Select t, then p, then p, then q in that order.
5019#define SHDR_DETAIL_SWIZZLE_tpqs 1, 2, 3, 0 // Select t, then p, then q, then s in that order.
5020#define SHDR_DETAIL_SWIZZLE_tpqt 1, 2, 3, 1 // Select t, then p, then q, then t in that order.
5021#define SHDR_DETAIL_SWIZZLE_tpqp 1, 2, 3, 2 // Select t, then p, then q, then p in that order.
5022#define SHDR_DETAIL_SWIZZLE_tpqq 1, 2, 3, 3 // Select t, then p, then q, then q in that order.
5023#define SHDR_DETAIL_SWIZZLE_tqss 1, 3, 0, 0 // Select t, then q, then s, then s in that order.
5024#define SHDR_DETAIL_SWIZZLE_tqst 1, 3, 0, 1 // Select t, then q, then s, then t in that order.
5025#define SHDR_DETAIL_SWIZZLE_tqsp 1, 3, 0, 2 // Select t, then q, then s, then p in that order.
5026#define SHDR_DETAIL_SWIZZLE_tqsq 1, 3, 0, 3 // Select t, then q, then s, then q in that order.
5027#define SHDR_DETAIL_SWIZZLE_tqts 1, 3, 1, 0 // Select t, then q, then t, then s in that order.
5028#define SHDR_DETAIL_SWIZZLE_tqtt 1, 3, 1, 1 // Select t, then q, then t, then t in that order.
5029#define SHDR_DETAIL_SWIZZLE_tqtp 1, 3, 1, 2 // Select t, then q, then t, then p in that order.
5030#define SHDR_DETAIL_SWIZZLE_tqtq 1, 3, 1, 3 // Select t, then q, then t, then q in that order.
5031#define SHDR_DETAIL_SWIZZLE_tqps 1, 3, 2, 0 // Select t, then q, then p, then s in that order.
5032#define SHDR_DETAIL_SWIZZLE_tqpt 1, 3, 2, 1 // Select t, then q, then p, then t in that order.
5033#define SHDR_DETAIL_SWIZZLE_tqpp 1, 3, 2, 2 // Select t, then q, then p, then p in that order.
5034#define SHDR_DETAIL_SWIZZLE_tqpq 1, 3, 2, 3 // Select t, then q, then p, then q in that order.
5035#define SHDR_DETAIL_SWIZZLE_tqqs 1, 3, 3, 0 // Select t, then q, then q, then s in that order.
5036#define SHDR_DETAIL_SWIZZLE_tqqt 1, 3, 3, 1 // Select t, then q, then q, then t in that order.
5037#define SHDR_DETAIL_SWIZZLE_tqqp 1, 3, 3, 2 // Select t, then q, then q, then p in that order.
5038#define SHDR_DETAIL_SWIZZLE_tqqq 1, 3, 3, 3 // Select t, then q, then q, then q in that order.
5039#define SHDR_DETAIL_SWIZZLE_psss 2, 0, 0, 0 // Select p, then s, then s, then s in that order.
5040#define SHDR_DETAIL_SWIZZLE_psst 2, 0, 0, 1 // Select p, then s, then s, then t in that order.
5041#define SHDR_DETAIL_SWIZZLE_pssp 2, 0, 0, 2 // Select p, then s, then s, then p in that order.
5042#define SHDR_DETAIL_SWIZZLE_pssq 2, 0, 0, 3 // Select p, then s, then s, then q in that order.
5043#define SHDR_DETAIL_SWIZZLE_psts 2, 0, 1, 0 // Select p, then s, then t, then s in that order.
5044#define SHDR_DETAIL_SWIZZLE_pstt 2, 0, 1, 1 // Select p, then s, then t, then t in that order.
5045#define SHDR_DETAIL_SWIZZLE_pstp 2, 0, 1, 2 // Select p, then s, then t, then p in that order.
5046#define SHDR_DETAIL_SWIZZLE_pstq 2, 0, 1, 3 // Select p, then s, then t, then q in that order.
5047#define SHDR_DETAIL_SWIZZLE_psps 2, 0, 2, 0 // Select p, then s, then p, then s in that order.
5048#define SHDR_DETAIL_SWIZZLE_pspt 2, 0, 2, 1 // Select p, then s, then p, then t in that order.
5049#define SHDR_DETAIL_SWIZZLE_pspp 2, 0, 2, 2 // Select p, then s, then p, then p in that order.
5050#define SHDR_DETAIL_SWIZZLE_pspq 2, 0, 2, 3 // Select p, then s, then p, then q in that order.
5051#define SHDR_DETAIL_SWIZZLE_psqs 2, 0, 3, 0 // Select p, then s, then q, then s in that order.
5052#define SHDR_DETAIL_SWIZZLE_psqt 2, 0, 3, 1 // Select p, then s, then q, then t in that order.
5053#define SHDR_DETAIL_SWIZZLE_psqp 2, 0, 3, 2 // Select p, then s, then q, then p in that order.
5054#define SHDR_DETAIL_SWIZZLE_psqq 2, 0, 3, 3 // Select p, then s, then q, then q in that order.
5055#define SHDR_DETAIL_SWIZZLE_ptss 2, 1, 0, 0 // Select p, then t, then s, then s in that order.
5056#define SHDR_DETAIL_SWIZZLE_ptst 2, 1, 0, 1 // Select p, then t, then s, then t in that order.
5057#define SHDR_DETAIL_SWIZZLE_ptsp 2, 1, 0, 2 // Select p, then t, then s, then p in that order.
5058#define SHDR_DETAIL_SWIZZLE_ptsq 2, 1, 0, 3 // Select p, then t, then s, then q in that order.
5059#define SHDR_DETAIL_SWIZZLE_ptts 2, 1, 1, 0 // Select p, then t, then t, then s in that order.
5060#define SHDR_DETAIL_SWIZZLE_pttt 2, 1, 1, 1 // Select p, then t, then t, then t in that order.
5061#define SHDR_DETAIL_SWIZZLE_pttp 2, 1, 1, 2 // Select p, then t, then t, then p in that order.
5062#define SHDR_DETAIL_SWIZZLE_pttq 2, 1, 1, 3 // Select p, then t, then t, then q in that order.
5063#define SHDR_DETAIL_SWIZZLE_ptps 2, 1, 2, 0 // Select p, then t, then p, then s in that order.
5064#define SHDR_DETAIL_SWIZZLE_ptpt 2, 1, 2, 1 // Select p, then t, then p, then t in that order.
5065#define SHDR_DETAIL_SWIZZLE_ptpp 2, 1, 2, 2 // Select p, then t, then p, then p in that order.
5066#define SHDR_DETAIL_SWIZZLE_ptpq 2, 1, 2, 3 // Select p, then t, then p, then q in that order.
5067#define SHDR_DETAIL_SWIZZLE_ptqs 2, 1, 3, 0 // Select p, then t, then q, then s in that order.
5068#define SHDR_DETAIL_SWIZZLE_ptqt 2, 1, 3, 1 // Select p, then t, then q, then t in that order.
5069#define SHDR_DETAIL_SWIZZLE_ptqp 2, 1, 3, 2 // Select p, then t, then q, then p in that order.
5070#define SHDR_DETAIL_SWIZZLE_ptqq 2, 1, 3, 3 // Select p, then t, then q, then q in that order.
5071#define SHDR_DETAIL_SWIZZLE_ppss 2, 2, 0, 0 // Select p, then p, then s, then s in that order.
5072#define SHDR_DETAIL_SWIZZLE_ppst 2, 2, 0, 1 // Select p, then p, then s, then t in that order.
5073#define SHDR_DETAIL_SWIZZLE_ppsp 2, 2, 0, 2 // Select p, then p, then s, then p in that order.
5074#define SHDR_DETAIL_SWIZZLE_ppsq 2, 2, 0, 3 // Select p, then p, then s, then q in that order.
5075#define SHDR_DETAIL_SWIZZLE_ppts 2, 2, 1, 0 // Select p, then p, then t, then s in that order.
5076#define SHDR_DETAIL_SWIZZLE_pptt 2, 2, 1, 1 // Select p, then p, then t, then t in that order.
5077#define SHDR_DETAIL_SWIZZLE_pptp 2, 2, 1, 2 // Select p, then p, then t, then p in that order.
5078#define SHDR_DETAIL_SWIZZLE_pptq 2, 2, 1, 3 // Select p, then p, then t, then q in that order.
5079#define SHDR_DETAIL_SWIZZLE_ppps 2, 2, 2, 0 // Select p, then p, then p, then s in that order.
5080#define SHDR_DETAIL_SWIZZLE_pppt 2, 2, 2, 1 // Select p, then p, then p, then t in that order.
5081#define SHDR_DETAIL_SWIZZLE_pppp 2, 2, 2, 2 // Select p, then p, then p, then p in that order.
5082#define SHDR_DETAIL_SWIZZLE_pppq 2, 2, 2, 3 // Select p, then p, then p, then q in that order.
5083#define SHDR_DETAIL_SWIZZLE_ppqs 2, 2, 3, 0 // Select p, then p, then q, then s in that order.
5084#define SHDR_DETAIL_SWIZZLE_ppqt 2, 2, 3, 1 // Select p, then p, then q, then t in that order.
5085#define SHDR_DETAIL_SWIZZLE_ppqp 2, 2, 3, 2 // Select p, then p, then q, then p in that order.
5086#define SHDR_DETAIL_SWIZZLE_ppqq 2, 2, 3, 3 // Select p, then p, then q, then q in that order.
5087#define SHDR_DETAIL_SWIZZLE_pqss 2, 3, 0, 0 // Select p, then q, then s, then s in that order.
5088#define SHDR_DETAIL_SWIZZLE_pqst 2, 3, 0, 1 // Select p, then q, then s, then t in that order.
5089#define SHDR_DETAIL_SWIZZLE_pqsp 2, 3, 0, 2 // Select p, then q, then s, then p in that order.
5090#define SHDR_DETAIL_SWIZZLE_pqsq 2, 3, 0, 3 // Select p, then q, then s, then q in that order.
5091#define SHDR_DETAIL_SWIZZLE_pqts 2, 3, 1, 0 // Select p, then q, then t, then s in that order.
5092#define SHDR_DETAIL_SWIZZLE_pqtt 2, 3, 1, 1 // Select p, then q, then t, then t in that order.
5093#define SHDR_DETAIL_SWIZZLE_pqtp 2, 3, 1, 2 // Select p, then q, then t, then p in that order.
5094#define SHDR_DETAIL_SWIZZLE_pqtq 2, 3, 1, 3 // Select p, then q, then t, then q in that order.
5095#define SHDR_DETAIL_SWIZZLE_pqps 2, 3, 2, 0 // Select p, then q, then p, then s in that order.
5096#define SHDR_DETAIL_SWIZZLE_pqpt 2, 3, 2, 1 // Select p, then q, then p, then t in that order.
5097#define SHDR_DETAIL_SWIZZLE_pqpp 2, 3, 2, 2 // Select p, then q, then p, then p in that order.
5098#define SHDR_DETAIL_SWIZZLE_pqpq 2, 3, 2, 3 // Select p, then q, then p, then q in that order.
5099#define SHDR_DETAIL_SWIZZLE_pqqs 2, 3, 3, 0 // Select p, then q, then q, then s in that order.
5100#define SHDR_DETAIL_SWIZZLE_pqqt 2, 3, 3, 1 // Select p, then q, then q, then t in that order.
5101#define SHDR_DETAIL_SWIZZLE_pqqp 2, 3, 3, 2 // Select p, then q, then q, then p in that order.
5102#define SHDR_DETAIL_SWIZZLE_pqqq 2, 3, 3, 3 // Select p, then q, then q, then q in that order.
5103#define SHDR_DETAIL_SWIZZLE_qsss 3, 0, 0, 0 // Select q, then s, then s, then s in that order.
5104#define SHDR_DETAIL_SWIZZLE_qsst 3, 0, 0, 1 // Select q, then s, then s, then t in that order.
5105#define SHDR_DETAIL_SWIZZLE_qssp 3, 0, 0, 2 // Select q, then s, then s, then p in that order.
5106#define SHDR_DETAIL_SWIZZLE_qssq 3, 0, 0, 3 // Select q, then s, then s, then q in that order.
5107#define SHDR_DETAIL_SWIZZLE_qsts 3, 0, 1, 0 // Select q, then s, then t, then s in that order.
5108#define SHDR_DETAIL_SWIZZLE_qstt 3, 0, 1, 1 // Select q, then s, then t, then t in that order.
5109#define SHDR_DETAIL_SWIZZLE_qstp 3, 0, 1, 2 // Select q, then s, then t, then p in that order.
5110#define SHDR_DETAIL_SWIZZLE_qstq 3, 0, 1, 3 // Select q, then s, then t, then q in that order.
5111#define SHDR_DETAIL_SWIZZLE_qsps 3, 0, 2, 0 // Select q, then s, then p, then s in that order.
5112#define SHDR_DETAIL_SWIZZLE_qspt 3, 0, 2, 1 // Select q, then s, then p, then t in that order.
5113#define SHDR_DETAIL_SWIZZLE_qspp 3, 0, 2, 2 // Select q, then s, then p, then p in that order.
5114#define SHDR_DETAIL_SWIZZLE_qspq 3, 0, 2, 3 // Select q, then s, then p, then q in that order.
5115#define SHDR_DETAIL_SWIZZLE_qsqs 3, 0, 3, 0 // Select q, then s, then q, then s in that order.
5116#define SHDR_DETAIL_SWIZZLE_qsqt 3, 0, 3, 1 // Select q, then s, then q, then t in that order.
5117#define SHDR_DETAIL_SWIZZLE_qsqp 3, 0, 3, 2 // Select q, then s, then q, then p in that order.
5118#define SHDR_DETAIL_SWIZZLE_qsqq 3, 0, 3, 3 // Select q, then s, then q, then q in that order.
5119#define SHDR_DETAIL_SWIZZLE_qtss 3, 1, 0, 0 // Select q, then t, then s, then s in that order.
5120#define SHDR_DETAIL_SWIZZLE_qtst 3, 1, 0, 1 // Select q, then t, then s, then t in that order.
5121#define SHDR_DETAIL_SWIZZLE_qtsp 3, 1, 0, 2 // Select q, then t, then s, then p in that order.
5122#define SHDR_DETAIL_SWIZZLE_qtsq 3, 1, 0, 3 // Select q, then t, then s, then q in that order.
5123#define SHDR_DETAIL_SWIZZLE_qtts 3, 1, 1, 0 // Select q, then t, then t, then s in that order.
5124#define SHDR_DETAIL_SWIZZLE_qttt 3, 1, 1, 1 // Select q, then t, then t, then t in that order.
5125#define SHDR_DETAIL_SWIZZLE_qttp 3, 1, 1, 2 // Select q, then t, then t, then p in that order.
5126#define SHDR_DETAIL_SWIZZLE_qttq 3, 1, 1, 3 // Select q, then t, then t, then q in that order.
5127#define SHDR_DETAIL_SWIZZLE_qtps 3, 1, 2, 0 // Select q, then t, then p, then s in that order.
5128#define SHDR_DETAIL_SWIZZLE_qtpt 3, 1, 2, 1 // Select q, then t, then p, then t in that order.
5129#define SHDR_DETAIL_SWIZZLE_qtpp 3, 1, 2, 2 // Select q, then t, then p, then p in that order.
5130#define SHDR_DETAIL_SWIZZLE_qtpq 3, 1, 2, 3 // Select q, then t, then p, then q in that order.
5131#define SHDR_DETAIL_SWIZZLE_qtqs 3, 1, 3, 0 // Select q, then t, then q, then s in that order.
5132#define SHDR_DETAIL_SWIZZLE_qtqt 3, 1, 3, 1 // Select q, then t, then q, then t in that order.
5133#define SHDR_DETAIL_SWIZZLE_qtqp 3, 1, 3, 2 // Select q, then t, then q, then p in that order.
5134#define SHDR_DETAIL_SWIZZLE_qtqq 3, 1, 3, 3 // Select q, then t, then q, then q in that order.
5135#define SHDR_DETAIL_SWIZZLE_qpss 3, 2, 0, 0 // Select q, then p, then s, then s in that order.
5136#define SHDR_DETAIL_SWIZZLE_qpst 3, 2, 0, 1 // Select q, then p, then s, then t in that order.
5137#define SHDR_DETAIL_SWIZZLE_qpsp 3, 2, 0, 2 // Select q, then p, then s, then p in that order.
5138#define SHDR_DETAIL_SWIZZLE_qpsq 3, 2, 0, 3 // Select q, then p, then s, then q in that order.
5139#define SHDR_DETAIL_SWIZZLE_qpts 3, 2, 1, 0 // Select q, then p, then t, then s in that order.
5140#define SHDR_DETAIL_SWIZZLE_qptt 3, 2, 1, 1 // Select q, then p, then t, then t in that order.
5141#define SHDR_DETAIL_SWIZZLE_qptp 3, 2, 1, 2 // Select q, then p, then t, then p in that order.
5142#define SHDR_DETAIL_SWIZZLE_qptq 3, 2, 1, 3 // Select q, then p, then t, then q in that order.
5143#define SHDR_DETAIL_SWIZZLE_qpps 3, 2, 2, 0 // Select q, then p, then p, then s in that order.
5144#define SHDR_DETAIL_SWIZZLE_qppt 3, 2, 2, 1 // Select q, then p, then p, then t in that order.
5145#define SHDR_DETAIL_SWIZZLE_qppp 3, 2, 2, 2 // Select q, then p, then p, then p in that order.
5146#define SHDR_DETAIL_SWIZZLE_qppq 3, 2, 2, 3 // Select q, then p, then p, then q in that order.
5147#define SHDR_DETAIL_SWIZZLE_qpqs 3, 2, 3, 0 // Select q, then p, then q, then s in that order.
5148#define SHDR_DETAIL_SWIZZLE_qpqt 3, 2, 3, 1 // Select q, then p, then q, then t in that order.
5149#define SHDR_DETAIL_SWIZZLE_qpqp 3, 2, 3, 2 // Select q, then p, then q, then p in that order.
5150#define SHDR_DETAIL_SWIZZLE_qpqq 3, 2, 3, 3 // Select q, then p, then q, then q in that order.
5151#define SHDR_DETAIL_SWIZZLE_qqss 3, 3, 0, 0 // Select q, then q, then s, then s in that order.
5152#define SHDR_DETAIL_SWIZZLE_qqst 3, 3, 0, 1 // Select q, then q, then s, then t in that order.
5153#define SHDR_DETAIL_SWIZZLE_qqsp 3, 3, 0, 2 // Select q, then q, then s, then p in that order.
5154#define SHDR_DETAIL_SWIZZLE_qqsq 3, 3, 0, 3 // Select q, then q, then s, then q in that order.
5155#define SHDR_DETAIL_SWIZZLE_qqts 3, 3, 1, 0 // Select q, then q, then t, then s in that order.
5156#define SHDR_DETAIL_SWIZZLE_qqtt 3, 3, 1, 1 // Select q, then q, then t, then t in that order.
5157#define SHDR_DETAIL_SWIZZLE_qqtp 3, 3, 1, 2 // Select q, then q, then t, then p in that order.
5158#define SHDR_DETAIL_SWIZZLE_qqtq 3, 3, 1, 3 // Select q, then q, then t, then q in that order.
5159#define SHDR_DETAIL_SWIZZLE_qqps 3, 3, 2, 0 // Select q, then q, then p, then s in that order.
5160#define SHDR_DETAIL_SWIZZLE_qqpt 3, 3, 2, 1 // Select q, then q, then p, then t in that order.
5161#define SHDR_DETAIL_SWIZZLE_qqpp 3, 3, 2, 2 // Select q, then q, then p, then p in that order.
5162#define SHDR_DETAIL_SWIZZLE_qqpq 3, 3, 2, 3 // Select q, then q, then p, then q in that order.
5163#define SHDR_DETAIL_SWIZZLE_qqqs 3, 3, 3, 0 // Select q, then q, then q, then s in that order.
5164#define SHDR_DETAIL_SWIZZLE_qqqt 3, 3, 3, 1 // Select q, then q, then q, then t in that order.
5165#define SHDR_DETAIL_SWIZZLE_qqqp 3, 3, 3, 2 // Select q, then q, then q, then p in that order.
5166#define SHDR_DETAIL_SWIZZLE_qqqq 3, 3, 3, 3 // Select q, then q, then q, then q in that order.
5167
5168#endif // SHDR_MACROS_HPP
5169
5170#endif // SHDR_SINGLE_HEADER_INCLUDED