#define SHDR_VERSION_MAJOR
Major version of shdr.
shdr.h, line 1703Runtime 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.
| Backend | Minimum requirement |
|---|---|
| CPU | C++11 compiler and host resources. |
| OpenGL ES | ES 3.1 with GLSL ES 3.10, or ES 3.2 with GLSL ES 3.20. |
| Desktop OpenGL | GL 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.
#define SHDR_VERSION_MAJOR
Major version of shdr.
shdr.h, line 1703#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#define SHDR_VERSION
The library release version as a string.
shdr.h, line 1709struct error : std::runtime_error
A shader, resource, context or dispatch validation failure.
shdr.h, line 1732struct extent
Three unsigned dimensions. dispatch dimensions count work groups.
shdr.h, line 1738explicit 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 1741enum class profile { es31, es32, gl43, gl45, gl46 };
Minimum shader language selected independently of the context's actual version.
shdr.h, line 1745explicit 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.
virtual ~device() noexcept
Release deferred completion handles through context-thread cleanup.
Destroy devices on their context thread after CPU workers have stopped.
profile shader_profile() const
Return the shader language profile selected for this device.
shdr.h, line 2563unsigned gl_handle(device& d)
Obtain the synchronized GL SSBO handle for application interop.
shdr.h, line 2665unsigned gl_handle(device& d)
Obtain the synchronized level-zero GL texture handle for application interop.
shdr.h, line 2745void mark_gpu_modified(device& d)
Notify shdr after the application writes the GL texture. its context must be current.
shdr.h, line 2750extent local_size() const
Return the fixed local workgroup dimensions declared by SHDR_BEGIN.
shdr.h, line 2868std::string glsl(profile p) const
Export this shader's automatically embedded source for compiler diagnostics or tooling.
shdr.h, line 2872void prepare(device& d);
Compile and allocate GPU resources before entering a latency-sensitive dispatch loop.
shdr.h, line 2907void run() const
Run automatic and CPU stages on the CPU. explicit GPU stages need a device.
shdr.h, line 3351void 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.
submission submit(device& d) const;
Enqueue GPU stages and return a fence for zero-timeout completion polls.
shdr.h, line 3367template <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.
enum class access { readonly, writeonly, readwrite };
Resource access qualifiers. readonly also prevents CPU writes at compile time.
shdr.h, line 1749template <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.
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.
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.
buffer(std::initializer_list<T> values) : buffer(values.size())
Allocate owned host storage and copy an initializer list into it.
shdr.h, line 2622void upload(device& d)
Ensure this device has the latest contents, allocating or uploading as needed.
shdr.h, line 2655void download(device& d)
Download newer GPU contents. reject a different owning device.
shdr.h, line 2659void mark_gpu_modified(device& d)
Notify shdr after the application writes the GL buffer. its context must be current.
shdr.h, line 2670static 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 2682template <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.
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 2710void upload(device& d)
Ensure this device has the latest pixels, allocating or uploading as needed.
shdr.h, line 2735void download(device& d)
Download newer GPU pixels through a portable compute-to-buffer copy.
shdr.h, line 2739static 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 2760template <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 2918buffer_port& operator=(const buffer<T>& b)
Bind or rebind this port to the buffer's retained shared storage.
shdr.h, line 2928unsigned length() const
Return the bound buffer's element count, matching GLSL array length().
shdr.h, line 2939typename 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.
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 3066image_port& operator=(const image2d<T, C>& image)
Bind or rebind this port to the image's retained shared storage.
shdr.h, line 3075template <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 3113template <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.
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 3136void prepare(device& d) const
Compile GPU programs and upload resources before steady-state submission.
shdr.h, line 3361enum class backend { automatic, cpu, gpu };
Automatic uses CPU execution for run() and GPU execution for run(device).
shdr.h, line 1747class 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.
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.
virtual std::unique_ptr<kernel> clone() const
Make an independent shader instance with a snapshot of its resource bindings and uniforms.
shdr.h, line 2839template <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 2889template <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 2891template <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 2894buffer_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 2924uniform_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 3030uniform_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 3035image_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 3071struct stage
One dispatch retaining a reference to its shader. Keep that shader alive during execution.
shdr.h, line 3284stage(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 3290inline 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 3299inline 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 3303virtual void main() = 0;
Execute one CPU invocation. SHDR_MAIN supplies the override.
Dispatch through a stage or pipeline to initialize builtins and synchronize resources.
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.
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.
pipeline()
Construct an empty pipeline. append dispatches with operator+=.
shdr.h, line 3329pipeline(stage s)
Construct a pipeline containing one dispatch.
shdr.h, line 3332pipeline& operator+=(stage s)
Append a dispatch in execution order and return this pipeline.
shdr.h, line 3336pipeline& operator+=(const pipeline& other)
Append every dispatch from another pipeline, including a safe copy of this pipeline.
shdr.h, line 3341pipeline snapshot() const
Snapshot shader instances, uniforms and bindings for deferred CPU execution.
shdr.h, line 3373inline pipeline operator>>(stage a, stage b)
Compose ordered stages into a reusable pipeline.
shdr.h, line 3399inline pipeline operator>>(pipeline p, stage b)
Append a stage to a pipeline value, retaining references to the same kernels.
shdr.h, line 3405inline pipeline operator>>(stage a, const pipeline& b)
Prepend a stage to a pipeline while retaining the same linked shader resources.
shdr.h, line 3410inline pipeline operator>>(pipeline a, const pipeline& b)
Join two complete processing pipelines in execution order.
shdr.h, line 3416inline 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.
enum class wait_status { ready, timeout };
Result of a completion query: completed work or an expired timeout.
shdr.h, line 3501class 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.
submission()
Construct an empty, already-complete handle.
shdr.h, line 3581bool valid() const
Return whether this handle represents submitted GPU commands.
shdr.h, line 3588bool ready()
Query completion with a zero timeout on the device context thread.
shdr.h, line 3592wait_status wait(std::chrono::nanoseconds timeout)
Request a driver wait with a nonnegative timeout in nanoseconds.
shdr.h, line 3596wait_status wait()
Explicitly wait until submitted commands complete.
shdr.h, line 3604inline 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.
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.
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.
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.
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.
std::size_t pending() const
Return the count of queued or currently being constructed jobs.
shdr.h, line 3793std::size_t capacity() const
Return the maximum number of pending jobs.
shdr.h, line 3798std::size_t workers() const
Return the number of worker threads.
shdr.h, line 3802void shutdown()
Drain accepted jobs and join all workers. later submissions fail.
Call from an application thread so it can join every worker.
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.
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.
explicit backend_unavailable(const std::string& message) : error(message)
Describe the unavailable graphics infrastructure.
shdr.h, line 3845class 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.
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.
void make_current() const
Make this context current on its creating thread.
shdr.h, line 4035static void* resolve(const char* name)
Resolve a GL entry point through EGL, for shdr::device or external GL calls.
shdr.h, line 4039class 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.
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.
void make_current() const
Make the owned context current for external GL interoperability.
shdr.h, line 4080typedef std::uint32_t uint;
GLSL's portable 32-bit unsigned scalar spelling.
shdr.h, line 34static constexpr std::size_t length()
Return the number of array elements.
shdr.h, line 210array() : elements_()
Initialize every element to its zero/default value.
shdr.h, line 214template <class... A>
explicit array(const A&... values) : elements_
Construct from exactly N scalar or aggregate element values.
shdr.h, line 217array(std::initializer_list<T> values) : elements_()
Initialize from a C++ brace list containing exactly N elements.
A length mismatch throws std::invalid_argument.
T& operator[](std::size_t i)
Read or modify element i. i must be less than length().
shdr.h, line 232template <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 241template <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 248template <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().
static constexpr std::size_t length()
Return the number of vector components.
shdr.h, line 268template <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 291T& operator[](std::size_t i)
Read or modify component i.
shdr.h, line 309T& r()
Color aliases for x/y/z/w. b and a require three and four components.
shdr.h, line 316T& s()
Texture-coordinate aliases for x/y/z/w.
shdr.h, line 345template <std::size_t I> T& swizzle()
Select one component as a scalar reference.
shdr.h, line 374template <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.
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.
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.
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.
static constexpr std::size_t length()
Return the number of matrix columns.
shdr.h, line 620template <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 638column_type& operator[](std::size_t c)
Read or modify column c. m[c][r] selects row r within that column.
shdr.h, line 662template <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.
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 721template <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 825template <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 844template <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 852template <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 860template <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 868template <class T, std::size_t N> T determinant(mat<T, N, N> a)
Determinant using partial-pivot elimination.
shdr.h, line 876template <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.
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.
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.
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 1066template <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.
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.
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 1218Geometry
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.
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.
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.
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 1513template <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 1534Packing
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.
#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.
#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_END()
End a shared shader declaration.
shdr.h, line 4107#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.
#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 4145void synchronize()
Wait for submitted GPU work to complete, including for accurate wall-clock benchmarks.
shdr.h, line 2567void collect_garbage()
Delete GL objects retired by CPU workers and poll pending completions.
shdr.h, line 2573std::string renderer() const
Current GL renderer name, for diagnostics and reproducible benchmark reports.
shdr.h, line 2577std::size_t size() const
Return the stored element count.
shdr.h, line 2626T* data()
Synchronize newer GPU contents and return mutable host elements.
Marks host data modified. Reacquire this pointer after GPU work before using it.
const T* data() const
Synchronize newer GPU contents and return readonly host elements.
shdr.h, line 2638T& operator[](std::size_t i)
Access one host element after synchronization. reject an out-of-range index.
shdr.h, line 2643const T& operator[](std::size_t i) const
Read one host element after synchronization. reject an out-of-range index.
shdr.h, line 2649void mark_host_modified()
Notify shdr after changing previously obtained or borrowed host memory.
Call data() before editing if GPU data must first be preserved.
unsigned width() const
Return the stored number of pixels in each row.
shdr.h, line 2713unsigned height() const
Return the stored number of pixel rows.
shdr.h, line 2717T* 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.
const T* data() const
Synchronize newer GPU contents and return readonly interleaved host pixels.
shdr.h, line 2730void mark_host_modified()
Notify shdr after changing a retained host pixel pointer.
shdr.h, line 2756const std::string& name() const
Return the kernel's diagnostic name.
shdr.h, line 2864template <class T> class uniform_port : public detail::port_base
A zero-initialized typed shader uniform, assigned with ordinary C++ syntax.
shdr.h, line 3024uniform_port& operator=(const T& value)
Set the uniform value uploaded at the next dispatch.
shdr.h, line 3040operator T() const
Read the uniform as its declared shader type during CPU execution.
shdr.h, line 3045const T& value() const
Return the stored uniform value.
shdr.h, line 3049std::size_t size() const
Return the number of stages.
shdr.h, line 3347void require_host_ready() const
Validate CPU execution support and current host data for a deferred job.
shdr.h, line 33861// 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