Source browser
shdr.h
Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.
File fingerprint
1// shdr 1.0.0
2// C++11 CPU and OpenGL compute pipelines.
3#ifndef SHDR_SINGLE_HEADER_INCLUDED
4#define SHDR_SINGLE_HEADER_INCLUDED
5
6// ---- math.hpp ----
7/** @file math.hpp
8 * @brief GLSL-compatible scalar, vector and matrix operations for C++11.
9 *
10 * Vectors provide x/y/z/w component fields, indexed access, and writable
11 * swizzles. Color and texture-coordinate aliases are accessor functions in
12 * ordinary C++ code. Matrices use GLSL column-major order. The same types and
13 * functions are available to generated CPU kernels and application code.
14 *
15 * Floating-point precision and exceptional values depend on the implementation.
16 * Normalize nonzero vectors, invert nonsingular matrices and use valid shift
17 * counts. Keep signed arithmetic within its representable range and use
18 * nonnegative signed operands for left shifts to follow portable C++ rules.
19 * Resource element layout is defined by the buffer and image APIs separately.
20 */
21#ifndef SHDR_DETAIL_MATH_HPP // Include this math layer only once.
22#define SHDR_DETAIL_MATH_HPP // Remember that the math layer is available.
23#include <cmath> // Use the standard scalar math functions.
24#include <cstddef> // Use portable size types.
25#include <cstdint> // Use exact-width GLSL integer types.
26#include <cstring> // Copy bit patterns through byte storage.
27#include <initializer_list> // Accept ordinary C++ brace lists.
28#include <limits> // Query numeric limits and quiet NaNs.
29#include <ostream> // Support readable vector and matrix output.
30#include <stdexcept> // Report invalid array initializers.
31#include <type_traits> // Choose only compatible template overloads.
32namespace shdr { // Keep these names inside the shdr namespace.
33namespace glsl { // Keep these names inside the glsl namespace.
34/** @brief GLSL's portable 32-bit unsigned scalar spelling. */
35typedef std::uint32_t uint; // Use a portable 32-bit unsigned scalar.
36template <class T, std::size_t N> class vec; // Store a fixed-size vector with named component fields.
37template <class T, std::size_t N> class array; // Store a fixed number of values of one element type.
38template <class T, std::size_t N, std::size_t... I> class swizzle_ref; // Describe a component selection that refers to a vector.
39template <class T, std::size_t C, std::size_t R> class mat; // Describe a matrix by its scalar type and dimensions.
40namespace detail { // Keep these names inside the detail namespace.
41template <class T, std::size_t N> struct storage; // Choose named storage for the vector dimension.
42template <class T> struct storage<T, 2> { // Choose named storage for the vector dimension.
43 T x, y; // Store the named vector components in order.
44 T& at(std::size_t i) { // Select the named component matching this index.
45 return i == 0 ? x : y; // Select the named field for this valid component index.
46 } // Finish the at operation.
47 const T& at(std::size_t i) const { // Select the named component matching this index.
48 return i == 0 ? x : y; // Select the named field for this valid component index.
49 } // Finish the at operation.
50}; // Finish the storage type description.
51template <class T> struct storage<T, 3> { // Choose named storage for the vector dimension.
52 T x, y, z; // Store the named vector components in order.
53 T& at(std::size_t i) { // Select the named component matching this index.
54 return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
55 } // Finish the at operation.
56 const T& at(std::size_t i) const { // Select the named component matching this index.
57 return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
58 } // Finish the at operation.
59}; // Finish the storage type description.
60template <class T> struct storage<T, 4> { // Choose named storage for the vector dimension.
61 T x, y, z, w; // Store the named vector components in order.
62 T& at(std::size_t i) { // Select the named component matching this index.
63 return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
64 } // Finish the at operation.
65 const T& at(std::size_t i) const { // Select the named component matching this index.
66 return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
67 } // Finish the at operation.
68}; // Finish the storage type description.
69template <class A> struct shape { // Describe an ordinary scalar input.
70 typedef A scalar; // Keep the chosen component type for the calculation.
71 static const std::size_t size = 1; // Treat a scalar as one component.
72 static const bool vector = false; // Keep this input out of vector-only overloads.
73 static const bool valid = std::is_arithmetic<A>::value; // Record whether componentwise arithmetic accepts this shape.
74}; // Finish the shape type description.
75template <class T, std::size_t N> struct shape<vec<T, N>> { // Describe the scalar type and size of a vector.
76 typedef T scalar; // Keep the chosen component type for the calculation.
77 static const std::size_t size = N; // Keep the fixed component count available at compile time.
78 static const bool vector = true; // Mark this input as a vector-shaped value.
79 static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
80}; // Finish the shape type description.
81template <class T, std::size_t N, std::size_t... I> struct shape<swizzle_ref<T, N, I...>> { // Describe the scalar type and size of a component selection.
82 typedef T scalar; // Keep the chosen component type for the calculation.
83 static const std::size_t size = sizeof...(I); // Count the selected vector components.
84 static const bool vector = true; // Mark this input as a vector-shaped value.
85 static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
86}; // Finish the shape type description.
87template <class A> struct traits : shape<typename std::decay<A>::type> {}; // Ignore references and const when inspecting an input type.
88template <class... A> struct count; // Count components supplied by constructor arguments.
89template <> struct count<> { // Count components supplied by constructor arguments.
90 static const std::size_t value = 0; // Start the component count at zero.
91}; // Finish the count type description.
92template <class A, class... B> struct count<A, B...> { // Count components supplied by constructor arguments.
93 static const std::size_t value = traits<A>::size + count<B...>::value; // Add this argument count to the remaining components.
94}; // Finish the count type description.
95template <class... A> struct prefix_count; // Count constructor components before the final argument.
96template <class Last> struct prefix_count<Last> { // Count constructor components before the final argument.
97 static const std::size_t value = 0; // Start the component count at zero.
98}; // Finish the prefix_count type description.
99template <class A, class B, class... Rest> struct prefix_count<A, B, Rest...> { // Count constructor components before the final argument.
100 static const std::size_t value = traits<A>::size + prefix_count<B, Rest...>::value; // Add this argument count to the remaining components.
101}; // Finish the prefix_count type description.
102template <class A> struct is_matrix : std::false_type {}; // Identify matrix types at compile time.
103template <class T, std::size_t C, std::size_t R> struct is_matrix<mat<T, C, R>> : std::true_type {}; // Identify matrix types at compile time.
104template <class T, std::size_t C, std::size_t R> struct shape<mat<T, C, R>> { // Describe a matrix separately from vector arithmetic.
105 typedef T scalar; // Keep the chosen component type for the calculation.
106 static const std::size_t size = C * R; // Count scalar entries across every matrix column.
107 static const bool vector = false; // Keep this input out of vector-only overloads.
108 static const bool valid = false; // Record whether componentwise arithmetic accepts this shape.
109}; // Finish the shape type description.
110template <class... A> struct any_matrix; // Check whether a constructor argument is a matrix.
111template <> struct any_matrix<> : std::false_type {}; // Check whether a constructor argument is a matrix.
112template <class A, class... B> // Accept the matching input types and dimensions.
113struct any_matrix<A, B...> // Describe this input or selection at compile time.
114 : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
115 is_matrix<typename std::decay<A>::type>::value || // Complete the type and dimension rule for this overload.
116 any_matrix<B...>::value> {}; // Complete the type and dimension rule for this overload.
117template <std::size_t Needle, std::size_t... I> struct contains; // Check whether the remaining index list contains an index.
118template <std::size_t Needle> struct contains<Needle> : std::false_type {}; // Check whether the remaining index list contains an index.
119template <std::size_t Needle, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
120struct contains<Needle, A, I...> // Describe this input or selection at compile time.
121 : std::integral_constant<bool, Needle == A || contains<Needle, I...>::value> {}; // Turn the component rule into a compile-time boolean.
122template <std::size_t... I> struct unique; // Check that selected component indices are distinct.
123template <> struct unique<> : std::true_type {}; // Check that selected component indices are distinct.
124template <std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
125struct unique<A, I...> // Describe this input or selection at compile time.
126 : std::integral_constant<bool, !contains<A, I...>::value && unique<I...>::value> {}; // Turn the component rule into a compile-time boolean.
127template <class A> struct writable_shape : std::false_type {}; // Identify vector selections that can receive values.
128template <class T, std::size_t N> struct writable_shape<vec<T, N>> : std::true_type {}; // Describe the scalar type and size of a vector.
129template <class T, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
130struct writable_shape<swizzle_ref<T, N, I...>> : unique<I...> {}; // Describe this input or selection at compile time.
131template <class A> // Accept the matching input types and dimensions.
132struct writable // Describe this input or selection at compile time.
133 : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
134 writable_shape<typename std::decay<A>::type>::value && // Complete the type and dimension rule for this overload.
135 !std::is_const<typename std::remove_reference<A>::type>::value> {}; // Complete the type and dimension rule for this overload.
136template <std::size_t N, std::size_t... I> struct in_range; // Check that every selected index fits the vector.
137template <std::size_t N> struct in_range<N> : std::true_type {}; // Check that every selected index fits the vector.
138template <std::size_t N, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
139struct in_range<N, A, I...> : std::integral_constant<bool, // Check this index and the remaining selected indices.
140 A < N && in_range<N, I...>::value> {}; // Require every selected component index to fit the vector.
141template <class A> // Accept the matching input types and dimensions.
142typename std::enable_if<!traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
143component(const A& a, std::size_t) { // Read the requested scalar or vector component.
144 return a; // Return the scalar unchanged.
145} // Finish the component operation.
146template <class A> // Accept the matching input types and dimensions.
147typename std::enable_if<traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
148component(const A& a, std::size_t i) { // Read the requested scalar or vector component.
149 return a[i]; // Read the requested scalar or vector component.
150} // Finish the component operation.
151template <class A, class B> struct binary { // Choose compatible componentwise operand shapes.
152 static const bool valid = // Record whether componentwise arithmetic accepts this shape.
153 traits<A>::valid && traits<B>::valid && (traits<A>::vector || traits<B>::vector) && // Complete the type and dimension rule for this overload.
154 (!traits<A>::vector || !traits<B>::vector || traits<A>::size == traits<B>::size); // Require equal lengths when both operands are vectors.
155 typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
156 typename traits<A>::scalar, // Preserve the selected component type and result shape.
157 typename traits<B>::scalar>::type scalar; // Preserve the selected component type and result shape.
158 static const std::size_t size = traits<A>::vector ? traits<A>::size : traits<B>::size; // Record the compile-time component rule.
159 typedef vec<scalar, size> result; // Name the vector type produced by this operation.
160}; // Finish the binary type description.
161template <class A> struct result { // Choose the value type for this expression result.
162 typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
163 vec<typename traits<A>::scalar, traits<A>::size>, // Preserve the selected component type and result shape.
164 typename traits<A>::scalar>::type type; // Preserve the selected component type and result shape.
165}; // Finish the result type description.
166template <class T, class U> // Accept the matching input types and dimensions.
167typename std::enable_if<std::is_arithmetic<U>::value>::type // Enable this overload only for compatible input types.
168append(T* target, std::size_t& n, const U& a) { // Append the next argument to the flat component list.
169 target[n++] = static_cast<T>(a); // Append this component and advance the destination position.
170} // Finish the append operation.
171template <class T, class U, std::size_t N> // Accept the matching input types and dimensions.
172void append(T* target, std::size_t& n, const vec<U, N>& a) { // Append constructor components in their original order.
173 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
174 target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
175} // Finish the append operation.
176template <class T, class U, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
177void append(T* target, std::size_t& n, const swizzle_ref<U, N, I...>& a) { // Append constructor components in their original order.
178 for (std::size_t i = 0; i < sizeof...(I); ++i) // Visit each component needed by this calculation.
179 target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
180} // Finish the append operation.
181template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
182void append(T* target, std::size_t& n, const mat<U, C, R>& a) { // Append constructor components in their original order.
183 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
184 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
185 target[n++] = static_cast<T>(a[c][r]); // Append this component and advance the destination position.
186} // Finish the append operation.
187template <class T> void flatten(T*, std::size_t&) { // Accept the matching input types and dimensions.
188} // Finish the flatten operation.
189template <class T, class A, class... B> // Accept the matching input types and dimensions.
190void flatten(T* target, std::size_t& n, const A& a, const B&... b) { // Collect components from the remaining constructor arguments.
191 append(target, n, a); // Append the next argument to the flat component list.
192 flatten(target, n, b...); // Append the remaining arguments in order.
193} // Finish the flatten operation.
194} // namespace detail
195
196/** @brief A fixed-size array for GLSL local variables and function arguments.
197 * The size must be positive. Default construction initializes every element to
198 * its zero/default value. component construction requires exactly N elements.
199 * Copy construction and assignment copy all elements. Use length() to query
200 * the element count and operator[] to select an element with a valid index.
201 * Resource ports define buffer and uniform memory layouts separately.
202 */
203template <class T, std::size_t N> class array { // Store a fixed number of values of one element type.
204 static_assert(N > 0, "GLSL fixed arrays require a positive size"); // Require at least one fixed-array element.
205 T elements_[N]; // Keep exactly N fixed-array elements.
206
207 public: // Expose the public math operations.
208 typedef T value_type; // Expose the element type to host code and templates.
209 static const std::size_t size_value = N; // Keep the fixed component count available at compile time.
210 /** @brief Return the number of array elements. */
211 static constexpr std::size_t length() { // Record the compile-time component rule.
212 return N; // Return the fixed number of available components.
213 } // Finish the length operation.
214 /** @brief Initialize every element to its zero/default value. */
215 array() : elements_() { // Initialize fixed-array storage from the supplied values.
216 } // Finish initializing the fixed array.
217 /** @brief Construct from exactly N scalar or aggregate element values. */
218 template <class... A> // Accept the matching input types and dimensions.
219 explicit array(const A&... values) : elements_{static_cast<T>(values)...} { // Initialize fixed-array storage from the supplied values.
220 static_assert(sizeof...(A) == N, "array constructor element count mismatch"); // Require exactly one argument for each array element.
221 } // Finish initializing the fixed array.
222 /** @brief Initialize from a C++ brace list containing exactly N elements.
223 * A length mismatch throws std::invalid_argument.
224 */
225 array(std::initializer_list<T> values) : elements_() { // Initialize fixed-array storage from the supplied values.
226 if (values.size() != N) // Reject a brace list with the wrong element count.
227 throw std::invalid_argument("array initializer element count mismatch"); // Report an initializer length mismatch.
228 std::size_t i = 0; // Begin filling the first array element.
229 for (const T& value : values) // Read initializer values in their original order.
230 elements_[i++] = value; // Store the next brace-list element.
231 } // Finish initializing the fixed array.
232 /** @brief Read or modify element i. i must be less than length(). */
233 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
234 return elements_[i]; // Return the selected component with its original reference type.
235 } // Finish this operator overload.
236 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
237 return elements_[i]; // Return the selected component with its original reference type.
238 } // Finish this operator overload.
239}; // Finish the array type description.
240template <class T, std::size_t N> const std::size_t array<T, N>::size_value; // Accept the matching input types and dimensions.
241/** @brief Compare two arrays by comparing every element. */
242template <class T, std::size_t N> bool operator==(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
243 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
244 if (!(a[i] == b[i])) // Stop when corresponding components differ.
245 return false; // Report that at least one component differs.
246 return true; // Report that every required component matched.
247} // Finish this operator overload.
248/** @brief Return true when any pair of corresponding elements differs. */
249template <class T, std::size_t N> bool operator!=(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
250 return !(a == b); // Return the component count or geometric length.
251} // Finish this operator overload.
252
253/** @brief A vector with two, three or four components of one scalar type.
254 * A scalar constructor fills every component. Component constructors consume
255 * scalar, vector and matrix arguments from left to right. matrices contribute
256 * columns in order. Excess components in the final argument are discarded.
257 * Vector conversion takes the first N components of a source with at least N components.
258 * Default construction initializes every component to zero. Indexing requires
259 * an index less than length().
260 */
261template <class T, std::size_t N> class vec : public detail::storage<T, N> { // Store a fixed-size vector with named component fields.
262 static_assert(N >= 2 && N <= 4, "GLSL vectors require 2 to 4 components"); // Require two, three or four vector components.
263
264 public: // Expose the public math operations.
265 typedef T value_type; // Expose the element type to host code and templates.
266 typedef T component_type; // Expose the element type to host code and templates.
267 static const std::size_t length_value = N; // Keep the fixed component count available at compile time.
268 /** @brief Return the number of vector components. */
269 static constexpr std::size_t length() { // Record the compile-time component rule.
270 return N; // Return the fixed number of available components.
271 } // Finish the length operation.
272 vec() { // Initialize vector components from the supplied values.
273 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
274 (*this)[i] = T(); // Update the selected destination component.
275 } // Finish initializing the vector.
276 template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
277 explicit vec(U value) { // Initialize vector components from the supplied values.
278 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
279 (*this)[i] = static_cast<T>(value); // Update the selected destination component.
280 } // Finish initializing the vector.
281 template <class U, std::size_t M> explicit vec(const vec<U, M>& value) { // Accept the matching input types and dimensions.
282 static_assert(M >= N, "vector conversion cannot invent components"); // Check this type or dimension requirement at compile time.
283 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
284 (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
285 } // Finish initializing the vector.
286 template <class U, std::size_t M, std::size_t... I> vec(const swizzle_ref<U, M, I...>& value) { // Accept the matching input types and dimensions.
287 static_assert(sizeof...(I) >= N, "swizzle conversion cannot invent components"); // Check this type or dimension requirement at compile time.
288 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
289 (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
290 } // Finish initializing the vector.
291 /** @brief Read matrix columns consecutively to initialize the vector. */
292 template <class U, std::size_t C, std::size_t R> explicit vec(const mat<U, C, R>& value) { // Accept the matching input types and dimensions.
293 static_assert(C * R >= N, "matrix does not provide enough vector components"); // Check this type or dimension requirement at compile time.
294 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
295 (*this)[i] = static_cast<T>(value[i / R][i % R]); // Update the selected destination component.
296 } // Finish initializing the vector.
297 template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
298 explicit vec(const A& a, const B& b, const Rest&... rest) { // Initialize vector components from the supplied values.
299 static_assert(detail::count<A, B, Rest...>::value >= N, // Require enough components to fill the destination.
300 "vector constructor has too few components"); // Explain the rejected input: vector constructor has too few components.
301 static_assert(detail::prefix_count<A, B, Rest...>::value < N, // Reject constructor arguments that would go unused.
302 "vector constructor has unused arguments"); // Explain the rejected input: vector constructor has unused arguments.
303 T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
304 std::size_t n = 0; // Begin appending at the first temporary component.
305 detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
306 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
307 (*this)[i] = values[i]; // Update the selected destination component.
308 } // Finish initializing the vector.
309 /** @brief Read or modify component i. */
310 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
311 return this->at(i); // Return the selected component with its original reference type.
312 } // Finish this operator overload.
313 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
314 return this->at(i); // Return the selected component with its original reference type.
315 } // Finish this operator overload.
316 /** @brief Color aliases for x/y/z/w. b and a require three and four components. */
317 T& r() { // Expose the first component through its color name.
318 return (*this)[0]; // Return the selected component with its original reference type.
319 } // Finish the r operation.
320 const T& r() const { // Expose the first component through its color name.
321 return (*this)[0]; // Return the selected component with its original reference type.
322 } // Finish the r operation.
323 T& g() { // Expose the second component through its color name.
324 return (*this)[1]; // Return the selected component with its original reference type.
325 } // Finish the g operation.
326 const T& g() const { // Expose the second component through its color name.
327 return (*this)[1]; // Return the selected component with its original reference type.
328 } // Finish the g operation.
329 T& b() { // Expose the third component through its color name.
330 static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
331 return (*this)[2]; // Return the selected component with its original reference type.
332 } // Finish the b operation.
333 const T& b() const { // Expose the third component through its color name.
334 static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
335 return (*this)[2]; // Return the selected component with its original reference type.
336 } // Finish the b operation.
337 T& a() { // Expose the fourth component through its color name.
338 static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
339 return (*this)[3]; // Return the selected component with its original reference type.
340 } // Finish the a operation.
341 const T& a() const { // Expose the fourth component through its color name.
342 static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
343 return (*this)[3]; // Return the selected component with its original reference type.
344 } // Finish the a operation.
345 /** @brief Texture-coordinate aliases for x/y/z/w. */
346 T& s() { // Expose the first texture coordinate.
347 return (*this)[0]; // Return the selected component with its original reference type.
348 } // Finish the s operation.
349 const T& s() const { // Expose the first texture coordinate.
350 return (*this)[0]; // Return the selected component with its original reference type.
351 } // Finish the s operation.
352 T& t() { // Expose the second texture coordinate.
353 return (*this)[1]; // Return the selected component with its original reference type.
354 } // Finish the t operation.
355 const T& t() const { // Expose the second texture coordinate.
356 return (*this)[1]; // Return the selected component with its original reference type.
357 } // Finish the t operation.
358 T& p() { // Expose the third texture coordinate.
359 static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
360 return (*this)[2]; // Return the selected component with its original reference type.
361 } // Finish the p operation.
362 const T& p() const { // Expose the third texture coordinate.
363 static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
364 return (*this)[2]; // Return the selected component with its original reference type.
365 } // Finish the p operation.
366 T& q() { // Expose the fourth texture coordinate.
367 static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
368 return (*this)[3]; // Return the selected component with its original reference type.
369 } // Finish the q operation.
370 const T& q() const { // Expose the fourth texture coordinate.
371 static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
372 return (*this)[3]; // Return the selected component with its original reference type.
373 } // Finish the q operation.
374 /** @brief Select one component as a scalar reference. */
375 template <std::size_t I> T& swizzle() { // Accept the matching input types and dimensions.
376 static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
377 return (*this)[I]; // Return the selected component with its original reference type.
378 } // Finish the swizzle operation.
379 template <std::size_t I> const T& swizzle() const { // Accept the matching input types and dimensions.
380 static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
381 return (*this)[I]; // Return the selected component with its original reference type.
382 } // Finish the swizzle operation.
383 /** @brief Select components in the requested order. writable destinations
384 * must contain unique indices. Const vectors produce an independent value.
385 */
386 template <std::size_t... I> // Accept the matching input types and dimensions.
387 typename std::enable_if<(sizeof...(I) >= 2), swizzle_ref<T, N, I...>>::type swizzle() { // Enable this overload only for compatible input types.
388 static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
389 static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
390 return swizzle_ref<T, N, I...>(*this); // Select components in the requested order.
391 } // Finish the swizzle operation.
392 template <std::size_t... I> // Accept the matching input types and dimensions.
393 typename std::enable_if<(sizeof...(I) >= 2), vec<T, sizeof...(I)>>::type swizzle() const { // Enable this overload only for compatible input types.
394 static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
395 static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
396 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
397 vec<T, sizeof...(I)> out; // Keep an independent value for the result or aliased inputs.
398 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
399 out[j] = (*this)[indices[j]]; // Store the computed component in the independent result.
400 return out; // Return the completed result.
401 } // Finish the swizzle operation.
402#define SHDR_DETAIL_VEC_ASSIGN(OP) /* Generate the matching scalar and vector overloads. */ \
403 template <class A> vec& operator OP(const A & a) { /* Accept the matching input types and dimensions. */ \
404 static_assert(!detail::traits<A>::vector || detail::traits<A>::size == N, /* Require matching component counts. */ \
405 "vector dimension mismatch"); /* Explain the rejected input: vector dimension mismatch. */ \
406 T values[N]; /* Allocate space for the supplied constructor components. */ \
407 for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
408 values[i] = static_cast<T>(detail::component(a, i)); /* Copy source components before any destination is changed. */ \
409 } /* Finish this component or matrix pass. */ \
410 for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
411 (*this)[i] OP values[i]; /* Update the selected destination component. */ \
412 } /* Finish this component or matrix pass. */ \
413 return *this; /* Allow this update to be used in a chained expression. */ \
414 } /* Finish this operator overload. */
415 SHDR_DETAIL_VEC_ASSIGN(+=) // Provide componentwise addition.
416 SHDR_DETAIL_VEC_ASSIGN(-=) // Provide componentwise subtraction.
417 SHDR_DETAIL_VEC_ASSIGN(*=) // Provide componentwise multiplication.
418 SHDR_DETAIL_VEC_ASSIGN(/=) // Provide componentwise division.
419 SHDR_DETAIL_VEC_ASSIGN(%=) // Provide componentwise integer remainder.
420 SHDR_DETAIL_VEC_ASSIGN(&=) // Provide componentwise bitwise AND.
421 SHDR_DETAIL_VEC_ASSIGN(|=) // Provide componentwise bitwise OR.
422 SHDR_DETAIL_VEC_ASSIGN(^=) // Provide componentwise bitwise XOR.
423 SHDR_DETAIL_VEC_ASSIGN(<<=) // Provide componentwise left shifting.
424 SHDR_DETAIL_VEC_ASSIGN(>>=) // Provide componentwise right shifting.
425#undef SHDR_DETAIL_VEC_ASSIGN // Remove this local code generator macro.
426 vec& operator++() { // Provide this arithmetic or component access overload.
427 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
428 ++(*this)[i]; // Increment this vector component.
429 return *this; // Allow this update to be used in a chained expression.
430 } // Finish this operator overload.
431 vec operator++(int) { // Provide this arithmetic or component access overload.
432 vec old(*this); // Save the vector value before incrementing or decrementing it.
433 ++*this; // Increment every vector component.
434 return old; // Return the value from before the update.
435 } // Finish this operator overload.
436 vec& operator--() { // Provide this arithmetic or component access overload.
437 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
438 --(*this)[i]; // Decrement this vector component.
439 return *this; // Allow this update to be used in a chained expression.
440 } // Finish this operator overload.
441 vec operator--(int) { // Provide this arithmetic or component access overload.
442 vec old(*this); // Save the vector value before incrementing or decrementing it.
443 --*this; // Decrement every vector component.
444 return old; // Return the value from before the update.
445 } // Finish this operator overload.
446}; // Finish the vec type description.
447template <class T, std::size_t N> const std::size_t vec<T, N>::length_value; // Accept the matching input types and dimensions.
448
449/** @brief A component selection referencing an existing vector.
450 * Assignment evaluates all source components before writing any destination,
451 * so exchanging components of the same vector is safe. Duplicate destination
452 * indices are rejected at compile time. The vector must outlive the selection.
453 * construct a vec value to keep an independent copy.
454 */
455template <class T, std::size_t N, std::size_t... I> class swizzle_ref { // Describe a component selection that refers to a vector.
456 vec<T, N>* source_; // Refer to the vector that owns the selected components.
457
458 public: // Expose the public math operations.
459 static constexpr std::size_t length() { // Record the compile-time component rule.
460 return sizeof...(I); // Return the fixed number of available components.
461 } // Finish the length operation.
462 explicit swizzle_ref(vec<T, N>& source) : source_(&source) { // Keep a reference to the source vector.
463 } // Finish keeping the source vector reference.
464 swizzle_ref(const swizzle_ref&) = default; // Copy the reference to the same source vector.
465 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
466 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
467 return (*source_)[indices[i]]; // Return the selected component with its original reference type.
468 } // Finish this operator overload.
469 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
470 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
471 return (*source_)[indices[i]]; // Return the selected component with its original reference type.
472 } // Finish this operator overload.
473 operator vec<T, sizeof...(I)>() const { // Provide this arithmetic or component access overload.
474 return vec<T, sizeof...(I)>(*this); // Return the component count or geometric length.
475 } // Finish this operator overload.
476 swizzle_ref& operator=(const swizzle_ref& rhs) { // Provide this arithmetic or component access overload.
477 return assign(rhs); // Write through a temporary so overlapping selections remain safe.
478 } // Finish this operator overload.
479 template <class A> swizzle_ref& operator=(const A& rhs) { // Accept the matching input types and dimensions.
480 return assign(rhs); // Write through a temporary so overlapping selections remain safe.
481 } // Finish this operator overload.
482 template <class A> swizzle_ref& assign(const A& rhs) { // Accept the matching input types and dimensions.
483 static_assert(detail::unique<I...>::value, "a writable swizzle cannot repeat components"); // Prevent repeated destination components.
484 static_assert(!detail::traits<A>::vector || detail::traits<A>::size == sizeof...(I), // Require matching component counts.
485 "swizzle dimension mismatch"); // Explain the rejected input: swizzle dimension mismatch.
486 vec<T, sizeof...(I)> temp; // Keep an independent value for the result or aliased inputs.
487 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
488 temp[j] = static_cast<T>(detail::component(rhs, j)); // Save this source component before writing the selection.
489 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
490 (*this)[j] = temp[j]; // Update the selected destination component.
491 return *this; // Allow this update to be used in a chained expression.
492 } // Finish the assign operation.
493#define SHDR_DETAIL_SWIZZLE_ASSIGN(OP, BINARY) /* Generate the matching scalar and vector overloads. */ \
494 template <class A> swizzle_ref& operator OP(const A & rhs) { /* Accept the matching input types and dimensions. */ \
495 return assign(vec<T, sizeof...(I)>(*this) BINARY rhs); /* Write through a temporary so overlapping selections remain safe. */ \
496 } /* Finish this operator overload. */
497 SHDR_DETAIL_SWIZZLE_ASSIGN(+=, +) // Provide componentwise addition.
498 SHDR_DETAIL_SWIZZLE_ASSIGN(-=, -) // Provide componentwise subtraction.
499 SHDR_DETAIL_SWIZZLE_ASSIGN(*=, *) // Provide componentwise multiplication.
500 SHDR_DETAIL_SWIZZLE_ASSIGN(/=, /) // Provide componentwise division.
501 SHDR_DETAIL_SWIZZLE_ASSIGN(%=, %) // Provide componentwise integer remainder.
502 SHDR_DETAIL_SWIZZLE_ASSIGN(&=, &) // Provide componentwise bitwise AND.
503 SHDR_DETAIL_SWIZZLE_ASSIGN(|=, |) // Provide componentwise bitwise OR.
504 SHDR_DETAIL_SWIZZLE_ASSIGN(^=, ^) // Provide componentwise bitwise XOR.
505 SHDR_DETAIL_SWIZZLE_ASSIGN(<<=, <<) // Provide componentwise left shifting.
506 SHDR_DETAIL_SWIZZLE_ASSIGN(>>=, >>) // Provide componentwise right shifting.
507#undef SHDR_DETAIL_SWIZZLE_ASSIGN // Remove this local code generator macro.
508}; // Finish the swizzle_ref type description.
509/** @name Vector component arithmetic
510 * Vector/scalar and scalar/vector forms broadcast the scalar.
511 * Integer operators require integer components, as in GLSL.
512 * @{ */
513#define SHDR_DETAIL_VEC_BINARY(OP) /* Generate the matching scalar and vector overloads. */ \
514 template <class A, class B> /* Accept the matching input types and dimensions. */ \
515 typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
516 typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
517 operator OP(const A& a, const B& b) { /* Provide this arithmetic or component access overload. */ \
518 typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
519 typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
520 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
521 out[i] = static_cast<T>(detail::component(a, i) OP detail::component(b, i)); /* Store the computed component in the independent result. */ \
522 } /* Finish this component or matrix pass. */ \
523 return out; /* Return the completed result. */ \
524 } /* Finish this operator overload. */
525SHDR_DETAIL_VEC_BINARY(+) // Provide componentwise addition.
526SHDR_DETAIL_VEC_BINARY(-) // Provide componentwise subtraction.
527SHDR_DETAIL_VEC_BINARY(*) // Provide componentwise multiplication.
528SHDR_DETAIL_VEC_BINARY(/) // Provide componentwise division.
529SHDR_DETAIL_VEC_BINARY(%) // Provide componentwise integer remainder.
530SHDR_DETAIL_VEC_BINARY(&) // Provide componentwise bitwise AND.
531SHDR_DETAIL_VEC_BINARY(|) // Provide componentwise bitwise OR.
532SHDR_DETAIL_VEC_BINARY(^) // Provide componentwise bitwise XOR.
533SHDR_DETAIL_VEC_BINARY(<<) // Provide componentwise left shifting.
534SHDR_DETAIL_VEC_BINARY(>>) // Provide componentwise right shifting.
535#undef SHDR_DETAIL_VEC_BINARY // Remove this local code generator macro.
536template <class A> // Accept the matching input types and dimensions.
537typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
538operator-(const A& a) { // Provide this arithmetic or component access overload.
539 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
540 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
541 out[i] = -a[i]; // Store the computed component in the independent result.
542 return out; // Return the completed result.
543} // Finish this operator overload.
544template <class A> // Accept the matching input types and dimensions.
545typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
546operator+(const A& a) { // Provide this arithmetic or component access overload.
547 return typename detail::result<A>::type(a); // Copy source components before changing the destination.
548} // Finish this operator overload.
549template <class A> // Accept the matching input types and dimensions.
550typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
551operator~(const A& a) { // Provide this arithmetic or component access overload.
552 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
553 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
554 out[i] = ~a[i]; // Store the computed component in the independent result.
555 return out; // Return the completed result.
556} // Finish this operator overload.
557template <class A, class B> // Accept the matching input types and dimensions.
558typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
559 detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
560 bool>::type // Complete the type and dimension rule for this overload.
561operator==(const A& a, const B& b) { // Provide this arithmetic or component access overload.
562 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
563 if (a[i] != b[i]) // Stop when corresponding components differ.
564 return false; // Report that at least one component differs.
565 } // Finish this component or matrix pass.
566 return true; // Report that every required component matched.
567} // Finish this operator overload.
568template <class A, class B> // Accept the matching input types and dimensions.
569typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
570 detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
571 bool>::type // Complete the type and dimension rule for this overload.
572operator!=(const A& a, const B& b) { // Provide this arithmetic or component access overload.
573 return !(a == b); // Copy source components before changing the destination.
574} // Finish this operator overload.
575/** @} */
576typedef vec<float, 2> vec2; // Name the 2-component float vector.
577typedef vec<float, 3> vec3; // Name the 3-component float vector.
578typedef vec<float, 4> vec4; // Name the 4-component float vector.
579typedef vec<double, 2> dvec2; // Name the 2-component double vector.
580typedef vec<double, 3> dvec3; // Name the 3-component double vector.
581typedef vec<double, 4> dvec4; // Name the 4-component double vector.
582typedef vec<std::int32_t, 2> ivec2; // Name the 2-component signed integer vector.
583typedef vec<std::int32_t, 3> ivec3; // Name the 3-component signed integer vector.
584typedef vec<std::int32_t, 4> ivec4; // Name the 4-component signed integer vector.
585typedef vec<std::uint32_t, 2> uvec2; // Name the 2-component unsigned integer vector.
586typedef vec<std::uint32_t, 3> uvec3; // Name the 3-component unsigned integer vector.
587typedef vec<std::uint32_t, 4> uvec4; // Name the 4-component unsigned integer vector.
588typedef vec<bool, 2> bvec2; // Name the 2-component boolean vector.
589typedef vec<bool, 3> bvec3; // Name the 3-component boolean vector.
590typedef vec<bool, 4> bvec4; // Name the 4-component boolean vector.
591template <class T, std::size_t N> // Accept the matching input types and dimensions.
592std::ostream& operator<<(std::ostream& out, const vec<T, N>& value) { // Provide this arithmetic or component access overload.
593 out << '('; // Write the next component or separator for readable output.
594 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
595 if (i) // Write a separator only after the first component.
596 out << ", "; // Write the next component or separator for readable output.
597 out << value[i]; // Write the next component or separator for readable output.
598 } // Finish this component or matrix pass.
599 return out << ')'; // Finish the readable representation and return the stream.
600} // Finish this operator overload.
601
602/** @brief A floating-point matrix with C columns and R rows.
603 * A scalar constructor initializes the diagonal and sets other entries to
604 * zero. Component constructors consume scalars and vectors in column order,
605 * discarding excess components in the final argument. Matrix conversion copies
606 * the common region and fills the remaining entries with the identity matrix.
607 * Default construction initializes every component to zero.
608 */
609template <class T, std::size_t C, std::size_t R> class mat { // Describe a matrix by its scalar type and dimensions.
610 static_assert(C >= 2 && C <= 4 && R >= 2 && R <= 4, "matrix dimensions require 2 to 4"); // Require matching component counts.
611 static_assert(std::is_floating_point<T>::value, // Require floating-point components for this operation.
612 "GLSL matrices require floating point components"); // Explain the rejected input: GLSL matrices require floating point components.
613 vec<T, R> columns_[C]; // Store each matrix column as a vector.
614
615 public: // Expose the public math operations.
616 typedef T value_type; // Expose the element type to host code and templates.
617 typedef vec<T, R> column_type; // Expose the vector type used for each matrix column.
618 static const std::size_t columns = C; // Keep the matrix column count available at compile time.
619 static const std::size_t rows = R; // Keep the matrix row count available at compile time.
620 /** @brief Return the number of matrix columns. */
621 static constexpr std::size_t length() { // Record the compile-time component rule.
622 return C; // Return the fixed number of available components.
623 } // Finish the length operation.
624 mat() : columns_() { // Initialize matrix columns from the supplied values.
625 } // Finish initializing the matrix.
626 template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
627 explicit mat(U diagonal) : columns_() { // Initialize matrix columns from the supplied values.
628 for (std::size_t c = 0; c < C && c < R; ++c) // Visit each matrix column.
629 columns_[c][c] = static_cast<T>(diagonal); // Set this diagonal entry to the requested scalar.
630 } // Finish initializing the matrix.
631 template <class U, std::size_t A, std::size_t B> // Accept the matching input types and dimensions.
632 explicit mat(const mat<U, A, B>& other) : columns_() { // Initialize matrix columns from the supplied values.
633 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
634 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
635 columns_[c][r] = // Copy or complete this matrix entry.
636 c < A && r < B ? static_cast<T>(other[c][r]) : (c == r ? T(1) : T(0)); // Copy the common region and use identity entries elsewhere.
637 } // Finish initializing the matrix.
638 /** @brief Construct a matrix from the components of one vector or swizzle. */
639 template <class A, typename std::enable_if<detail::traits<A>::vector, int>::type = 0> // Accept the matching input types and dimensions.
640 explicit mat(const A& value) { // Initialize matrix columns from the supplied values.
641 static_assert(detail::traits<A>::size >= C * R, // Check this type or dimension requirement at compile time.
642 "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
643 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
644 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
645 columns_[c][r] = static_cast<T>(value[c * R + r]); // Copy the next source component in column order.
646 } // Finish initializing the matrix.
647 template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
648 explicit mat(const A& a, const B& b, const Rest&... rest) { // Initialize matrix columns from the supplied values.
649 static_assert(!detail::any_matrix<A, B, Rest...>::value, // Check this type or dimension requirement at compile time.
650 "matrix conversion cannot be mixed with other arguments"); // Require the matrix to be the sole conversion argument.
651 static_assert(detail::count<A, B, Rest...>::value >= C * R, // Require enough components to fill the destination.
652 "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
653 static_assert(detail::prefix_count<A, B, Rest...>::value < C * R, // Reject constructor arguments that would go unused.
654 "matrix constructor has unused arguments"); // Explain the rejected input: matrix constructor has unused arguments.
655 T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
656 std::size_t n = 0; // Begin appending at the first temporary component.
657 detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
658 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
659 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
660 columns_[c][r] = values[c * R + r]; // Fill the column from the flattened constructor values.
661 } // Finish initializing the matrix.
662 /** @brief Read or modify column c. m[c][r] selects row r within that column. */
663 column_type& operator[](std::size_t c) { // Provide this arithmetic or component access overload.
664 return columns_[c]; // Return the component count or geometric length.
665 } // Finish this operator overload.
666 const column_type& operator[](std::size_t c) const { // Provide this arithmetic or component access overload.
667 return columns_[c]; // Return the component count or geometric length.
668 } // Finish this operator overload.
669 mat& operator+=(const mat& b) { // Provide this arithmetic or component access overload.
670 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
671 columns_[c] += b[c]; // Add the corresponding matrix column.
672 return *this; // Allow this update to be used in a chained expression.
673 } // Finish this operator overload.
674 mat& operator-=(const mat& b) { // Provide this arithmetic or component access overload.
675 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
676 columns_[c] -= b[c]; // Subtract the corresponding matrix column.
677 return *this; // Allow this update to be used in a chained expression.
678 } // Finish this operator overload.
679 mat& operator+=(T b) { // Provide this arithmetic or component access overload.
680 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
681 columns_[c] += b; // Add the scalar to every entry in this column.
682 return *this; // Allow this update to be used in a chained expression.
683 } // Finish this operator overload.
684 mat& operator-=(T b) { // Provide this arithmetic or component access overload.
685 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
686 columns_[c] -= b; // Subtract the scalar from every entry in this column.
687 return *this; // Allow this update to be used in a chained expression.
688 } // Finish this operator overload.
689 mat& operator*=(T b) { // Provide this arithmetic or component access overload.
690 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
691 columns_[c] *= b; // Scale this column by the scalar.
692 return *this; // Allow this update to be used in a chained expression.
693 } // Finish this operator overload.
694 mat& operator/=(T b) { // Provide this arithmetic or component access overload.
695 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
696 columns_[c] /= b; // Divide this column by the scalar.
697 return *this; // Allow this update to be used in a chained expression.
698 } // Finish this operator overload.
699 mat& operator/=(const mat& b) { // Provide this arithmetic or component access overload.
700 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
701 columns_[c] /= b[c]; // Divide corresponding entries in this column.
702 return *this; // Allow this update to be used in a chained expression.
703 } // Finish this operator overload.
704 mat& operator*=(const mat<T, C, C>& b) { // Provide this arithmetic or component access overload.
705 *this = *this * b;
706 return *this; // Allow this update to be used in a chained expression.
707 } // Finish this operator overload.
708}; // Finish the mat type description.
709template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::columns; // Accept the matching input types and dimensions.
710template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::rows; // Accept the matching input types and dimensions.
711
712/** @brief Convert a scalar, or the first component of a vector, to T.
713 * This implements GLSL scalar constructors such as float(vec3) for generated
714 * C++ kernels. Ordinary C++ callers may use scalar_cast<float>(value) directly.
715 */
716template <class T, class A> // Accept the matching input types and dimensions.
717typename std::enable_if<std::is_arithmetic<T>::value && detail::traits<A>::valid, T>::type // Enable this overload only for compatible input types.
718scalar_cast(const A& value) { // Convert the first scalar component to the requested type.
719 return static_cast<T>(detail::component(value, 0)); // Convert the first scalar component to the requested type.
720} // Finish the scalar_cast operation.
721/** @brief Convert the first column's first matrix component to scalar type T. */
722template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
723typename std::enable_if<std::is_arithmetic<T>::value, T>::type // Enable this overload only for compatible input types.
724scalar_cast(const mat<U, C, R>& value) { // Convert the first scalar component to the requested type.
725 return static_cast<T>(value[0][0]); // Convert the first scalar component to the requested type.
726} // Finish the scalar_cast operation.
727/** @brief GLSL square and rectangular matrix aliases. dimensions are columns
728 * followed by rows. Float aliases are mat2..4 and mat2x2..mat4x4. double aliases
729 * use dmat. Double arithmetic is a host extension and requires a supporting
730 * desktop GLSL profile when used by shared shaders.
731 */
732#define SHDR_DETAIL_MATRIX_ALIASES(T, PREFIX) /* Generate the matching scalar and vector overloads. */ \
733 typedef mat<T, 2, 2> PREFIX##2; /* Name the type selected for this math result. */ \
734 typedef mat<T, 3, 3> PREFIX##3; /* Name the type selected for this math result. */ \
735 typedef mat<T, 4, 4> PREFIX##4; /* Name the type selected for this math result. */ \
736 typedef mat<T, 2, 2> PREFIX##2x2; /* Name the type selected for this math result. */ \
737 typedef mat<T, 2, 3> PREFIX##2x3; /* Name the type selected for this math result. */ \
738 typedef mat<T, 2, 4> PREFIX##2x4; /* Name the type selected for this math result. */ \
739 typedef mat<T, 3, 2> PREFIX##3x2; /* Name the type selected for this math result. */ \
740 typedef mat<T, 3, 3> PREFIX##3x3; /* Name the type selected for this math result. */ \
741 typedef mat<T, 3, 4> PREFIX##3x4; /* Name the type selected for this math result. */ \
742 typedef mat<T, 4, 2> PREFIX##4x2; /* Name the type selected for this math result. */ \
743 typedef mat<T, 4, 3> PREFIX##4x3; /* Name the type selected for this math result. */ \
744 typedef mat<T, 4, 4> PREFIX##4x4; /* Name the type selected for this math result. */
745SHDR_DETAIL_MATRIX_ALIASES(float, mat) // Provide the single-precision matrix names.
746SHDR_DETAIL_MATRIX_ALIASES(double, dmat) // Provide the double-precision matrix names.
747#undef SHDR_DETAIL_MATRIX_ALIASES // Remove this local code generator macro.
748template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
749mat<T, C, R> operator+(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
750 return a += b; // Convert the first scalar component to the requested type.
751} // Finish this operator overload.
752template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
753mat<T, C, R> operator-(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
754 return a -= b; // Convert the first scalar component to the requested type.
755} // Finish this operator overload.
756template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator-(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
757 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
758 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
759 out[c] = -a[c]; // Store the computed component in the independent result.
760 return out; // Return the completed result.
761} // Finish this operator overload.
762template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator+(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
763 return a; // Return the scalar unchanged.
764} // Finish this operator overload.
765#define SHDR_DETAIL_MATRIX_SCALAR(OP, ASSIGN) /* Generate the matching scalar and vector overloads. */ \
766 template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
767 typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
768 mat<T, C, R> a, U b) { /* Keep an independent value for the result or aliased inputs. */ \
769 return a ASSIGN static_cast<T>(b); /* Convert the first scalar component to the requested type. */ \
770 } /* Finish this declaration. */ \
771 template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
772 typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
773 U a, const mat<T, C, R>& b) { /* Accept a scalar before the matrix operand. */ \
774 mat<T, C, R> out; /* Keep an independent value for the result or aliased inputs. */ \
775 for (std::size_t c = 0; c < C; ++c) { /* Visit each matrix column. */ \
776 out[c] = static_cast<T>(a) OP b[c]; /* Store the computed component in the independent result. */ \
777 } /* Finish this component or matrix pass. */ \
778 return out; /* Return the completed result. */ \
779 } /* Finish this declaration. */
780SHDR_DETAIL_MATRIX_SCALAR(+, +=) // Provide componentwise addition.
781SHDR_DETAIL_MATRIX_SCALAR(-, -=) // Provide componentwise subtraction.
782#undef SHDR_DETAIL_MATRIX_SCALAR // Remove this local code generator macro.
783template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
784typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator*(mat<T, C, R> a, // Enable this overload only for compatible input types.
785 U b) { // Accept a scalar after the matrix operand.
786 return a *= static_cast<T>(b); // Convert the first scalar component to the requested type.
787} // Finish this declaration.
788template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
789typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
790operator*(U a, mat<T, C, R> b) { // Provide this arithmetic or component access overload.
791 return b *= static_cast<T>(a); // Convert the first scalar component to the requested type.
792} // Finish this operator overload.
793template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
794typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator/(mat<T, C, R> a, // Enable this overload only for compatible input types.
795 U b) { // Accept a scalar after the matrix operand.
796 return a /= static_cast<T>(b); // Convert the first scalar component to the requested type.
797} // Finish this declaration.
798template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
799typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
800operator/(U a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
801 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
802 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
803 out[c] = static_cast<T>(a) / b[c]; // Store the computed component in the independent result.
804 return out; // Return the completed result.
805} // Finish this operator overload.
806template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
807mat<T, C, R> operator/(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
808 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
809 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
810 out[c] = a[c] / b[c]; // Store the computed component in the independent result.
811 return out; // Return the completed result.
812} // Finish this operator overload.
813template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
814bool operator==(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
815 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
816 if (a[c] != b[c]) // Handle the exceptional or boundary case before continuing.
817 return false; // Report that at least one component differs.
818 } // Finish this component or matrix pass.
819 return true; // Report that every required component matched.
820} // Finish this operator overload.
821template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
822bool operator!=(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
823 return !(a == b); // Convert the first scalar component to the requested type.
824} // Finish this operator overload.
825/** @brief Algebraic matrix-vector multiplication. */
826template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
827typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == C, vec<T, R>>::type // Enable this overload only for compatible input types.
828operator*(const mat<T, C, R>& a, const A& b) { // Provide this arithmetic or component access overload.
829 vec<T, R> out(T(0)); // Keep an independent value for the result or aliased inputs.
830 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
831 out += a[c] * b[c]; // Add this component product to the running total.
832 return out; // Return the completed result.
833} // Finish this operator overload.
834template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
835typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == R, vec<T, C>>::type // Enable this overload only for compatible input types.
836operator*(const A& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
837 vec<T, C> out(T(0)); // Keep an independent value for the result or aliased inputs.
838 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
839 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
840 out[c] += a[r] * b[c][r]; // Store the computed component in the independent result.
841 } // Finish this component or matrix pass.
842 return out; // Return the completed result.
843} // Finish this operator overload.
844/** @brief Algebraic multiplication, including nonsquare matrices. */
845template <class T, std::size_t C, std::size_t R, std::size_t K> // Accept the matching input types and dimensions.
846mat<T, K, R> operator*(const mat<T, C, R>& a, const mat<T, K, C>& b) { // Provide this arithmetic or component access overload.
847 mat<T, K, R> out; // Keep an independent value for the result or aliased inputs.
848 for (std::size_t c = 0; c < K; ++c) // Visit each matrix column.
849 out[c] = a * b[c]; // Store the computed component in the independent result.
850 return out; // Return the completed result.
851} // Finish this operator overload.
852/** @brief Exchange rows and columns, including rectangular matrices. */
853template <class T, std::size_t C, std::size_t R> mat<T, R, C> transpose(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
854 mat<T, R, C> out; // Keep an independent value for the result or aliased inputs.
855 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
856 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
857 out[r][c] = a[c][r]; // Copy the entry to its exchanged row and column.
858 return out; // Return the completed result.
859} // Finish the transpose operation.
860/** @brief Multiply corresponding matrix components element by element. */
861template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
862mat<T, C, R> matrixCompMult(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Multiply corresponding matrix entries.
863 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
864 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
865 out[c] = a[c] * b[c]; // Store the computed component in the independent result.
866 return out; // Return the completed result.
867} // Finish the matrixCompMult operation.
868/** @brief Form a column-by-row outer product. output column j is column*row[j]. */
869template <class T, std::size_t R, std::size_t C> // Accept the matching input types and dimensions.
870mat<T, C, R> outerProduct(const vec<T, R>& column, const vec<T, C>& row) { // Keep an independent value for the result or aliased inputs.
871 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
872 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
873 out[c] = column * row[c]; // Store the computed component in the independent result.
874 return out; // Return the completed result.
875} // Finish the outerProduct operation.
876/** @brief Determinant using partial-pivot elimination. */
877template <class T, std::size_t N> T determinant(mat<T, N, N> a) { // Accept the matching input types and dimensions.
878 T result(1); // Begin the determinant product with multiplicative identity.
879 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
880 std::size_t pivot = i; // Begin with the current row as the pivot candidate.
881 for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
882 if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
883 pivot = r; // Use the stronger row for the next pivot.
884 if (a[i][pivot] == T(0)) // Detect a singular column before division.
885 return T(0); // Compute the determinant with row pivoting.
886 if (pivot != i) { // Swap rows when a better pivot was found.
887 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
888 T temp = a[c][i]; // Save an entry while exchanging the two rows.
889 a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
890 a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
891 } // Finish this component or matrix pass.
892 result = -result; // Reverse the determinant sign after a row exchange.
893 } // Finish handling this condition.
894 T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
895 result *= diagonal; // Multiply the determinant by the next diagonal value.
896 for (std::size_t r = i + 1; r < N; ++r) { // Visit each matrix row.
897 T factor = a[i][r] / diagonal; // Find the amount of the pivot row to eliminate.
898 for (std::size_t c = i + 1; c < N; ++c) // Visit each matrix column.
899 a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
900 } // Finish this component or matrix pass.
901 } // Finish this component or matrix pass.
902 return result; // Return the completed result.
903} // Finish the determinant operation.
904/** @brief Inverse using partial-pivot Gauss-Jordan elimination.
905 * Singular input has undefined GLSL semantics. the host returns quiet NaNs.
906 */
907template <class T, std::size_t N> mat<T, N, N> inverse(mat<T, N, N> a) { // Accept the matching input types and dimensions.
908 mat<T, N, N> out(T(1)); // Keep an independent value for the result or aliased inputs.
909 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
910 std::size_t pivot = i; // Begin with the current row as the pivot candidate.
911 for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
912 if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
913 pivot = r; // Use the stronger row for the next pivot.
914 if (a[i][pivot] == T(0)) { // Detect a singular column before division.
915 for (std::size_t c = 0; c < N; ++c) // Visit each matrix column.
916 out[c] = vec<T, N>(std::numeric_limits<T>::quiet_NaN()); // Store the computed component in the independent result.
917 return out; // Return the completed result.
918 } // Finish handling this condition.
919 if (pivot != i) // Swap rows when a better pivot was found.
920 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
921 T temp = a[c][i]; // Save an entry while exchanging the two rows.
922 a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
923 a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
924 temp = out[c][i]; // Save an entry while exchanging the two rows.
925 out[c][i] = out[c][pivot]; // Store the computed component in the independent result.
926 out[c][pivot] = temp; // Store the computed component in the independent result.
927 } // Finish this component or matrix pass.
928 T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
929 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
930 a[c][i] /= diagonal; // Update this matrix entry during row elimination or exchange.
931 out[c][i] /= diagonal; // Store the computed component in the independent result.
932 } // Finish this component or matrix pass.
933 for (std::size_t r = 0; r < N; ++r) // Visit each matrix row.
934 if (r != i) { // Handle the exceptional or boundary case before continuing.
935 T factor = a[i][r]; // Find the amount of the pivot row to eliminate.
936 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
937 a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
938 out[c][r] -= factor * out[c][i]; // Subtract the pivot-row contribution from the inverse.
939 } // Finish this component or matrix pass.
940 } // Finish handling this condition.
941 } // Finish this component or matrix pass.
942 return out; // Return the completed result.
943} // Finish the inverse operation.
944template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
945std::ostream& operator<<(std::ostream& out, const mat<T, C, R>& value) { // Provide this arithmetic or component access overload.
946 out << '['; // Write the next component or separator for readable output.
947 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
948 if (c) // Write a separator only after the first component.
949 out << ", "; // Write the next component or separator for readable output.
950 out << value[c]; // Write the next component or separator for readable output.
951 } // Finish this component or matrix pass.
952 return out << ']'; // Finish the readable representation and return the stream.
953} // Finish this operator overload.
954/** @name Angle, exponential and common scalar/vector math
955 * Floating-point overloads preserve their component type. Vector overloads
956 * apply each scalar operation independently, including swizzle expressions.
957 * @{ */
958#define SHDR_DETAIL_FLOAT_UNARY(NAME, EXPR) /* Generate the matching scalar and vector overloads. */ \
959 template <class T> /* Accept the matching input types and dimensions. */ \
960 typename std::enable_if<std::is_floating_point<T>::value, T>::type NAME(T x) { /* Enable this overload only for compatible input types. */ \
961 return static_cast<T>(EXPR); /* Compute the inverse with row pivoting. */ \
962 } /* Finish this generated overload. */ \
963 template <class A> /* Accept the matching input types and dimensions. */ \
964 typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type /* Enable this overload only for compatible input types. */ \
965 NAME(const A& x) { /* Start the matching math overload. */ \
966 typedef typename detail::traits<A>::scalar T; /* Keep the chosen component type for the calculation. */ \
967 static_assert(std::is_floating_point<T>::value, "floating point components required"); /* Require floating-point components for this operation. */ \
968 typename detail::result<A>::type out; /* Allocate an independent result with the correct shape. */ \
969 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
970 out[i] = glsl::NAME(x[i]); /* Store the computed component in the independent result. */ \
971 return out; /* Return the completed result. */ \
972 } /* Finish this generated overload. */
973SHDR_DETAIL_FLOAT_UNARY(radians, x* T(0.01745329251994329576923690768489L)) // Convert degrees to radians for scalars and vector components.
974SHDR_DETAIL_FLOAT_UNARY(degrees, x* T(57.295779513082320876798154814105L)) // Convert radians to degrees for scalars and vector components.
975SHDR_DETAIL_FLOAT_UNARY(sin, std::sin(x)) // Compute the sine for scalars and vector components.
976SHDR_DETAIL_FLOAT_UNARY(cos, std::cos(x)) // Compute the cosine for scalars and vector components.
977SHDR_DETAIL_FLOAT_UNARY(tan, std::tan(x)) // Compute the tangent for scalars and vector components.
978SHDR_DETAIL_FLOAT_UNARY(asin, std::asin(x)) // Compute the inverse sine for scalars and vector components.
979SHDR_DETAIL_FLOAT_UNARY(acos, std::acos(x)) // Compute the inverse cosine for scalars and vector components.
980SHDR_DETAIL_FLOAT_UNARY(atan, std::atan(x)) // Compute the inverse tangent for scalars and vector components.
981SHDR_DETAIL_FLOAT_UNARY(sinh, std::sinh(x)) // Compute the hyperbolic sine for scalars and vector components.
982SHDR_DETAIL_FLOAT_UNARY(cosh, std::cosh(x)) // Compute the hyperbolic cosine for scalars and vector components.
983SHDR_DETAIL_FLOAT_UNARY(tanh, std::tanh(x)) // Compute the hyperbolic tangent for scalars and vector components.
984SHDR_DETAIL_FLOAT_UNARY(asinh, std::asinh(x)) // Compute the inverse hyperbolic sine for scalars and vector components.
985SHDR_DETAIL_FLOAT_UNARY(acosh, std::acosh(x)) // Compute the inverse hyperbolic cosine for scalars and vector components.
986SHDR_DETAIL_FLOAT_UNARY(atanh, std::atanh(x)) // Compute the inverse hyperbolic tangent for scalars and vector components.
987SHDR_DETAIL_FLOAT_UNARY(exp, std::exp(x)) // Raise e to the input power for scalars and vector components.
988SHDR_DETAIL_FLOAT_UNARY(log, std::log(x)) // Compute the natural logarithm for scalars and vector components.
989SHDR_DETAIL_FLOAT_UNARY(exp2, std::exp2(x)) // Raise two to the input power for scalars and vector components.
990SHDR_DETAIL_FLOAT_UNARY(log2, std::log2(x)) // Compute the base-two logarithm for scalars and vector components.
991SHDR_DETAIL_FLOAT_UNARY(sqrt, std::sqrt(x)) // Compute the square root for scalars and vector components.
992SHDR_DETAIL_FLOAT_UNARY(inversesqrt, T(1) / std::sqrt(x)) // Compute the reciprocal square root for scalars and vector components.
993SHDR_DETAIL_FLOAT_UNARY(floor, std::floor(x)) // Round toward negative infinity for scalars and vector components.
994SHDR_DETAIL_FLOAT_UNARY(trunc, std::trunc(x)) // Round toward zero for scalars and vector components.
995SHDR_DETAIL_FLOAT_UNARY(round, std::round(x)) // Round to the nearest integer for scalars and vector components.
996SHDR_DETAIL_FLOAT_UNARY(ceil, std::ceil(x)) // Round toward positive infinity for scalars and vector components.
997SHDR_DETAIL_FLOAT_UNARY(fract, x - std::floor(x)) // Keep the fraction above the floor for scalars and vector components.
998#undef SHDR_DETAIL_FLOAT_UNARY // Remove this local code generator macro.
999template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type abs(T x) { // Accept the matching input types and dimensions.
1000 return x < T(0) ? -x : x; // Return a nonnegative magnitude.
1001} // Finish the abs operation.
1002template <class A> // Accept the matching input types and dimensions.
1003typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1004abs(const A& a) { // Return a nonnegative magnitude.
1005 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1006 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1007 out[i] = glsl::abs(a[i]); // Store the computed component in the independent result.
1008 return out; // Return the completed result.
1009} // Finish the abs operation.
1010template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type sign(T x) { // Accept the matching input types and dimensions.
1011 return x > T(0) ? T(1) : (x < T(0) ? T(-1) : T(0)); // Return minus one, zero or one from the input sign.
1012} // Finish the sign operation.
1013template <class A> // Accept the matching input types and dimensions.
1014typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1015sign(const A& a) { // Return minus one, zero or one from the input sign.
1016 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1017 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1018 out[i] = glsl::sign(a[i]); // Store the computed component in the independent result.
1019 return out; // Return the completed result.
1020} // Finish the sign operation.
1021/** @brief Round halfway cases to the nearest even integer, independent of the
1022 * host's floating-point rounding mode. Nonfinite inputs are preserved.
1023 */
1024template <class T> // Accept the matching input types and dimensions.
1025typename std::enable_if<std::is_floating_point<T>::value, T>::type roundEven(T x) { // Enable this overload only for compatible input types.
1026 if (!std::isfinite(x)) // Keep nonfinite inputs unchanged.
1027 return x; // Round halfway values to the nearest even integer.
1028 T lo = std::floor(x), fraction = x - lo; // Separate the lower integer from its fractional remainder.
1029 if (fraction < T(0.5)) // Choose the lower integer below the halfway point.
1030 return lo; // Round halfway values to the nearest even integer.
1031 if (fraction > T(0.5)) // Choose the upper integer above the halfway point.
1032 return lo + T(1); // Round halfway values to the nearest even integer.
1033 return std::fmod(lo, T(2)) == T(0) ? lo : lo + T(1); // Round halfway values to the nearest even integer.
1034} // Finish the roundEven operation.
1035template <class A> // Accept the matching input types and dimensions.
1036typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1037roundEven(const A& a) { // Round halfway values to the nearest even integer.
1038 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1039 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1040 out[i] = glsl::roundEven(a[i]); // Store the computed component in the independent result.
1041 return out; // Return the completed result.
1042} // Finish the roundEven operation.
1043#define SHDR_DETAIL_MATH_BINARY(NAME, ENABLE, EXPR) /* Generate the matching scalar and vector overloads. */ \
1044 template <class T> typename std::enable_if<ENABLE, T>::type NAME(T x, T y) { /* Accept the matching input types and dimensions. */ \
1045 return static_cast<T>(EXPR); /* Round halfway values to the nearest even integer. */ \
1046 } /* Finish this generated overload. */ \
1047 template <class A, class B> /* Accept the matching input types and dimensions. */ \
1048 typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
1049 typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
1050 NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1051 typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
1052 typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
1053 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
1054 out[i] = glsl::NAME(static_cast<T>(detail::component(a, i)), /* Store the computed component in the independent result. */ \
1055 static_cast<T>(detail::component(b, i))); /* Convert the second operand component to the result type. */ \
1056 } /* Finish this component or matrix pass. */ \
1057 return out; /* Return the completed result. */ \
1058 } /* Finish this generated overload. */
1059SHDR_DETAIL_MATH_BINARY(atan, std::is_floating_point<T>::value, std::atan2(x, y)) // Compute the inverse tangent for scalars and vector components.
1060SHDR_DETAIL_MATH_BINARY(pow, std::is_floating_point<T>::value, std::pow(x, y)) // Raise each base to its exponent.
1061SHDR_DETAIL_MATH_BINARY(mod, std::is_floating_point<T>::value, x - y * std::floor(x / y)) // Use the GLSL floor-based remainder.
1062SHDR_DETAIL_MATH_BINARY(min, std::is_arithmetic<T>::value, y < x ? y : x) // Choose the smaller value.
1063SHDR_DETAIL_MATH_BINARY(max, std::is_arithmetic<T>::value, x < y ? y : x) // Choose the larger value.
1064SHDR_DETAIL_MATH_BINARY(step, std::is_floating_point<T>::value, y < x ? T(0) : T(1)) // Return zero below the edge and one otherwise.
1065#undef SHDR_DETAIL_MATH_BINARY // Remove this local code generator macro.
1066/** @brief Fused multiply-add. final rounding may differ across CPU/GPU. */
1067template <class T> // Accept the matching input types and dimensions.
1068typename std::enable_if<std::is_floating_point<T>::value, T>::type fma(T a, T b, T c) { // Enable this overload only for compatible input types.
1069 return std::fma(a, b, c); // Multiply and add with one final rounding.
1070} // Finish the fma operation.
1071template <class A, class B, class C> // Accept the matching input types and dimensions.
1072typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1073fma(const A& a, const B& b, const C& c) { // Multiply and add with one final rounding.
1074 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1075 "fma dimensions mismatch"); // Explain the rejected input: fma dimensions mismatch.
1076 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1077 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1078 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1079 out[i] = glsl::fma( // Store the computed component in the independent result.
1080 a[i], static_cast<T>(detail::component(b, i)), static_cast<T>(detail::component(c, i))); // Supply the matching three components to fused multiply-add.
1081 return out; // Return the completed result.
1082} // Finish the fma operation.
1083template <class T> // Accept the matching input types and dimensions.
1084typename std::enable_if<std::is_arithmetic<T>::value, T>::type clamp(T x, T lower, T upper) { // Enable this overload only for compatible input types.
1085 return glsl::min(glsl::max(x, lower), upper); // Keep a value between its lower and upper limits.
1086} // Finish the clamp operation.
1087template <class A, class B, class C> // Accept the matching input types and dimensions.
1088typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1089clamp(const A& a, const B& lower, const C& upper) { // Keep a value between its lower and upper limits.
1090 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1091 "clamp dimensions mismatch"); // Explain the rejected input: clamp dimensions mismatch.
1092 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1093 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1094 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1095 out[i] = glsl::clamp(a[i], // Store the computed component in the independent result.
1096 static_cast<T>(detail::component(lower, i)), // Use the matching lower bound component.
1097 static_cast<T>(detail::component(upper, i))); // Use the matching upper bound component.
1098 return out; // Return the completed result.
1099} // Finish the clamp operation.
1100template <class T, class U> // Accept the matching input types and dimensions.
1101typename std::enable_if<std::is_floating_point<T>::value && std::is_arithmetic<U>::value && // Enable this overload only for compatible input types.
1102 !std::is_same<U, bool>::value, // Complete the type and dimension rule for this overload.
1103 T>::type // Complete the type and dimension rule for this overload.
1104mix(T x, T y, U selector) { // Blend values or select one with a boolean.
1105 T a = static_cast<T>(selector); // Convert the interpolation amount to the component type.
1106 return x * (T(1) - a) + y * a; // Blend values or select one with a boolean.
1107} // Finish the mix operation.
1108template <class T, class B> // Accept the matching input types and dimensions.
1109typename std::enable_if<std::is_arithmetic<T>::value && std::is_same<B, bool>::value, T>::type // Enable this overload only for compatible input types.
1110mix(T x, T y, B a) { // Blend values or select one with a boolean.
1111 return a ? y : x; // Blend values or select one with a boolean.
1112} // Finish the mix operation.
1113template <class A, class B, class C> // Accept the matching input types and dimensions.
1114typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1115mix(const A& a, const B& b, const C& selector) { // Blend values or select one with a boolean.
1116 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1117 "mix dimensions mismatch"); // Explain the rejected input: mix dimensions mismatch.
1118 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1119 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1120 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1121 out[i] = glsl::mix( // Store the computed component in the independent result.
1122 a[i], static_cast<T>(detail::component(b, i)), detail::component(selector, i)); // Blend or select the matching input components.
1123 return out; // Return the completed result.
1124} // Finish the mix operation.
1125template <class T> // Accept the matching input types and dimensions.
1126typename std::enable_if<std::is_floating_point<T>::value, T>::type // Enable this overload only for compatible input types.
1127smoothstep(T lower, T upper, T x) { // Interpolate smoothly between two edges.
1128 T t = glsl::clamp((x - lower) / (upper - lower), T(0), T(1)); // Map the input into a clamped zero-to-one interval.
1129 return t * t * (T(3) - T(2) * t); // Interpolate smoothly between two edges.
1130} // Finish the smoothstep operation.
1131template <class A, class B, class C> // Accept the matching input types and dimensions.
1132typename std::enable_if<detail::traits<C>::vector, typename detail::result<C>::type>::type // Enable this overload only for compatible input types.
1133smoothstep(const A& lower, const B& upper, const C& x) { // Interpolate smoothly between two edges.
1134 static_assert(detail::binary<C, A>::valid && detail::binary<C, B>::valid, // Check this type or dimension requirement at compile time.
1135 "smoothstep dimensions mismatch"); // Explain the rejected input: smoothstep dimensions mismatch.
1136 typedef typename detail::traits<C>::scalar T; // Keep the chosen component type for the calculation.
1137 typename detail::result<C>::type out; // Allocate an independent result with the correct shape.
1138 for (std::size_t i = 0; i < detail::traits<C>::size; ++i) // Visit each component needed by this calculation.
1139 out[i] = glsl::smoothstep(static_cast<T>(detail::component(lower, i)), // Store the computed component in the independent result.
1140 static_cast<T>(detail::component(upper, i)), // Use the matching upper interpolation edge.
1141 x[i]); // Interpolate this input component between its edges.
1142 return out; // Return the completed result.
1143} // Finish the smoothstep operation.
1144template <class T> // Accept the matching input types and dimensions.
1145typename std::enable_if<std::is_floating_point<T>::value, bool>::type isnan(T x) { // Enable this overload only for compatible input types.
1146 return std::isnan(x); // Check whether the value is not a number.
1147} // Finish the isnan operation.
1148template <class T> // Accept the matching input types and dimensions.
1149typename std::enable_if<std::is_floating_point<T>::value, bool>::type isinf(T x) { // Enable this overload only for compatible input types.
1150 return std::isinf(x); // Check whether the value is infinite.
1151} // Finish the isinf operation.
1152#define SHDR_DETAIL_CLASSIFICATION(NAME) /* Generate the matching scalar and vector overloads. */ \
1153 template <class A> /* Accept the matching input types and dimensions. */ \
1154 typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1155 NAME(const A& a) { /* Start the matching math overload. */ \
1156 vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1157 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1158 out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1159 return out; /* Return the completed result. */ \
1160 } /* Finish this generated overload. */
1161SHDR_DETAIL_CLASSIFICATION(isnan) // Check whether the value is not a number.
1162SHDR_DETAIL_CLASSIFICATION(isinf) // Check whether the value is infinite.
1163#undef SHDR_DETAIL_CLASSIFICATION // Remove this local code generator macro.
1164template <class T> // Accept the matching input types and dimensions.
1165typename std::enable_if<std::is_floating_point<T>::value, T>::type modf(T x, T& integer) { // Enable this overload only for compatible input types.
1166 return std::modf(x, &integer); // Separate fractional and integral components.
1167} // Finish the modf operation.
1168/** @brief Split a vector into signed fractional and integer parts.
1169 * The return value contains fractional components. integer receives the
1170 * integral components. Both arguments may be swizzles, including selections
1171 * of the same vector, because the input is copied before output assignment.
1172 */
1173template <class A, class B> // Accept the matching input types and dimensions.
1174typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1175 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1176modf(const A& x, B&& integer) { // Separate fractional and integral components.
1177 static_assert(detail::traits<A>::size == detail::traits<B>::size, "modf dimensions mismatch"); // Require matching component counts.
1178 static_assert( // Check this type or dimension requirement at compile time.
1179 std::is_same<typename detail::traits<A>::scalar, typename detail::traits<B>::scalar>::value, // Require the input and output component types to match.
1180 "modf component types must match"); // Explain the rejected input: modf component types must match.
1181 static_assert(detail::writable<B>::value, "modf output requires writable unique components"); // Prevent repeated destination components.
1182 typename detail::result<A>::type input(x), out, integral; // Preserve the selected component type and result shape.
1183 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1184 out[i] = glsl::modf(input[i], integral[i]); // Store the computed component in the independent result.
1185 integer = integral; // Publish all integral components after reading the input.
1186 return out; // Return the completed result.
1187} // Finish the modf operation.
1188template <class T> // Accept the matching input types and dimensions.
1189typename std::enable_if<std::is_floating_point<T>::value, T>::type frexp(T x, int& exponent) { // Enable this overload only for compatible input types.
1190 return std::frexp(x, &exponent); // Separate a significand and its binary exponent.
1191} // Finish the frexp operation.
1192/** @brief Return binary significands and write matching signed exponents.
1193 * Each nonzero component satisfies x = significand * 2^exponent. Output may be
1194 * an integer vector or a writable swizzle with matching component count.
1195 */
1196template <class A, class B> // Accept the matching input types and dimensions.
1197typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1198 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1199frexp(const A& x, B&& exponent) { // Separate a significand and its binary exponent.
1200 static_assert(detail::traits<A>::size == detail::traits<B>::size, "frexp dimensions mismatch"); // Require matching component counts.
1201 static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1202 "frexp requires signed integer exponent components"); // Explain the rejected input: frexp requires signed integer exponent components.
1203 static_assert(detail::writable<B>::value, "frexp output requires writable unique components"); // Prevent repeated destination components.
1204 typename detail::result<A>::type input(x), out; // Allocate an independent result with the correct shape.
1205 vec<std::int32_t, detail::traits<A>::size> powers; // Use the selected vector or matrix shape for this value.
1206 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1207 int e = 0; // Prepare a signed exponent for this component.
1208 out[i] = std::frexp(input[i], &e); // Store the computed component in the independent result.
1209 powers[i] = e; // Store the binary exponent for this component.
1210 } // Finish this component or matrix pass.
1211 exponent = powers; // Publish all exponents after reading the input.
1212 return out; // Return the completed result.
1213} // Finish the frexp operation.
1214template <class T> // Accept the matching input types and dimensions.
1215typename std::enable_if<std::is_floating_point<T>::value, T>::type ldexp(T x, int exponent) { // Enable this overload only for compatible input types.
1216 return std::ldexp(x, exponent); // Scale a significand by a power of two.
1217} // Finish the ldexp operation.
1218/** @brief Multiply each component by two raised to its signed integer exponent. */
1219template <class A, class B> // Accept the matching input types and dimensions.
1220typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1221 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1222ldexp(const A& x, const B& exponent) { // Scale a significand by a power of two.
1223 static_assert(detail::traits<A>::size == detail::traits<B>::size, "ldexp dimensions mismatch"); // Require matching component counts.
1224 static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1225 "ldexp requires signed integer exponent components"); // Explain the rejected input: ldexp requires signed integer exponent components.
1226 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1227 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1228 out[i] = std::ldexp(x[i], exponent[i]); // Store the computed component in the independent result.
1229 return out; // Return the completed result.
1230} // Finish the ldexp operation.
1231/** @} */
1232
1233/** @name Geometry
1234 * Geometry uses scalar dot products and GLSL's usual component formulas.
1235 * normalize requires nonzero length. Inputs to reflect, refract and faceforward
1236 * should obey GLSL's normalized-normal requirements.
1237 * @{ */
1238template <class T> // Accept the matching input types and dimensions.
1239typename std::enable_if<std::is_floating_point<T>::value, T>::type dot(T a, T b) { // Enable this overload only for compatible input types.
1240 return a * b; // Sum products of corresponding components.
1241} // Finish the dot operation.
1242template <class A, class B> // Accept the matching input types and dimensions.
1243typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1244 typename detail::traits<A>::scalar>::type // Preserve the selected component type and result shape.
1245dot(const A& a, const B& b) { // Sum products of corresponding components.
1246 static_assert(detail::traits<A>::size == detail::traits<B>::size, "dot dimensions mismatch"); // Require matching component counts.
1247 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1248 T out(0); // Start the scalar accumulator at zero.
1249 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1250 out += a[i] * b[i]; // Add this component product to the running total.
1251 } // Finish this component or matrix pass.
1252 return out; // Return the completed result.
1253} // Finish the dot operation.
1254template <class T> typename std::enable_if<std::is_floating_point<T>::value, T>::type length(T x) { // Accept the matching input types and dimensions.
1255 return glsl::abs(x); // Return the component count or geometric length.
1256} // Finish the length operation.
1257template <class A> // Accept the matching input types and dimensions.
1258typename std::enable_if<detail::traits<A>::vector, typename detail::traits<A>::scalar>::type // Enable this overload only for compatible input types.
1259length(const A& a) { // Return the component count or geometric length.
1260 return glsl::sqrt(glsl::dot(a, a)); // Return the component count or geometric length.
1261} // Finish the length operation.
1262template <class A, class B> auto distance(const A& a, const B& b) -> decltype(glsl::length(a - b)) { // Accept the matching input types and dimensions.
1263 return glsl::length(a - b); // Measure the length of the difference.
1264} // Finish the distance operation.
1265template <class A, class B> // Accept the matching input types and dimensions.
1266typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1267 detail::traits<A>::size == 3 && detail::traits<B>::size == 3, // Complete the type and dimension rule for this overload.
1268 vec<typename detail::traits<A>::scalar, 3>>::type // Preserve the selected component type and result shape.
1269cross(const A& a, const B& b) { // Compute the three-dimensional cross product.
1270 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1271 return vec<T, 3>( // Compute the three-dimensional cross product.
1272 a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]); // Use the three signed two-by-two minors for the cross product.
1273} // Finish the cross operation.
1274template <class A> // Accept the matching input types and dimensions.
1275typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1276normalize(const A& a) { // Scale a nonzero value to unit length.
1277 return a / glsl::length(a); // Scale a nonzero value to unit length.
1278} // Finish the normalize operation.
1279template <class A, class B, class C> // Accept the matching input types and dimensions.
1280typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1281faceforward(const A& normal, const B& incident, const C& reference) { // Choose the normal direction facing the incident vector.
1282 return glsl::dot(reference, incident) < 0 ? normal : -normal; // Choose the normal direction facing the incident vector.
1283} // Finish the faceforward operation.
1284template <class A, class B> // Accept the matching input types and dimensions.
1285typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1286reflect(const A& incident, const B& normal) { // Reflect an incident vector around its normal.
1287 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1288 return incident - T(2) * glsl::dot(normal, incident) * normal; // Reflect an incident vector around its normal.
1289} // Finish the reflect operation.
1290template <class A, class B> // Accept the matching input types and dimensions.
1291typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1292refract(const A& incident, const B& normal, typename detail::traits<A>::scalar eta) { // Refract an incident vector using the index ratio.
1293 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1294 T d = glsl::dot(normal, incident); // Measure the incident component along the normal.
1295 T k = T(1) - eta * eta * (T(1) - d * d); // Compute the refraction discriminant before taking its root.
1296 return k < T(0) ? typename detail::result<A>::type(T(0)) // Refract an incident vector using the index ratio.
1297 : eta * incident - (eta * d + glsl::sqrt(k)) * normal; // Apply the transmitted-direction formula when refraction is possible.
1298} // Finish the refract operation.
1299/** @} */
1300
1301/** @name Vector relational functions
1302 * operator== compares the whole vector and returns bool. These builtins return
1303 * component masks. logicalNot is the C++ spelling of GLSL's reserved `not`.
1304 * @{ */
1305#define SHDR_DETAIL_RELATIONAL(NAME, OP) /* Generate the matching scalar and vector overloads. */ \
1306 template <class A, class B> /* Accept the matching input types and dimensions. */ \
1307 typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, /* Enable this overload only for compatible input types. */ \
1308 vec<bool, detail::traits<A>::size>>::type /* Use the selected vector or matrix shape for this value. */ \
1309 NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1310 static_assert(detail::traits<A>::size == detail::traits<B>::size, /* Require matching component counts. */ \
1311 "relational dimensions mismatch"); /* Explain the rejected input: relational dimensions mismatch. */ \
1312 vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1313 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1314 out[i] = a[i] OP b[i]; /* Store the computed component in the independent result. */ \
1315 return out; /* Return the completed result. */ \
1316 } /* Finish this generated overload. */
1317SHDR_DETAIL_RELATIONAL(lessThan, <) // Provide the requested component operation.
1318SHDR_DETAIL_RELATIONAL(lessThanEqual, <=) // Provide the requested component operation.
1319SHDR_DETAIL_RELATIONAL(greaterThan, >) // Provide the requested component operation.
1320SHDR_DETAIL_RELATIONAL(greaterThanEqual, >=) // Provide the requested component operation.
1321SHDR_DETAIL_RELATIONAL(equal, ==) // Provide the requested component operation.
1322SHDR_DETAIL_RELATIONAL(notEqual, !=) // Provide the requested component operation.
1323#undef SHDR_DETAIL_RELATIONAL // Remove this local code generator macro.
1324template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type any(const A& a) { // Accept the matching input types and dimensions.
1325 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1326 if (a[i]) // Handle the exceptional or boundary case before continuing.
1327 return true; // Report that every required component matched.
1328 return false; // Report that at least one component differs.
1329} // Finish the any operation.
1330template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type all(const A& a) { // Accept the matching input types and dimensions.
1331 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1332 if (!a[i]) // Handle the exceptional or boundary case before continuing.
1333 return false; // Report that at least one component differs.
1334 return true; // Report that every required component matched.
1335} // Finish the all operation.
1336template <class A> // Accept the matching input types and dimensions.
1337typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1338logicalNot(const A& a) { // Invert each boolean component.
1339 vec<bool, detail::traits<A>::size> out; // Keep an independent value for the result or aliased inputs.
1340 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1341 out[i] = !a[i]; // Store the computed component in the independent result.
1342 return out; // Return the completed result.
1343} // Finish the logicalNot operation.
1344template <class A> // Accept the matching input types and dimensions.
1345typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1346_not(const A& a) { // Start the matching math overload.
1347 return glsl::logicalNot(a); // Invert each boolean component.
1348} // Finish the _not operation.
1349/** @} */
1350/** @name 32-bit bit operations
1351 * Reinterpretation uses memcpy and requires IEEE binary32 floats and 32-bit
1352 * integers. Bitfield ranges must satisfy 0 <= offset,bits and offset+bits<=32.
1353 * The 64-bit host intermediates in extended multiplication are never exposed
1354 * to shared shaders. Bit searches and counts return signed integer results.
1355 * @{ */
1356namespace detail { // Keep these names inside the detail namespace.
1357template <class To, class From> To bit_copy(const From& value) { // Accept the matching input types and dimensions.
1358 static_assert(sizeof(To) == sizeof(From), "bit conversion requires equal sizes"); // Check this type or dimension requirement at compile time.
1359 To out; // Allocate a destination with the same bit width.
1360 std::memcpy(&out, &value, sizeof(out)); // Copy the bits with the alias-safe byte-copy operation.
1361 return out; // Return the completed result.
1362} // Finish the bit_copy operation.
1363inline std::uint32_t bit_mask(int bits) { // Start the matching math overload.
1364 return bits == 32 ? UINT32_MAX : (bits == 0 ? 0u : (std::uint32_t(1) << bits) - 1u); // Invert each boolean component.
1365} // Finish the bit_mask operation.
1366template <class T> // Accept the matching input types and dimensions.
1367struct integer32 : std::integral_constant<bool, // Describe this input or selection at compile time.
1368 std::is_integral<T>::value && // Require integer components for the bit operation.
1369 !std::is_same<T, bool>::value && sizeof(T) == 4> {}; // Complete the type and dimension rule for this overload.
1370} // namespace detail
1371inline std::uint32_t floatBitsToUint(float x) { // Copy float bits into an unsigned integer.
1372 static_assert(sizeof(float) == 4 && std::numeric_limits<float>::is_iec559, // Check this type or dimension requirement at compile time.
1373 "IEEE binary32 float required"); // Explain the rejected input: IEEE binary32 float required.
1374 return detail::bit_copy<std::uint32_t>(x); // Copy float bits into an unsigned integer.
1375} // Finish the floatBitsToUint operation.
1376inline std::int32_t floatBitsToInt(float x) { // Copy float bits into a signed integer.
1377 return detail::bit_copy<std::int32_t>(x); // Copy float bits into a signed integer.
1378} // Finish the floatBitsToInt operation.
1379inline float uintBitsToFloat(std::uint32_t x) { // Copy unsigned integer bits into a float.
1380 return detail::bit_copy<float>(x); // Copy unsigned integer bits into a float.
1381} // Finish the uintBitsToFloat operation.
1382inline float intBitsToFloat(std::int32_t x) { // Copy signed integer bits into a float.
1383 return detail::bit_copy<float>(x); // Copy signed integer bits into a float.
1384} // Finish the intBitsToFloat operation.
1385#define SHDR_DETAIL_BIT_VECTOR(NAME, OUT_T) /* Generate the matching scalar and vector overloads. */ \
1386 template <class A> /* Accept the matching input types and dimensions. */ \
1387 typename std::enable_if<detail::traits<A>::vector, vec<OUT_T, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1388 NAME(const A& a) { /* Start the matching math overload. */ \
1389 vec<OUT_T, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1390 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1391 out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1392 return out; /* Return the completed result. */ \
1393 } /* Finish this generated overload. */
1394SHDR_DETAIL_BIT_VECTOR(floatBitsToUint, std::uint32_t) // Copy float bits into an unsigned integer.
1395SHDR_DETAIL_BIT_VECTOR(floatBitsToInt, std::int32_t) // Copy float bits into a signed integer.
1396SHDR_DETAIL_BIT_VECTOR(uintBitsToFloat, float) // Copy unsigned integer bits into a float.
1397SHDR_DETAIL_BIT_VECTOR(intBitsToFloat, float) // Copy signed integer bits into a float.
1398template <class T> // Accept the matching input types and dimensions.
1399typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type bitCount(T x) { // Enable this overload only for compatible input types.
1400 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1401 std::int32_t count = 0; // Hold the exact integer bits used by this operation.
1402 while (v) { // Continue until the remaining bits reach the required form.
1403 v &= v - 1u; // Remove the least significant set bit.
1404 ++count; // Count the set bit that was removed.
1405 } // Finish this component or matrix pass.
1406 return count; // Count the set bits in a 32-bit value.
1407} // Finish the bitCount operation.
1408template <class T> // Accept the matching input types and dimensions.
1409typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findLSB(T x) { // Enable this overload only for compatible input types.
1410 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1411 if (!v) // Handle the exceptional or boundary case before continuing.
1412 return -1; // Find the first set bit from the least significant end.
1413 std::int32_t position = 0; // Hold the exact integer bits used by this operation.
1414 while (!(v & 1u)) { // Continue until the remaining bits reach the required form.
1415 v >>= 1; // Move the next bit into the least significant position.
1416 ++position; // Advance the bit position being tested.
1417 } // Finish this component or matrix pass.
1418 return position; // Find the first set bit from the least significant end.
1419} // Finish the findLSB operation.
1420template <class T> // Accept the matching input types and dimensions.
1421typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findMSB(T x) { // Enable this overload only for compatible input types.
1422 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1423 if (std::is_signed<T>::value && x < T(0)) // Handle the exceptional or boundary case before continuing.
1424 v = ~v; // For negative values, search for the highest zero bit.
1425 std::int32_t position = -1; // Hold the exact integer bits used by this operation.
1426 while (v) { // Continue until the remaining bits reach the required form.
1427 v >>= 1; // Move the next bit into the least significant position.
1428 ++position; // Advance the bit position being tested.
1429 } // Finish this component or matrix pass.
1430 return position; // Find the highest bit that differs from the sign bit.
1431} // Finish the findMSB operation.
1432SHDR_DETAIL_BIT_VECTOR(bitCount, std::int32_t) // Count the set bits in a 32-bit value.
1433SHDR_DETAIL_BIT_VECTOR(findLSB, std::int32_t) // Find the first set bit from the least significant end.
1434SHDR_DETAIL_BIT_VECTOR(findMSB, std::int32_t) // Find the highest bit that differs from the sign bit.
1435#undef SHDR_DETAIL_BIT_VECTOR // Remove this local code generator macro.
1436template <class T> // Accept the matching input types and dimensions.
1437typename std::enable_if<detail::integer32<T>::value, T>::type bitfieldReverse(T x) { // Enable this overload only for compatible input types.
1438 std::uint32_t v = static_cast<std::uint32_t>(x), out = 0; // Hold the exact integer bits used by this operation.
1439 for (int i = 0; i < 32; ++i) { // Visit all 32 bits of the value.
1440 out = (out << 1) | (v & 1u); // Append the current low bit in reversed order.
1441 v >>= 1; // Move the next bit into the least significant position.
1442 } // Finish this component or matrix pass.
1443 return detail::bit_copy<T>(out); // Reverse all 32 bits.
1444} // Finish the bitfieldReverse operation.
1445template <class A> // Accept the matching input types and dimensions.
1446typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1447bitfieldReverse(const A& a) { // Reverse all 32 bits.
1448 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1449 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1450 out[i] = glsl::bitfieldReverse(a[i]); // Store the computed component in the independent result.
1451 return out; // Return the completed result.
1452} // Finish the bitfieldReverse operation.
1453template <class T> // Accept the matching input types and dimensions.
1454typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1455bitfieldExtract(T value, int offset, int bits) { // Extract the requested bit range.
1456 if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1457 return T(0); // Extract the requested bit range.
1458 std::uint32_t mask = detail::bit_mask(bits), // Prepare the mask for the requested bit range.
1459 out = (static_cast<std::uint32_t>(value) >> offset) & mask; // Shift the selected field down and discard other bits.
1460 if (std::is_signed<T>::value && bits < 32 && (out & (std::uint32_t(1) << (bits - 1)))) // Handle the exceptional or boundary case before continuing.
1461 out |= ~mask; // Add the encoded field to its packed bit position.
1462 return detail::bit_copy<T>(out); // Extract the requested bit range.
1463} // Finish the bitfieldExtract operation.
1464template <class A> // Accept the matching input types and dimensions.
1465typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1466bitfieldExtract(const A& a, int offset, int bits) { // Extract the requested bit range.
1467 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1468 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1469 out[i] = glsl::bitfieldExtract(a[i], offset, bits); // Store the computed component in the independent result.
1470 return out; // Return the completed result.
1471} // Finish the bitfieldExtract operation.
1472template <class T> // Accept the matching input types and dimensions.
1473typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1474bitfieldInsert(T base, T insert, int offset, int bits) { // Replace the requested bit range.
1475 if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1476 return base; // Replace the requested bit range.
1477 std::uint32_t mask = detail::bit_mask(bits) << offset; // Prepare the mask for the requested bit range.
1478 std::uint32_t out = (static_cast<std::uint32_t>(base) & ~mask) | // Prepare the mask for the requested bit range.
1479 ((static_cast<std::uint32_t>(insert) << offset) & mask); // Keep only insertion bits that belong to the selected field.
1480 return detail::bit_copy<T>(out); // Replace the requested bit range.
1481} // Finish the bitfieldInsert operation.
1482template <class A, class B> // Accept the matching input types and dimensions.
1483typename std::enable_if<detail::binary<A, B>::valid, typename detail::binary<A, B>::result>::type // Enable this overload only for compatible input types.
1484bitfieldInsert(const A& base, const B& insert, int offset, int bits) { // Replace the requested bit range.
1485 typedef typename detail::binary<A, B>::scalar T; // Keep the chosen component type for the calculation.
1486 typename detail::binary<A, B>::result out; // Allocate an independent result with the correct shape.
1487 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) // Visit each component needed by this calculation.
1488 out[i] = glsl::bitfieldInsert(static_cast<T>(detail::component(base, i)), // Store the computed component in the independent result.
1489 static_cast<T>(detail::component(insert, i)), // Use this component as the replacement bit pattern.
1490 offset, // Use the requested first bit position.
1491 bits); // Use the requested number of replacement bits.
1492 return out; // Return the completed result.
1493} // Finish the bitfieldInsert operation.
1494inline std::uint32_t uaddCarry(std::uint32_t x, std::uint32_t y, std::uint32_t& carry) { // Add unsigned values and report the carry.
1495 std::uint64_t sum = std::uint64_t(x) + y; // Use a wider integer to retain carry or product bits.
1496 carry = std::uint32_t(sum >> 32); // Publish the extra word after the input values have been copied.
1497 return std::uint32_t(sum); // Add unsigned values and report the carry.
1498} // Finish the uaddCarry operation.
1499inline std::uint32_t usubBorrow(std::uint32_t x, std::uint32_t y, std::uint32_t& borrow) { // Subtract unsigned values and report the borrow.
1500 borrow = x < y ? 1u : 0u; // Publish the extra word after the input values have been copied.
1501 return x - y; // Subtract unsigned values and report the borrow.
1502} // Finish the usubBorrow operation.
1503inline void umulExtended(std::uint32_t x, std::uint32_t y, std::uint32_t& msb, std::uint32_t& lsb) { // Split a full unsigned product into two words.
1504 std::uint64_t product = std::uint64_t(x) * y; // Use a wider integer to retain carry or product bits.
1505 msb = std::uint32_t(product >> 32); // Publish the extra word after the input values have been copied.
1506 lsb = std::uint32_t(product); // Publish the extra word after the input values have been copied.
1507} // Finish the umulExtended operation.
1508inline void imulExtended(std::int32_t x, std::int32_t y, std::int32_t& msb, std::int32_t& lsb) { // Split a full signed product into two words.
1509 std::uint64_t product = static_cast<std::uint64_t>(std::int64_t(x) * y); // Use a wider integer to retain carry or product bits.
1510 msb = detail::bit_copy<std::int32_t>(std::uint32_t(product >> 32)); // Publish the extra word after the input values have been copied.
1511 lsb = detail::bit_copy<std::int32_t>(std::uint32_t(product)); // Publish the extra word after the input values have been copied.
1512} // Finish the imulExtended operation.
1513/** @brief Add unsigned vectors modulo 2^32 and write their carry flags. */
1514template <class A, class B, class C> // Accept the matching input types and dimensions.
1515typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1516 detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1517 vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1518uaddCarry(const A& x, const B& y, C&& carry) { // Add unsigned values and report the carry.
1519 static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1520 detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1521 "uaddCarry dimensions mismatch"); // Explain the rejected input: uaddCarry dimensions mismatch.
1522 static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1523 std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1524 std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1525 "uaddCarry requires unsigned integer components"); // Explain the rejected input: uaddCarry requires unsigned integer components.
1526 static_assert(detail::writable<C>::value, // Require distinct writable output components.
1527 "uaddCarry output requires writable unique components"); // Explain the rejected input: uaddCarry output requires writable unique components.
1528 vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1529 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1530 out[i] = glsl::uaddCarry(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1531 carry = flags; // Publish the extra word after the input values have been copied.
1532 return out; // Return the completed result.
1533} // Finish the uaddCarry operation.
1534/** @brief Subtract unsigned vectors modulo 2^32 and write their borrow flags. */
1535template <class A, class B, class C> // Accept the matching input types and dimensions.
1536typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1537 detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1538 vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1539usubBorrow(const A& x, const B& y, C&& borrow) { // Subtract unsigned values and report the borrow.
1540 static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1541 detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1542 "usubBorrow dimensions mismatch"); // Explain the rejected input: usubBorrow dimensions mismatch.
1543 static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1544 std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1545 std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1546 "usubBorrow requires unsigned integer components"); // Explain the rejected input: usubBorrow requires unsigned integer components.
1547 static_assert(detail::writable<C>::value, // Require distinct writable output components.
1548 "usubBorrow output requires writable unique components"); // Explain the rejected input: usubBorrow output requires writable unique components.
1549 vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1550 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1551 out[i] = glsl::usubBorrow(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1552 borrow = flags; // Publish the extra word after the input values have been copied.
1553 return out; // Return the completed result.
1554} // Finish the usubBorrow operation.
1555#define SHDR_DETAIL_EXTENDED(NAME, T) /* Generate the matching scalar and vector overloads. */ \
1556 template <class A, class B, class C, class D> /* Accept the matching input types and dimensions. */ \
1557 typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && /* Enable this overload only for compatible input types. */ \
1558 detail::traits<C>::vector && detail::traits<D>::vector>::type /* Complete the type and dimension rule for this overload. */ \
1559 NAME(const A& x, const B& y, C&& msb, D&& lsb) { /* Start the matching math overload. */ \
1560 static_assert(detail::traits<A>::size == detail::traits<B>::size && /* Require matching component counts. */ \
1561 detail::traits<A>::size == detail::traits<C>::size && /* Complete the type and dimension rule for this overload. */ \
1562 detail::traits<A>::size == detail::traits<D>::size, /* Complete the type and dimension rule for this overload. */ \
1563 "extended multiplication dimensions mismatch"); /* Explain the rejected input: extended multiplication dimensions mismatch. */ \
1564 static_assert(std::is_same<typename detail::traits<A>::scalar, T>::value && /* Check this type or dimension requirement at compile time. */ \
1565 std::is_same<typename detail::traits<B>::scalar, T>::value && /* Require the second input to use the selected integer type. */ \
1566 std::is_same<typename detail::traits<C>::scalar, T>::value && /* Require the high output word to use the selected integer type. */ \
1567 std::is_same<typename detail::traits<D>::scalar, T>::value, /* Require the low output word to use the selected integer type. */ \
1568 "extended multiplication component types must match"); /* Explain the rejected input: extended multiplication component types must match. */ \
1569 static_assert(detail::writable<C>::value && detail::writable<D>::value, /* Require distinct writable output components. */ \
1570 "extended multiplication requires writable unique output components"); /* Explain the rejected input: extended multiplication requires writable unique output components. */ \
1571 vec<T, detail::traits<A>::size> a(x), b(y), high, low; /* Keep an independent value for the result or aliased inputs. */ \
1572 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { /* Visit each component needed by this calculation. */ \
1573 glsl::NAME(a[i], b[i], high[i], low[i]); /* Compute both words for this pair of copied components. */ \
1574 } /* Finish this component or matrix pass. */ \
1575 msb = high; /* Publish the extra word after the input values have been copied. */ \
1576 lsb = low; /* Publish the extra word after the input values have been copied. */ \
1577 } /* Finish this generated overload. */
1578SHDR_DETAIL_EXTENDED(umulExtended, std::uint32_t) // Split a full unsigned product into two words.
1579SHDR_DETAIL_EXTENDED(imulExtended, std::int32_t) // Split a full signed product into two words.
1580#undef SHDR_DETAIL_EXTENDED // Remove this local code generator macro.
1581/** @} */
1582
1583/** @name Packing
1584 * Normalized packing follows the GLSL clamp-and-round formulas. unpacking
1585 * places the least significant byte/halfword in x. Half-float encoding rounds
1586 * to nearest even and preserves infinities and a quiet-NaN representation.
1587 * @{ */
1588inline std::uint32_t packUnorm2x16(const vec2& v) { // Pack two normalized values into 16-bit fields.
1589 std::uint32_t x = std::uint32_t(std::round(glsl::clamp(v.x, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1590 std::uint32_t y = std::uint32_t(std::round(glsl::clamp(v.y, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1591 return x | (y << 16); // Pack two normalized values into 16-bit fields.
1592} // Finish the packUnorm2x16 operation.
1593inline vec2 unpackUnorm2x16(std::uint32_t p) { // Decode two unsigned normalized 16-bit fields.
1594 return vec2(float(p & 65535u), float(p >> 16)) / 65535.0f; // Decode two unsigned normalized 16-bit fields.
1595} // Finish the unpackUnorm2x16 operation.
1596inline std::uint32_t packSnorm2x16(const vec2& v) { // Pack two signed normalized values into 16-bit fields.
1597 std::int32_t x = std::int32_t(std::round(glsl::clamp(v.x, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1598 std::int32_t y = std::int32_t(std::round(glsl::clamp(v.y, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1599 return (std::uint32_t(x) & 65535u) | (std::uint32_t(y) << 16); // Pack two signed normalized values into 16-bit fields.
1600} // Finish the packSnorm2x16 operation.
1601inline vec2 unpackSnorm2x16(std::uint32_t p) { // Decode two signed normalized 16-bit fields.
1602 std::int32_t x = std::int32_t(p & 65535u), y = std::int32_t(p >> 16); // Hold the exact integer bits used by this operation.
1603 if (x & 32768) // Handle the exceptional or boundary case before continuing.
1604 x -= 65536; // Extend the stored signed field into a signed scalar.
1605 if (y & 32768) // Handle the exceptional or boundary case before continuing.
1606 y -= 65536; // Extend the stored signed field into a signed scalar.
1607 return glsl::clamp(vec2(x, y) / 32767.0f, -1.0f, 1.0f); // Decode two signed normalized 16-bit fields.
1608} // Finish the unpackSnorm2x16 operation.
1609inline std::uint32_t packUnorm4x8(const vec4& v) { // Pack four normalized values into bytes.
1610 std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1611 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1612 out |= std::uint32_t(std::round(glsl::clamp(v[i], 0.0f, 1.0f) * 255.0f)) << (i * 8); // Add the encoded field to its packed bit position.
1613 return out; // Return the completed result.
1614} // Finish the packUnorm4x8 operation.
1615inline vec4 unpackUnorm4x8(std::uint32_t p) { // Decode four unsigned normalized bytes.
1616 vec4 out; // Allocate four independent unpacked components.
1617 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1618 out[i] = float((p >> (i * 8)) & 255u) / 255.0f; // Store the computed component in the independent result.
1619 return out; // Return the completed result.
1620} // Finish the unpackUnorm4x8 operation.
1621inline std::uint32_t packSnorm4x8(const vec4& v) { // Pack four signed normalized values into bytes.
1622 std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1623 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1624 out |= (std::uint32_t(std::int32_t(std::round(glsl::clamp(v[i], -1.0f, 1.0f) * 127.0f))) & // Add the encoded field to its packed bit position.
1625 255u) // Keep only the low byte of the signed normalized encoding.
1626 << (i * 8); // Move that byte into its component position.
1627 return out; // Return the completed result.
1628} // Finish the packSnorm4x8 operation.
1629inline vec4 unpackSnorm4x8(std::uint32_t p) { // Decode four signed normalized bytes.
1630 vec4 out; // Allocate four independent unpacked components.
1631 for (std::size_t i = 0; i < 4; ++i) { // Visit each component needed by this calculation.
1632 int v = int((p >> (i * 8)) & 255u); // Extract this byte into a signed-capable scalar.
1633 if (v & 128) // Handle the exceptional or boundary case before continuing.
1634 v -= 256; // Extend an eight-bit negative value to the scalar type.
1635 out[i] = glsl::max(float(v) / 127.0f, -1.0f); // Store the computed component in the independent result.
1636 } // Finish this component or matrix pass.
1637 return out; // Return the completed result.
1638} // Finish the unpackSnorm4x8 operation.
1639namespace detail { // Keep these names inside the detail namespace.
1640inline std::uint16_t float_to_half(float value) { // Encode an IEEE half with ties rounded to even.
1641 std::uint32_t bits = glsl::floatBitsToUint(value), sign = (bits >> 16) & 32768u; // Separate the sign and payload bits for the conversion.
1642 int exponent = int((bits >> 23) & 255u) - 127 + 15; // Translate the exponent bias to the target float format.
1643 std::uint32_t mantissa = bits & 8388607u; // Keep the floating-point significand bits for encoding.
1644 if (((bits >> 23) & 255u) == 255u) // Handle the exceptional or boundary case before continuing.
1645 return std::uint16_t(sign | 31744u | (mantissa ? 512u : 0u)); // Encode an IEEE half with ties rounded to even.
1646 if (exponent >= 31) // Select the matching half-float exponent range.
1647 return std::uint16_t(sign | 31744u); // Encode an IEEE half with ties rounded to even.
1648 if (exponent <= 0) { // Select the matching half-float exponent range.
1649 if (exponent < -10) // Select the matching half-float exponent range.
1650 return std::uint16_t(sign); // Encode an IEEE half with ties rounded to even.
1651 mantissa |= 8388608u; // Restore the implicit leading significand bit.
1652 unsigned shift = unsigned(14 - exponent); // Choose the right shift for a half-float subnormal.
1653 std::uint32_t truncated = mantissa >> shift, remainder = mantissa & ((1u << shift) - 1u), // Keep the floating-point significand bits for encoding.
1654 halfway = 1u << (shift - 1); // Identify the exact halfway rounding bit.
1655 if (remainder > halfway || (remainder == halfway && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1656 ++truncated; // Round the retained encoding to the next representable value.
1657 return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1658 } // Finish handling this condition.
1659 std::uint32_t truncated = (std::uint32_t(exponent) << 10) | (mantissa >> 13), // Keep the floating-point significand bits for encoding.
1660 remainder = mantissa & 8191u; // Retain the discarded low bits for the rounding decision.
1661 if (remainder > 4096u || (remainder == 4096u && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1662 ++truncated; // Round the retained encoding to the next representable value.
1663 return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1664} // Finish the float_to_half operation.
1665inline float half_to_float(std::uint16_t h) { // Expand an IEEE half into a float.
1666 std::uint32_t sign = (std::uint32_t(h) & 32768u) << 16, mantissa = h & 1023u; // Separate the sign and payload bits for the conversion.
1667 int exponent = (h >> 10) & 31; // Translate the exponent bias to the target float format.
1668 if (exponent == 0) { // Select the matching half-float exponent range.
1669 if (!mantissa) // Handle the exceptional or boundary case before continuing.
1670 return glsl::uintBitsToFloat(sign); // Expand an IEEE half into a float.
1671 exponent = -14; // Set the exponent for a subnormal source value.
1672 while (!(mantissa & 1024u)) { // Continue until the remaining bits reach the required form.
1673 mantissa <<= 1; // Move the first significand bit toward the normalized position.
1674 --exponent; // Adjust the exponent while normalizing the significand.
1675 } // Finish this component or matrix pass.
1676 mantissa &= 1023u; // Remove the leading bit before storing the fraction.
1677 return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent + 127) << 23) | // Expand an IEEE half into a float.
1678 (mantissa << 13)); // Place the expanded significand in the float fraction field.
1679 } // Finish handling this condition.
1680 if (exponent == 31) // Select the matching half-float exponent range.
1681 return glsl::uintBitsToFloat(sign | 2139095040u | (mantissa << 13)); // Expand an IEEE half into a float.
1682 return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent - 15 + 127) << 23) | // Expand an IEEE half into a float.
1683 (mantissa << 13)); // Place the expanded significand in the float fraction field.
1684} // Finish the half_to_float operation.
1685} // namespace detail
1686inline std::uint32_t packHalf2x16(const vec2& v) { // Pack two IEEE half encodings into one word.
1687 return std::uint32_t(detail::float_to_half(v.x)) | // Pack two IEEE half encodings into one word.
1688 (std::uint32_t(detail::float_to_half(v.y)) << 16); // Place the second half encoding in the upper word.
1689} // Finish the packHalf2x16 operation.
1690inline vec2 unpackHalf2x16(std::uint32_t v) { // Expand the two IEEE half encodings.
1691 return vec2(detail::half_to_float(std::uint16_t(v)), // Expand the two IEEE half encodings.
1692 detail::half_to_float(std::uint16_t(v >> 16))); // Expand the upper half encoding into the second component.
1693} // Finish the unpackHalf2x16 operation.
1694/** @} */
1695} // namespace glsl
1696} // namespace shdr
1697#endif // Finish the math layer include guard.
1698
1699// ---- runtime.hpp ----
1700#ifndef SHDR_RUNTIME_HPP // Skip this section if it was already included.
1701#define SHDR_RUNTIME_HPP /* Mark this section as included. */
1702
1703/** @brief Major version of shdr. */
1704#define SHDR_VERSION_MAJOR 1 // Identify the public API's major release series.
1705/** @brief Minor version within the current major release. */
1706#define SHDR_VERSION_MINOR 0 // Identify additions within the public API's release series.
1707/** @brief Patch version within the current minor release. */
1708#define SHDR_VERSION_PATCH 0 // Identify corrections within this minor release.
1709/** @brief The library release version as a string. */
1710#define SHDR_VERSION "1.0.0" // Expose the library release as a compile-time string.
1711
1712#include <algorithm> // Use standard searches, bounds, and resource copying.
1713#include <cstddef> // Use portable pointer sizes and offsets.
1714#include <cstdint> // Use integer widths that match GLSL values.
1715#include <cctype> // Recognize characters in embedded shader declarations.
1716#include <cstring> // Copy bytes and function addresses with std::memcpy.
1717#include <functional> // Store GL resolvers and deferred cleanup callbacks.
1718#include <initializer_list> // Accept concise resource initialization from application values.
1719#include <limits> // Check arithmetic against the type limits.
1720#include <map> // Find registered shader factories and shared kernel snapshots.
1721#include <memory> // Retain resources while pipelines and queued jobs use them.
1722#include <mutex> // Protect shared work queues and deferred deletion.
1723#include <thread> // Track the context thread and start CPU workers.
1724#include <sstream> // Build readable shader and driver diagnostics.
1725#include <stdexcept> // Report invalid resources and failed execution.
1726#include <string> // Keep embedded shader text and named interfaces.
1727#include <type_traits> // Check shader storage and port types at compile time.
1728#include <vector> // Store ordered stages, ports, and resource values.
1729
1730/** @brief Portable, header-only CPU/OpenGL compute pipelines. */
1731namespace shdr { // Group these definitions in the shdr namespace.
1732/** @brief A shader, resource, context or dispatch validation failure. */
1733struct error : std::runtime_error { // Keep the error values and operations together.
1734 explicit error(const std::string& s) : std::runtime_error(s) { // Preserve the supplied validation or driver diagnostic.
1735 } // End this scope in runtime.
1736}; // End this scope in runtime.
1737
1738/** @brief Three unsigned dimensions. dispatch dimensions count work groups. */
1739struct extent { // Keep the extent values and operations together.
1740 unsigned x, y, z; // Keep the three unsigned dispatch or local dimensions.
1741 /** @brief Construct three workgroup counts, defaulting each dimension to one. */
1742 explicit extent(unsigned x_ = 1, unsigned y_ = 1, unsigned z_ = 1) : x(x_), y(y_), z(z_) { // Initialize all three positive-or-zero dimensions supplied by the caller.
1743 } // End this scope in runtime.
1744}; // End this scope in runtime.
1745/** @brief Minimum shader language selected independently of the context's actual version. */
1746enum class profile { es31, es32, gl43, gl45, gl46 }; // Name the supported shader language profiles.
1747/** @brief Automatic uses CPU execution for run() and GPU execution for run(device). */
1748enum class backend { automatic, cpu, gpu }; // Select automatic, explicit CPU or explicit GPU execution.
1749/** @brief Resource access qualifiers. readonly also prevents CPU writes at compile time. */
1750enum class access { readonly, writeonly, readwrite }; // Express how a shader may access a bound resource.
1751
1752namespace detail { // Group these definitions in the detail namespace.
1753inline bool identifier_char(char c) { // Recognize the letters, digits, and underscore allowed in an identifier.
1754 return std::isalnum(static_cast<unsigned char>(c)) || c == '_'; // Recognize the letters, digits, and underscore allowed in an identifier.
1755} // End this scope in identifier char.
1756inline std::string trim(const std::string& text) { // Remove surrounding whitespace from one resource argument.
1757 const std::size_t first = text.find_first_not_of(" \t\r\n"); // Set the first non-space character.
1758 return first == std::string::npos // Remove surrounding whitespace from one resource argument.
1759 ? std::string() // Select the value for this branch of the condition.
1760 : text.substr(first, text.find_last_not_of(" \t\r\n") - first + 1); // Copy only the non-whitespace portion of this argument.
1761} // End this scope in trim.
1762 // ESSL forbids token-pasting macros. Expand only resource declarations in the host,
1763 // preserving comments, string literals, shader statements and original line numbers.
1764inline std::string expand_declarations(const std::string& source, bool es) { // Expand host resource declarations into native GLSL interfaces.
1765 std::string out; // Keep the assembled shader text.
1766 for (std::size_t i = 0; i < source.size();) { // Walk the embedded shader text while respecting its token boundaries.
1767 const std::size_t start = i; // Set the beginning of the current token or range.
1768 if (source.compare(i, 2, "//") == 0) { // Copy the line comment verbatim.
1769 const std::size_t end = source.find('\n', i); // Set the end of the current range.
1770 i = end == std::string::npos ? source.size() : end + 1; // Advance beyond the preserved comment or declaration.
1771 } else if (source.compare(i, 2, "/*") == 0) { // Copy the block comment verbatim.
1772 const std::size_t end = source.find("*/", i + 2); // Set the end of the current range.
1773 i = end == std::string::npos ? source.size() : end + 2; // Advance beyond the preserved comment or declaration.
1774 } else if (source[i] == '\"' || source[i] == '\'') { // Copy quoted shader text as one lexical unit.
1775 const char quote = source[i++]; // Remember which quote terminates this shader literal.
1776 while (i < source.size()) { // Walk the embedded shader text while respecting its token boundaries.
1777 if (source[i] == '\\') { // Treat an escaped character as part of the quoted shader text.
1778 i = (std::min)(i + 2, source.size()); // Advance past the escaped character within the source bounds.
1779 continue; // Continue with the next token or work item.
1780 } // End this scope in expand declarations.
1781 if (source[i++] == quote) // Choose this branch when source[i++] equals quote.
1782 break; // Stop this search or loop once its current item is complete.
1783 } // End this scope in expand declarations.
1784 } else if (identifier_char(source[i])) { // Recognize the letters, digits, and underscore allowed in an identifier.
1785 while (i < source.size() && identifier_char(source[i])) // Walk the embedded shader text while respecting its token boundaries.
1786 ++i; // Expand host resource declarations into native GLSL interfaces.
1787 const std::string token = source.substr(start, i - start); // Set the current shader identifier.
1788 if (token == "SHDR_BUFFER" || token == "SHDR_IMAGE2D") { // Choose this branch when token equals "SHDR BUFFER" or token equals "SHDR IMAGE2D".
1789 std::size_t open = i; // Set the opening parenthesis of a resource declaration.
1790 while (open < source.size() && // Walk the embedded shader text while respecting its token boundaries.
1791 std::isspace(static_cast<unsigned char>(source[open]))) // Keep the opening parenthesis of a resource declaration.
1792 ++open; // Keep the opening parenthesis of a resource declaration.
1793 if (open >= source.size() || source[open] != '(') // Check resource size or driver limits before accessing storage.
1794 throw error("resource declaration requires parentheses: " + token); // Report resource declaration requires parentheses: .
1795 std::size_t end = open + 1, argument = end; // Set the end of the current range.
1796 unsigned depth = 1; // Set the current parenthesis nesting.
1797 std::vector<std::string> args; // Keep the parsed declaration arguments.
1798 for (; end < source.size(); ++end) { // Walk the embedded shader text while respecting its token boundaries.
1799 if (source[end] == '(') // Choose this branch when source[end] equals '('.
1800 ++depth; // Keep the current parenthesis nesting.
1801 if (source[end] == ')') // Choose this branch when source[end] equals ')'.
1802 --depth; // Keep the current parenthesis nesting.
1803 if ((source[end] == ',' && depth == 1) || depth == 0) { // Choose this branch when (source[end] equals ',' and depth equals 1) or depth equals 0.
1804 args.push_back(trim(source.substr(argument, end - argument))); // Retain this entry in the ordered resource or work collection.
1805 argument = end + 1; // Set the beginning of the next resource argument.
1806 } // End this scope in expand declarations.
1807 if (!depth) // Finish the argument list at its matching closing parenthesis.
1808 break; // Stop this search or loop once its current item is complete.
1809 } // End this scope in expand declarations.
1810 const bool image = token == "SHDR_IMAGE2D"; // Choose image or storage-buffer declaration syntax.
1811 if (depth || args.size() != (image ? 5u : 4u)) // Check resource size or driver limits before accessing storage.
1812 throw error("invalid resource declaration: " + token); // Report invalid resource declaration: .
1813 const std::string mode = args.back(); // Set the declared shader resource access.
1814 if (mode != "readonly" && mode != "writeonly" && mode != "readwrite") // Choose the branch matching this interface or resource access.
1815 throw error("invalid resource access: " + mode); // Report invalid resource access: .
1816 const std::string qualifier = mode == "readwrite" ? "" : mode + " "; // Set the access qualifier emitted into GLSL.
1817 if (image) { // Choose this branch when image.
1818 if (es && mode == "readwrite" && args[1].compare(0, 4, "rgba") == 0) // Choose the branch matching this interface or resource access.
1819 throw error( // Report the invalid operation.
1820 "GLES RGBA images require readonly or writeonly declarations: " + // Append this literal GLSL source fragment.
1821 args[3]); // Expand host resource declarations into native GLSL interfaces.
1822 out += "layout(" + args[1] + ",binding=" + args[0] + ") " + qualifier + // Set the assembled shader text.
1823 "uniform highp " + args[2] + " " + args[3] + ";"; // Append this literal GLSL source fragment.
1824 } else // Handle the alternative resource or completion case.
1825 out += "layout(std430,binding=" + args[0] + ") " + qualifier + // Set the assembled shader text.
1826 "buffer shdr_block_" + args[2] + " { " + args[1] + " " + args[2] + // Append this literal GLSL source fragment.
1827 "[]; };"; // Append this literal GLSL source fragment.
1828 out.append(static_cast<std::size_t>( // Restore the original declaration's line count after expansion.
1829 std::count(source.begin() + static_cast<std::ptrdiff_t>(start), // Keep the beginning of the current token or range.
1830 source.begin() + static_cast<std::ptrdiff_t>(end + 1), // Stop counting at the end of the replaced resource declaration.
1831 '\n')), // Count the newlines originally present in this declaration.
1832 '\n'); // Append one newline for each removed original newline.
1833 i = end + 1; // Advance beyond the preserved comment or declaration.
1834 continue; // Continue with the next token or work item.
1835 } // End this scope in expand declarations.
1836 } else // Handle the alternative resource or completion case.
1837 ++i; // Expand host resource declarations into native GLSL interfaces.
1838 out.append(source, start, i - start); // Preserve this untouched token or comment in the exported GLSL.
1839 } // End this scope in expand declarations.
1840 return out; // Return the assembled shader text.
1841} // End this scope in expand declarations.
1842} // namespace detail
1843
1844/** @internal Export an embedded shader as standard GLSL, with version and declaration macros.
1845 * This function supplies the version directive. Guard the body's C++ include
1846 * with #ifdef __cplusplus. The exported source contains the selected version
1847 * and expanded declarations.
1848 */
1849inline std::string glsl_source(const std::string& source, profile p) { // Add the selected GLSL version and shared-declaration definitions.
1850 std::istringstream lines(source); // Read the embedded shader one line at a time.
1851 std::string line; // Read each embedded source line while checking version directives.
1852 while (std::getline(lines, line)) { // Inspect each source line for an unsupported version directive.
1853 std::size_t start = line.find_first_not_of(" \t\r"); // Set the beginning of the current token or range.
1854 if (start != std::string::npos && line[start] == '#') { // Choose this branch when start differs from std::string::npos and line[start] equals '#'.
1855 start = line.find_first_not_of(" \t", start + 1); // Set the beginning of the current token or range.
1856 if (start != std::string::npos && line.compare(start, 7, "version") == 0) // Choose this branch when start differs from std::string::npos and line.compare(start, 7, "version") equals 0.
1857 throw error("shared shaders must omit #version; glsl_source supplies it"); // Report shared shaders must omit #version. glsl_source supplies it.
1858 } // End this scope in glsl source.
1859 } // End this scope in glsl source.
1860 const char* version = p == profile::es31 ? "310 es" // Set the current GL version text.
1861 : p == profile::es32 ? "320 es" // Select the version associated with this shader profile.
1862 : p == profile::gl43 ? "430 core" // Select the version associated with this shader profile.
1863 : p == profile::gl45 ? "450 core" // Select the version associated with this shader profile.
1864 : "460 core"; // Select desktop GLSL 4.60 for the remaining profile.
1865 std::string out = std::string("#version ") + version + "\n"; // Set the assembled shader text.
1866 if (p == profile::es31 || p == profile::es32) // Choose this branch when p equals profile::es31 or p equals profile::es32.
1867 out += "precision highp float;\nprecision highp int;\n"; // Set the assembled shader text.
1868 out += // Set the assembled shader text.
1869 "#define SHDR_BEGIN(name,x,y,z) layout(local_size_x=x,local_size_y=y,local_size_z=z) in;\n" // Emit a native workgroup declaration for this shader.
1870 "#define SHDR_END()\n" // Remove the host-only shader wrapper terminator.
1871 "#define SHDR_MAIN() void main()\n" // Map the shared entry-point spelling to native GLSL main.
1872 "#define SHDR_UNIFORM(t,n) uniform t n;\n" // Emit a native typed uniform declaration.
1873 "#define SHDR_SWIZZLE(v,s) (v).s\n" // Map shared swizzle syntax to native GLSL component selection.
1874 "#define SHDR_NOT(v) not(v)\n" // Map shared boolean negation to the native GLSL builtin.
1875 "#define SHDR_IN(t,n) in t n\n" // Emit a native input parameter qualifier.
1876 "#define SHDR_OUT(t,n) out t n\n" // Emit a native output parameter qualifier.
1877 "#define SHDR_INOUT(t,n) inout t n\n" // Emit a native input-output parameter qualifier.
1878 "#line 1\n"; // Restore shader line numbering before appending the original source.
1879 // Desktop GLSL accepts highp precision qualifiers from GLSL 4.10 onward.
1880 return out + detail::expand_declarations(source, p == profile::es31 || p == profile::es32); // Add the selected GLSL version and shared-declaration definitions.
1881} // End this scope in glsl source.
1882
1883namespace detail { // Group these definitions in the detail namespace.
1884 // Private GL types and entry points keep the default header compatible with standard C++11.
1885typedef unsigned int GLenum; // Name the representation used by this GL or shader interface.
1886typedef unsigned int GLuint; // Name the representation used by this GL or shader interface.
1887typedef int GLint; // Name the representation used by this GL or shader interface.
1888typedef int GLsizei; // Name the representation used by this GL or shader interface.
1889typedef unsigned int GLbitfield; // Name the representation used by this GL or shader interface.
1890typedef unsigned char GLboolean; // Name the representation used by this GL or shader interface.
1891typedef std::ptrdiff_t GLsizeiptr; // Name the representation used by this GL or shader interface.
1892typedef std::ptrdiff_t GLintptr; // Name the representation used by this GL or shader interface.
1893typedef std::uint64_t GLuint64; // Name the representation used by this GL or shader interface.
1894typedef void* GLsync; // Name the representation used by this GL or shader interface.
1895#if defined(_WIN32) // Compile this branch only when its platform or backend condition holds.
1896#define SHDR_GL_CALL __stdcall /* Match the calling convention of the GL entry points. */
1897#else // Use the alternative platform or backend definition.
1898#define SHDR_GL_CALL /* Match the calling convention of the GL entry points. */
1899#endif // Finish this conditional section.
1900enum : unsigned { // Name the profile, access, or completion values accepted by this section.
1901 VERSION = 0x1F02, // Use the GL numeric code for version.
1902 MAJOR_VERSION = 0x821B, // Use the GL numeric code for major version.
1903 MINOR_VERSION = 0x821C, // Use the GL numeric code for minor version.
1904 COMPUTE_SHADER = 0x91B9, // Use the GL numeric code for compute shader.
1905 COMPILE_STATUS = 0x8B81, // Use the GL numeric code for compile status.
1906 LINK_STATUS = 0x8B82, // Use the GL numeric code for link status.
1907 INFO_LOG_LENGTH = 0x8B84, // Use the GL numeric code for info log length.
1908 COMPUTE_WORK_GROUP_SIZE = 0x8267, // Use the GL numeric code for compute work group size.
1909 MAX_COMPUTE_WORK_GROUP_COUNT = 0x91BE, // Use the GL numeric code for max compute work group count.
1910 MAX_COMPUTE_WORK_GROUP_SIZE = 0x91BF, // Use the GL numeric code for max compute work group size.
1911 MAX_COMPUTE_WORK_GROUP_INVOCATIONS = 0x90EB, // Use the GL numeric code for max compute work group invocations.
1912 MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD, // Use the GL numeric code for max shader storage buffer bindings.
1913 MAX_IMAGE_UNITS = 0x8F38, // Use the GL numeric code for max image units.
1914 SHADER_STORAGE_BUFFER = 0x90D2, // Use the GL numeric code for shader storage buffer.
1915 DYNAMIC_DRAW = 0x88E8, // Use the GL numeric code for dynamic draw.
1916 MAP_READ_BIT = 1, // Use the GL numeric code for map read bit.
1917 ALL_BARRIER_BITS = 0xFFFFFFFFu, // Use the GL numeric code for all barrier bits.
1918 TEXTURE_2D = 0x0DE1, // Identify a two-dimensional texture target.
1919 FLOAT = 0x1406, // Use the GL numeric code for float.
1920 INT = 0x1404, // Use the GL numeric code for int.
1921 UNSIGNED_INT = 0x1405, // Use the GL numeric code for unsigned int.
1922 RED = 0x1903, // Use the GL numeric code for red.
1923 RGBA = 0x1908, // Use the GL numeric code for rgba.
1924 RED_INTEGER = 0x8D94, // Use the GL numeric code for red integer.
1925 RGBA_INTEGER = 0x8D99, // Use the GL numeric code for rgba integer.
1926 R32F = 0x822E, // Store one 32-bit floating-point component per pixel.
1927 R32I = 0x8235, // Store one signed 32-bit component per pixel.
1928 R32UI = 0x8236, // Store one unsigned 32-bit component per pixel.
1929 RGBA32F = 0x8814, // Store four 32-bit floating-point components per pixel.
1930 RGBA32I = 0x8D82, // Store four signed 32-bit components per pixel.
1931 RGBA32UI = 0x8D70, // Store four unsigned 32-bit components per pixel.
1932 READ_ONLY = 0x88B8, // Use the GL numeric code for read only.
1933 WRITE_ONLY = 0x88B9, // Use the GL numeric code for write only.
1934 READ_WRITE = 0x88BA, // Use the GL numeric code for read write.
1935 UNPACK_ALIGNMENT = 0x0CF5, // Use the GL numeric code for unpack alignment.
1936 UNPACK_ROW_LENGTH = 0x0CF2, // Use the GL numeric code for unpack row length.
1937 UNPACK_SKIP_ROWS = 0x0CF3, // Use the GL numeric code for unpack skip rows.
1938 UNPACK_SKIP_PIXELS = 0x0CF4, // Use the GL numeric code for unpack skip pixels.
1939 PIXEL_UNPACK_BUFFER = 0x88EC, // Use the GL numeric code for pixel unpack buffer.
1940 SYNC_GPU_COMMANDS_COMPLETE = 0x9117, // Use the GL numeric code for sync gpu commands complete.
1941 ALREADY_SIGNALED = 0x911A, // Use the GL numeric code for already signaled.
1942 TIMEOUT_EXPIRED = 0x911B, // Use the GL numeric code for timeout expired.
1943 CONDITION_SATISFIED = 0x911C, // Use the GL numeric code for condition satisfied.
1944 WAIT_FAILED = 0x911D, // Use the GL numeric code for wait failed.
1945 SYNC_FLUSH_COMMANDS_BIT = 1 // Use the GL numeric code for sync flush commands bit.
1946}; // End this scope in runtime.
1947
1948struct gl_api { // Keep the gl api values and operations together.
1949#define SHDR_GL_PROC(ret, n, args) /* Declare a GL function pointer with its exact argument types. */ \
1950 typedef ret(SHDR_GL_CALL* n##_type) args; /* Name the representation used by this GL or shader interface. */ \
1951 n##_type n; /* Store the resolved function pointer for this GL entry point. */
1952 SHDR_GL_PROC(const unsigned char*, GetString, (GLenum)) // Declare a function to read the driver version or renderer text.
1953 SHDR_GL_PROC(void, GetIntegerv, (GLenum, GLint*)) // Declare a function to read a scalar device limit or current binding.
1954 SHDR_GL_PROC(void, GetIntegeri_v, (GLenum, GLuint, GLint*)) // Declare a function to read the limit for a selected compute axis.
1955 SHDR_GL_PROC(GLenum, GetError, ()) // Declare a function to read the pending GL error code.
1956 SHDR_GL_PROC(GLuint, CreateShader, (GLenum)) // Declare a function to allocate a compute shader object.
1957 SHDR_GL_PROC(void, ShaderSource, (GLuint, GLsizei, const char* const*, const GLint*)) // Declare a function to supply the embedded shader text to the driver.
1958 SHDR_GL_PROC(void, CompileShader, (GLuint)) // Declare a function to ask the driver to compile the compute shader.
1959 SHDR_GL_PROC(void, GetShaderiv, (GLuint, GLenum, GLint*)) // Declare a function to read shader compilation status or log length.
1960 SHDR_GL_PROC(void, GetShaderInfoLog, (GLuint, GLsizei, GLsizei*, char*)) // Declare a function to read the driver explanation of a shader compilation failure.
1961 SHDR_GL_PROC(void, DeleteShader, (GLuint)) // Declare a function to release the temporary shader object.
1962 SHDR_GL_PROC(GLuint, CreateProgram, ()) // Declare a function to allocate the linked compute program.
1963 SHDR_GL_PROC(void, AttachShader, (GLuint, GLuint)) // Declare a function to attach the compute shader before linking.
1964 SHDR_GL_PROC(void, LinkProgram, (GLuint)) // Declare a function to link the compiled compute program.
1965 SHDR_GL_PROC(void, GetProgramiv, (GLuint, GLenum, GLint*)) // Declare a function to read linked-program status, log length, or local dimensions.
1966 SHDR_GL_PROC(void, GetProgramInfoLog, (GLuint, GLsizei, GLsizei*, char*)) // Declare a function to read the driver explanation of a program-link failure.
1967 SHDR_GL_PROC(void, DeleteProgram, (GLuint)) // Declare a function to release the GL program after its owners finish using it.
1968 SHDR_GL_PROC(void, UseProgram, (GLuint)) // Declare a function to select the compute program for the next dispatch.
1969 SHDR_GL_PROC(GLint, GetUniformLocation, (GLuint, const char*)) // Declare a function to find a named uniform in the linked program.
1970 SHDR_GL_PROC(void, Uniform1f, (GLint, float)) // Declare a function to assign a float uniform.
1971 SHDR_GL_PROC(void, Uniform1i, (GLint, GLint)) // Declare a function to assign an integer or boolean uniform.
1972 SHDR_GL_PROC(void, Uniform1ui, (GLint, GLuint)) // Declare a function to assign an unsigned integer uniform.
1973#define SHDR_GL_UNIFORM(n) /* Define the SHDR_GL_UNIFORM helper for this group of declarations. */ \
1974 SHDR_GL_PROC(void, Uniform##n##fv, (GLint, GLsizei, const float*)) /* Declare a function to send this typed uniform to GL. */ \
1975 SHDR_GL_PROC(void, Uniform##n##iv, (GLint, GLsizei, const GLint*)) /* Declare a function to send this typed uniform to GL. */ \
1976 SHDR_GL_PROC(void, Uniform##n##uiv, (GLint, GLsizei, const GLuint*)) /* Declare a function to send this typed uniform to GL. */
1977 SHDR_GL_UNIFORM(2) // Declare the GL functions for vectors with this component count.
1978 SHDR_GL_UNIFORM(3) // Declare the GL functions for vectors with this component count.
1979 SHDR_GL_UNIFORM(4) // Declare the GL functions for vectors with this component count.
1980#undef SHDR_GL_UNIFORM // Remove this temporary macro after its declarations are complete.
1981#define SHDR_GL_MATRIX(n) /* Define the SHDR_GL_MATRIX helper for this group of declarations. */ \
1982 SHDR_GL_PROC(void, UniformMatrix##n##fv, (GLint, GLsizei, GLboolean, const float*)) /* Declare a function to send this typed uniform to GL. */
1983 SHDR_GL_MATRIX(2) // Declare the GL function for this column-major matrix shape.
1984 SHDR_GL_MATRIX(3) // Declare the GL function for this column-major matrix shape.
1985 SHDR_GL_MATRIX(4) // Declare the GL function for this column-major matrix shape.
1986 SHDR_GL_MATRIX(2x3) // Declare the GL function for this column-major matrix shape.
1987 SHDR_GL_MATRIX(2x4) // Declare the GL function for this column-major matrix shape.
1988 SHDR_GL_MATRIX(3x2) // Declare the GL function for this column-major matrix shape.
1989 SHDR_GL_MATRIX(3x4) // Declare the GL function for this column-major matrix shape.
1990 SHDR_GL_MATRIX(4x2) // Declare the GL function for this column-major matrix shape.
1991 SHDR_GL_MATRIX(4x3) // Declare the GL function for this column-major matrix shape.
1992#undef SHDR_GL_MATRIX // Remove this temporary macro after its declarations are complete.
1993 SHDR_GL_PROC(void, GenBuffers, (GLsizei, GLuint*)) // Declare a function to allocate names for GL storage buffers.
1994 SHDR_GL_PROC(void, DeleteBuffers, (GLsizei, const GLuint*)) // Declare a function to release owned GL buffer names.
1995 SHDR_GL_PROC(void, BindBuffer, (GLenum, GLuint)) // Declare a function to select a buffer for allocation or transfer.
1996 SHDR_GL_PROC(void, BufferData, (GLenum, GLsizeiptr, const void*, GLenum)) // Declare a function to allocate buffer storage and supply its initial host values.
1997 SHDR_GL_PROC(void, BufferSubData, (GLenum, GLintptr, GLsizeiptr, const void*)) // Declare a function to upload the current host buffer values.
1998 SHDR_GL_PROC(void, BindBufferBase, (GLenum, GLuint, GLuint)) // Declare a function to bind storage to the shader interface index.
1999 SHDR_GL_PROC(void*, MapBufferRange, (GLenum, GLintptr, GLsizeiptr, GLbitfield)) // Declare a function to map completed GPU buffer values for a host readback.
2000 SHDR_GL_PROC(GLboolean, UnmapBuffer, (GLenum)) // Declare a function to finish reading the mapped GPU buffer.
2001 SHDR_GL_PROC(void, DispatchCompute, (GLuint, GLuint, GLuint)) // Declare a function to queue the shader workgroups.
2002 SHDR_GL_PROC(void, MemoryBarrier, (GLbitfield)) // Declare a function to make earlier resource writes visible to following GPU commands.
2003 SHDR_GL_PROC(void, Finish, ()) // Declare a function to explicitly wait until queued GPU commands complete.
2004 SHDR_GL_PROC(GLsync, FenceSync, (GLenum, GLbitfield)) // Declare a function to insert a completion fence after queued compute work.
2005 SHDR_GL_PROC(GLenum, ClientWaitSync, (GLsync, GLbitfield, GLuint64)) // Declare a function to check a GPU fence with the caller-selected timeout.
2006 SHDR_GL_PROC(void, DeleteSync, (GLsync)) // Declare the GL completion-fence deletion entry point.
2007 SHDR_GL_PROC(void, Flush, ()) // Declare the GL command-flush entry point.
2008 SHDR_GL_PROC(void, GenTextures, (GLsizei, GLuint*)) // Declare a function to allocate names for owned GL images.
2009 SHDR_GL_PROC(void, DeleteTextures, (GLsizei, const GLuint*)) // Declare a function to release owned GL image names.
2010 SHDR_GL_PROC(void, BindTexture, (GLenum, GLuint)) // Declare a function to select the image for allocation or upload.
2011 SHDR_GL_PROC(void, TexStorage2D, (GLenum, GLsizei, GLenum, GLsizei, GLsizei)) // Declare a function to allocate immutable two-dimensional image storage.
2012 SHDR_GL_PROC(void, // Declare the next dynamically resolved GL function signature.
2013 TexSubImage2D, // Name the function that uploads pixels into an existing texture.
2014 (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void*)) // Match the argument order required by this GL entry point.
2015 SHDR_GL_PROC(void, BindImageTexture, (GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum)) // Declare a function to bind a typed image to its shader interface index.
2016 SHDR_GL_PROC(void, PixelStorei, (GLenum, GLint)) // Declare a function to set or restore the application pixel-transfer layout.
2017#undef SHDR_GL_PROC // Remove this temporary macro after its declarations are complete.
2018 explicit gl_api(const std::function<void*(const char*)>& resolver) { // Resolve the GL calls used by resource transfers and dispatches.
2019#define SHDR_LOAD(n) /* Resolve one GL entry point and reject missing functions. */ \
2020 { /* Begin the protected scope for this operation. */ \
2021 void* p = resolver("gl" #n); /* Resolve the address of this named GL entry point. */ \
2022 if (!p) /* Reject a missing dynamically resolved GL function. */ \
2023 throw error("missing GL entry point: gl" #n); /* Report missing gl entry point: gl. */ \
2024 static_assert(sizeof(p) == sizeof(n), "function pointer size unsupported"); /* Require a representation that matches the shader interface. */ \
2025 std::memcpy(&n, &p, sizeof(n)); /* Copy the representation with the alias-safe byte-copy operation. */ \
2026 } /* End this scope in gl api. */
2027 SHDR_LOAD(GetString) // Load the function to read the driver version or renderer text.
2028 SHDR_LOAD(GetIntegerv) // Load the function to read a scalar device limit or current binding.
2029 SHDR_LOAD(GetIntegeri_v) // Load the function to read the limit for a selected compute axis.
2030 SHDR_LOAD(GetError) // Load the function to read the pending GL error code.
2031 SHDR_LOAD(CreateShader) // Load the function to allocate a compute shader object.
2032 SHDR_LOAD(ShaderSource) // Load the function to supply the embedded shader text to the driver.
2033 SHDR_LOAD(CompileShader) // Load the function to ask the driver to compile the compute shader.
2034 SHDR_LOAD(GetShaderiv) // Load the function to read shader compilation status or log length.
2035 SHDR_LOAD(GetShaderInfoLog) // Load the function to read the driver explanation of a shader compilation failure.
2036 SHDR_LOAD(DeleteShader) // Load the function to release the temporary shader object.
2037 SHDR_LOAD(CreateProgram) // Load the function to allocate the linked compute program.
2038 SHDR_LOAD(AttachShader) // Load the function to attach the compute shader before linking.
2039 SHDR_LOAD(LinkProgram) // Load the function to link the compiled compute program.
2040 SHDR_LOAD(GetProgramiv) // Load the function to read linked-program status, log length, or local dimensions.
2041 SHDR_LOAD(GetProgramInfoLog) // Load the function to read the driver explanation of a program-link failure.
2042 SHDR_LOAD(DeleteProgram) // Load the function to release the GL program after its owners finish using it.
2043 SHDR_LOAD(UseProgram) // Load the function to select the compute program for the next dispatch.
2044 SHDR_LOAD(GetUniformLocation) // Load the function to find a named uniform in the linked program.
2045 SHDR_LOAD(Uniform1f) // Load the function to assign a float uniform.
2046 SHDR_LOAD(Uniform1i) // Load the function to assign an integer or boolean uniform.
2047 SHDR_LOAD(Uniform1ui) // Load the function to assign an unsigned integer uniform.
2048#define SHDR_LOAD_UNIFORM(n) /* Load the float, signed and unsigned uniform functions for this vector width. */ \
2049 SHDR_LOAD(Uniform##n##fv) /* Load the function to send this typed uniform to GL. */ \
2050 SHDR_LOAD(Uniform##n##iv) /* Load the function to send this typed uniform to GL. */ \
2051 SHDR_LOAD(Uniform##n##uiv) /* Load the function to send this typed uniform to GL. */
2052 SHDR_LOAD_UNIFORM(2) // Load the float, signed and unsigned uniform functions for this vector width.
2053 SHDR_LOAD_UNIFORM(3) // Load the float, signed and unsigned uniform functions for this vector width.
2054 SHDR_LOAD_UNIFORM(4) // Load the float, signed and unsigned uniform functions for this vector width.
2055#undef SHDR_LOAD_UNIFORM // Remove this temporary macro after its declarations are complete.
2056 SHDR_LOAD(UniformMatrix2fv) // Load the function to send this typed uniform to GL.
2057 SHDR_LOAD(UniformMatrix3fv) // Load the function to send this typed uniform to GL.
2058 SHDR_LOAD(UniformMatrix4fv) // Load the function to send this typed uniform to GL.
2059 SHDR_LOAD(UniformMatrix2x3fv) // Load the function to send this typed uniform to GL.
2060 SHDR_LOAD(UniformMatrix2x4fv) // Load the function to send this typed uniform to GL.
2061 SHDR_LOAD(UniformMatrix3x2fv) // Load the function to send this typed uniform to GL.
2062 SHDR_LOAD(UniformMatrix3x4fv) // Load the function to send this typed uniform to GL.
2063 SHDR_LOAD(UniformMatrix4x2fv) // Load the function to send this typed uniform to GL.
2064 SHDR_LOAD(UniformMatrix4x3fv) // Load the function to send this typed uniform to GL.
2065 SHDR_LOAD(GenBuffers) // Load the function to allocate names for GL storage buffers.
2066 SHDR_LOAD(DeleteBuffers) // Load the function to release owned GL buffer names.
2067 SHDR_LOAD(BindBuffer) // Load the function to select a buffer for allocation or transfer.
2068 SHDR_LOAD(BufferData) // Load the function to allocate buffer storage and supply its initial host values.
2069 SHDR_LOAD(BufferSubData) // Load the function to upload the current host buffer values.
2070 SHDR_LOAD(BindBufferBase) // Load the function to bind storage to the shader interface index.
2071 SHDR_LOAD(MapBufferRange) // Load the function to map completed GPU buffer values for a host readback.
2072 SHDR_LOAD(UnmapBuffer) // Load the function to finish reading the mapped GPU buffer.
2073 SHDR_LOAD(DispatchCompute) // Load the function to queue the shader workgroups.
2074 SHDR_LOAD(MemoryBarrier) // Load the function to make earlier resource writes visible to following GPU commands.
2075 SHDR_LOAD(Finish) // Load the function to explicitly wait until queued GPU commands complete.
2076 SHDR_LOAD(GenTextures) // Load the function to allocate names for owned GL images.
2077 SHDR_LOAD(DeleteTextures) // Load the function to release owned GL image names.
2078 SHDR_LOAD(FenceSync) // Load the function to insert a completion fence after queued compute work.
2079 SHDR_LOAD(ClientWaitSync) // Load the function to check a GPU fence with the caller-selected timeout.
2080 SHDR_LOAD(DeleteSync) // Resolve the GL completion-fence deletion entry point.
2081 SHDR_LOAD(Flush) // Resolve the GL command-flush entry point.
2082 SHDR_LOAD(BindTexture) // Load the function to select the image for allocation or upload.
2083 SHDR_LOAD(TexStorage2D) // Load the function to allocate immutable two-dimensional image storage.
2084 SHDR_LOAD(TexSubImage2D) // Load the function to upload the current host pixel values.
2085 SHDR_LOAD(BindImageTexture) // Load the function to bind a typed image to its shader interface index.
2086 SHDR_LOAD(PixelStorei) // Load the function to set or restore the application pixel-transfer layout.
2087#undef SHDR_LOAD // Remove this temporary macro after its declarations are complete.
2088 } // End this scope in gl api.
2089 void check(const std::string& operation) const { // Check for a driver error from the preceding GL operation.
2090 const unsigned code = GetError(); // Read the pending GL error code.
2091 if (code) { // Choose this branch when code.
2092 std::ostringstream s; // Build a readable diagnostic containing the operation and GL error.
2093 s << operation << ": GL error 0x" << std::hex << code; // Combine the operation name and hexadecimal driver error.
2094 throw error(s.str()); // Report the invalid operation.
2095 } // End this scope in runtime.
2096 } // End this scope in runtime.
2097}; // End this scope in runtime.
2098#undef SHDR_GL_CALL // Remove this temporary macro after its declarations are complete.
2099
2100struct device_state { // Retain GL functions, context ownership, limits, and pending cleanup.
2101 gl_api gl; // Keep the retained GL function table.
2102 profile language; // Keep the selected shader profile.
2103 unsigned max_groups[3], max_local[3], max_invocations, max_buffers, max_images; // Keep work group dimensions, invocation and resource binding limits.
2104 std::shared_ptr<void> context_keepalive; // Keep the retained headless context.
2105 std::function<void()> activate_context; // Keep the callback that makes this device context current.
2106 std::thread::id context_thread; // Keep the thread allowed to issue GL commands.
2107 std::mutex retirement_mutex; // Keep the lock for deferred resource cleanup.
2108 std::vector<std::function<void(gl_api&)>> retirements; // Keep GL deletions requested by another thread.
2109 struct deferred { // Keep the deferred values and operations together.
2110 std::function<bool(gl_api&)> poll; // Keep the zero-time completion callback.
2111 std::function<void(gl_api&)> cancel; // Keep the fence-deletion callback used at shutdown.
2112 }; // End this scope in runtime.
2113 std::vector<deferred> pending_work; // Keep discarded submissions awaiting completion.
2114 bool retirements_closed; // Keep whether device teardown has stopped retaining submissions.
2115 device_state(const std::function<void*(const char*)>& resolver, profile p) // Load GL entry points and validate the selected compute profile.
2116 : gl(resolver), language(p), context_thread(std::this_thread::get_id()), // Resolve GL functions and record this context's profile and owning thread.
2117 retirements_closed(false) { // Allow pending completion leases until the public device is destroyed.
2118 const unsigned char* version = gl.GetString(VERSION); // Read the current context version before checking the requested profile.
2119 if (!version) // Require a version string from the current context.
2120 throw error("device requires a current GL context"); // Report device requires a current gl context.
2121 const bool es = std::string(reinterpret_cast<const char*>(version)).find("OpenGL ES") != // Set whether the current context uses OpenGL ES.
2122 std::string::npos; // Detect the GLES marker anywhere in the driver version string.
2123 const bool requested_es = p == profile::es31 || p == profile::es32; // Set whether the requested profile uses GLES.
2124 if (es != requested_es) // Choose this branch when es differs from requested es.
2125 throw error("shader profile does not match current GL/ES context"); // Report a mismatch between the selected profile and the current context.
2126 GLint major = 0, minor = 0; // Prepare both parts of the current GL version query.
2127 gl.GetIntegerv(MAJOR_VERSION, &major); // Read a scalar device limit or current binding.
2128 gl.GetIntegerv(MINOR_VERSION, &minor); // Read a scalar device limit or current binding.
2129 const int required_major = es ? 3 : 4; // Set the minimum GL major version for this profile.
2130 const int required_minor = p == profile::es31 ? 1 // Set the minimum GL minor version for this profile.
2131 : p == profile::es32 ? 2 // Select the version associated with this shader profile.
2132 : p == profile::gl43 ? 3 // Select the version associated with this shader profile.
2133 : p == profile::gl45 ? 5 // Select the version associated with this shader profile.
2134 : 6; // Select minor version six for the desktop GL 4.6 profile.
2135 if (major < required_major || (major == required_major && minor < required_minor)) // Choose this branch when major < required major or (major equals required major and minor < required minor).
2136 throw error("current context is older than requested compute profile"); // Report current context is older than requested compute profile.
2137 for (unsigned i = 0; i < 3; ++i) { // Validate or query each of the three compute dimensions.
2138 GLint n = 0; // Set the queried GL limit or element count.
2139 gl.GetIntegeri_v(MAX_COMPUTE_WORK_GROUP_COUNT, i, &n); // Read the limit for a selected compute axis.
2140 max_groups[i] = static_cast<unsigned>(n); // Set the device workgroup-count limits.
2141 gl.GetIntegeri_v(MAX_COMPUTE_WORK_GROUP_SIZE, i, &n); // Read the limit for a selected compute axis.
2142 max_local[i] = static_cast<unsigned>(n); // Set the device local-size limits.
2143 } // End this scope in device state.
2144 GLint n = 0; // Set the queried GL limit or element count.
2145 gl.GetIntegerv(MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &n); // Read a scalar device limit or current binding.
2146 max_invocations = static_cast<unsigned>(n); // Set the maximum invocations in one workgroup.
2147 gl.GetIntegerv(MAX_SHADER_STORAGE_BUFFER_BINDINGS, &n); // Read a scalar device limit or current binding.
2148 max_buffers = static_cast<unsigned>(n); // Set the storage-buffer binding limit.
2149 gl.GetIntegerv(MAX_IMAGE_UNITS, &n); // Read a scalar device limit or current binding.
2150 max_images = static_cast<unsigned>(n); // Set the image binding limit.
2151 gl.check("query compute capabilities"); // Check for a driver error from the preceding GL operation.
2152 } // End this scope in device state.
2153 void require_thread() { // Require the device context thread and activate its headless context.
2154 if (std::this_thread::get_id() != context_thread) // Check that the operation uses the context or lifecycle thread.
2155 throw error("GL operations require the device's context thread"); // Report gl operations require the device's context thread.
2156 if (activate_context) // Choose this branch when activate context.
2157 activate_context(); // Keep the callback that makes this device context current.
2158 } // End this scope in require thread.
2159 void collect() { // Run queued deletions and zero-time completion checks.
2160 require_thread(); // Require the device context thread and activate its headless context.
2161 std::vector<std::function<void(gl_api&)>> pending; // Keep the queued work or cleanup callbacks awaiting processing.
2162 std::vector<deferred> polls, unfinished; // Keep completion polls that must be checked again.
2163 { // Begin the protected scope for this operation.
2164 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2165 pending.swap(retirements); // Take the shared entries into a local collection for unlocked processing.
2166 polls.swap(pending_work); // Take the shared entries into a local collection for unlocked processing.
2167 } // End this scope in collect.
2168 for (std::size_t i = 0; i < pending.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2169 pending[i](gl); // Keep the retained GL function table.
2170 for (std::size_t i = 0; i < polls.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2171 if (!polls[i].poll(gl)) // Retain a completion callback while its work is pending.
2172 unfinished.push_back(std::move(polls[i])); // Retain this entry in the ordered resource or work collection.
2173 if (!unfinished.empty()) { // Keep the remaining callbacks for the next collection pass.
2174 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2175 pending_work.insert(pending_work.end(), // Retain this entry in the ordered resource or work collection.
2176 std::make_move_iterator(unfinished.begin()), // Supply the next value for the current call or declaration.
2177 std::make_move_iterator(unfinished.end())); // Keep the end of the current range.
2178 } // End this scope in collect.
2179 } // End this scope in collect.
2180 void defer_poll(const std::function<bool(gl_api&)>& poll, // Retain a completion check until its fence signals.
2181 const std::function<void(gl_api&)>& cancel = std::function<void(gl_api&)>()) { // Set the fence-deletion callback used at shutdown.
2182 { // Begin the protected scope for this operation.
2183 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2184 if (!retirements_closed) { // Check whether teardown still allows retained completion callbacks.
2185 pending_work.push_back(deferred{poll, cancel}); // Retain this entry in the ordered resource or work collection.
2186 return; // Finish this operation.
2187 } // End this scope in defer poll.
2188 } // End this scope in defer poll.
2189 // Handles may outlive the public device wrapper. After wrapper teardown,
2190 // schedule their fence deletion directly on the context thread.
2191 if (cancel) // Choose this branch when cancel.
2192 retire(cancel); // Delete on the context thread or defer deletion to that thread.
2193 } // End this scope in defer poll.
2194 void close_retirements() { // Stop retaining new submission bundles during device teardown.
2195 { // Begin the protected scope for this operation.
2196 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2197 retirements_closed = true; // Set whether device teardown has stopped retaining submissions.
2198 } // End this scope in close retirements.
2199 cancel_pending(); // Schedule deferred-fence deletion on the context thread.
2200 } // End this scope in close retirements.
2201 void cancel_pending() { // Schedule deferred-fence deletion on the context thread.
2202 require_thread(); // Require the device context thread and activate its headless context.
2203 std::vector<deferred> pending; // Keep the queued work or cleanup callbacks awaiting processing.
2204 { // Begin the protected scope for this operation.
2205 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2206 pending.swap(pending_work); // Take the shared entries into a local collection for unlocked processing.
2207 } // End this scope in cancel pending.
2208 for (std::size_t i = 0; i < pending.size(); ++i) // Process the cleanup or completion callbacks taken from the queue.
2209 if (pending[i].cancel) // Check the queue state before accepting or executing work.
2210 pending[i].cancel(gl); // Keep the retained GL function table.
2211 pending.clear(); // Release the retained entries after their work or cleanup is complete.
2212 collect(); // Run queued deletions and zero-time completion checks.
2213 } // End this scope in cancel pending.
2214 void retire(const std::function<void(gl_api&)>& deletion) { // Delete on the context thread or defer deletion to that thread.
2215 if (std::this_thread::get_id() == context_thread) { // Check that the operation uses the context or lifecycle thread.
2216 require_thread(); // Require the device context thread and activate its headless context.
2217 deletion(gl); // Keep the retained GL function table.
2218 } else { // Handle the alternative resource or completion case.
2219 std::lock_guard<std::mutex> lock(retirement_mutex); // Hold the mutex while this shared state is accessed.
2220 retirements.push_back(deletion); // Retain this entry in the ordered resource or work collection.
2221 } // End this scope in retire.
2222 } // End this scope in retire.
2223 ~device_state() noexcept { // Close pending retirement leases on the context thread.
2224 if (std::this_thread::get_id() == context_thread) { // Check that the operation uses the context or lifecycle thread.
2225 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2226 close_retirements(); // Stop retaining new submission bundles during device teardown.
2227 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2228 } // End this scope in device state.
2229 } // End this scope in device state.
2230 } // End this scope in device state.
2231 GLuint compile(const std::string& source, const std::string& name) { // Compile and link the embedded compute source with driver diagnostics.
2232 if (source.size() > static_cast<std::size_t>((std::numeric_limits<GLint>::max)())) // Check resource size or driver limits before accessing storage.
2233 throw error("shader source too large"); // Report shader source too large.
2234 GLuint shader = gl.CreateShader(COMPUTE_SHADER), program = 0; // Allocate a compute shader object.
2235 if (!shader) // Check that the driver allocated a shader object.
2236 throw error("cannot create compute shader"); // Report compute-shader allocation failure.
2237 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2238 const char* text = source.c_str(); // Give GL a pointer to the retained shader characters.
2239 GLint len = static_cast<GLint>(source.size()); // Pass the validated shader character count to GL.
2240 gl.ShaderSource(shader, 1, &text, &len); // Supply the embedded shader text to the driver.
2241 gl.CompileShader(shader); // Ask the driver to compile the compute shader.
2242 GLint success = 0; // Prepare the compile or link status returned by GL.
2243 gl.GetShaderiv(shader, COMPILE_STATUS, &success); // Read shader compilation status or log length.
2244 if (!success) { // Read the driver diagnostic for this failed operation.
2245 GLint size = 0; // Prepare the driver diagnostic log length.
2246 gl.GetShaderiv(shader, INFO_LOG_LENGTH, &size); // Read shader compilation status or log length.
2247 std::vector<char> log(static_cast<std::size_t>((std::max)(size, 1)), 0); // Allocate enough characters for the driver diagnostic and terminator.
2248 gl.GetShaderInfoLog(shader, size, 0, log.data()); // Read the driver explanation of a shader compilation failure.
2249 throw error(name + ": shader compilation failed\n" + log.data()); // Report : shader compilation failed\n.
2250 } // End this scope in compile.
2251 program = gl.CreateProgram(); // Allocate the linked compute program.
2252 if (!program) // Check that the driver allocated a program object.
2253 throw error("cannot create compute program"); // Report compute-program allocation failure.
2254 gl.AttachShader(program, shader); // Attach the compute shader before linking.
2255 gl.LinkProgram(program); // Link the compiled compute program.
2256 gl.GetProgramiv(program, LINK_STATUS, &success); // Read linked-program status, log length, or local dimensions.
2257 if (!success) { // Read the driver diagnostic for this failed operation.
2258 GLint size = 0; // Prepare the driver diagnostic log length.
2259 gl.GetProgramiv(program, INFO_LOG_LENGTH, &size); // Read linked-program status, log length, or local dimensions.
2260 std::vector<char> log(static_cast<std::size_t>((std::max)(size, 1)), 0); // Allocate enough characters for the driver diagnostic and terminator.
2261 gl.GetProgramInfoLog(program, size, 0, log.data()); // Read the driver explanation of a program-link failure.
2262 throw error(name + ": program link failed\n" + log.data()); // Report : program link failed\n.
2263 } // End this scope in compile.
2264 gl.DeleteShader(shader); // Release the temporary shader object.
2265 shader = 0; // Set the shader used by this dispatch.
2266 gl.check("link " + name); // Keep the resource or entry-point name.
2267 return program; // Compile and link the embedded compute source with driver diagnostics.
2268 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2269 if (shader) // Choose this branch when shader.
2270 gl.DeleteShader(shader); // Release the temporary shader object.
2271 if (program) // Choose this branch when program.
2272 gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2273 throw; // Rethrow the original failure after arranging the necessary cleanup.
2274 } // End this scope in compile.
2275 } // End this scope in compile.
2276}; // End this scope in runtime.
2277struct program_state { // Keep the program state values and operations together.
2278 std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
2279 GLuint id; // Keep the compiled GL program name.
2280 program_state(const std::shared_ptr<device_state>& d, GLuint id_) : owner(d), id(id_) { // Expose the retained compiled program for asynchronous ownership.
2281 } // End this scope in program state.
2282 ~program_state() { // Release this object's owned resources at teardown.
2283 if (id) { // Choose this branch when id.
2284 const GLuint name = id; // Set the resource or entry-point name.
2285 owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2286 gl.DeleteProgram(name); // Release the GL program after its owners finish using it.
2287 }); // End this scope in program state.
2288 } // End this scope in program state.
2289 } // End this scope in program state.
2290}; // End this scope in runtime.
2291
2292inline std::size_t checked_product(std::size_t a, std::size_t b) { // Reject resource-size multiplication that would overflow.
2293 if (b && a > (std::numeric_limits<std::size_t>::max)() / b) // Check resource size or driver limits before accessing storage.
2294 throw error("resource size overflow"); // Report resource size overflow.
2295 return a * b; // Reject resource-size multiplication that would overflow.
2296} // End this scope in checked product.
2297inline GLsizeiptr gl_size(std::size_t size) { // Require a byte count representable by the GL buffer API.
2298 if (size > static_cast<std::size_t>((std::numeric_limits<GLsizeiptr>::max)())) // Check resource size or driver limits before accessing storage.
2299 throw error("resource exceeds GLsizeiptr"); // Report resource exceeds glsizeiptr.
2300 return static_cast<GLsizeiptr>(size); // Require a byte count representable by the GL buffer API.
2301} // End this scope in gl size.
2302enum class authority { host, gpu, both }; // Name the profile, access, or completion values accepted by this section.
2303enum class resource_kind { buffer, image }; // Name the profile, access, or completion values accepted by this section.
2304struct resource_state { // Track shared storage and which backend has the newest values.
2305 resource_kind kind; // Keep the buffer, image, or uniform interface kind.
2306 authority latest; // Keep which copy contains the latest resource values.
2307 std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
2308 GLuint handle; // Keep the GL buffer or texture name.
2309 bool borrowed; // Keep whether the application owns the supplied GL object.
2310 unsigned width, height, components, format, scalar; // Keep the GL scalar representation.
2311 resource_state(resource_kind k) // Initialize ownership and synchronization for one resource.
2312 : kind(k), latest(authority::host), handle(0), borrowed(false), width(0), height(0), // Start with authoritative host data and allocate GL storage on demand.
2313 components(0), format(0), scalar(0) { // Initialize image layout metadata to zero.
2314 } // End this scope in resource state.
2315 virtual ~resource_state() { // Release this object's owned resources at teardown.
2316 if (handle && !borrowed) { // Delete the resource when its GL handle is owned by this object.
2317 const GLuint name = handle; // Set the resource or entry-point name.
2318 if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2319 owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2320 gl.DeleteBuffers(1, &name); // Release owned GL buffer names.
2321 }); // End this scope in resource state.
2322 else // Handle the other resource, platform, or completion case.
2323 owner->retire([name](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
2324 gl.DeleteTextures(1, &name); // Release owned GL image names.
2325 }); // End this scope in resource state.
2326 } // End this scope in resource state.
2327 } // End this scope in resource state.
2328 virtual void* host_pointer() = 0; // Require each resource type to expose its host storage.
2329 virtual std::size_t bytes() const = 0; // Require each resource type to report its byte count.
2330 void ensure_host(); // Download newer GPU values only when host access needs them.
2331 void ensure_gpu(const std::shared_ptr<device_state>& d) { // Allocate or upload GPU storage when its host copy is newer.
2332 d->collect(); // Run queued deletions and zero-time completion checks.
2333 if (owner && owner != d) // Check that this storage belongs to the requested device.
2334 throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2335 owner = d; // Set the device that owns the GL resource.
2336 const gl_api& gl = d->gl; // Set the retained GL function table.
2337 if (!handle) { // Allocate GPU storage on the first device access.
2338 if (kind == resource_kind::buffer) { // Choose the branch matching this interface or resource access.
2339 gl.GenBuffers(1, &handle); // Allocate names for GL storage buffers.
2340 gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2341 gl.BufferData(SHADER_STORAGE_BUFFER, // Allocate buffer storage and supply its initial host values.
2342 gl_size(bytes()), // Require a byte count representable by the GL buffer API.
2343 bytes() ? host_pointer() : 0, // Supply the next value for the current call or declaration.
2344 DYNAMIC_DRAW); // Require a byte count representable by the GL buffer API.
2345 } else { // Handle the alternative resource or completion case.
2346 gl.GenTextures(1, &handle); // Allocate names for owned GL images.
2347 gl.BindTexture(TEXTURE_2D, handle); // Select the image for allocation or upload.
2348 gl.TexStorage2D(TEXTURE_2D, // Allocate immutable two-dimensional image storage.
2349 1, // Supply the next value for the current call or declaration.
2350 format, // Visit the values or interfaces needed by ensure gpu.
2351 static_cast<GLsizei>(width), // Keep the image width in pixels.
2352 static_cast<GLsizei>(height)); // Keep the image height in pixels.
2353 } // End this scope in ensure gpu.
2354 gl.check("allocate compute resource"); // Check for a driver error from the preceding GL operation.
2355 if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2356 latest = authority::both; // Record which backend now owns the newest resource values.
2357 } // End this scope in ensure gpu.
2358 if (latest == authority::host) { // Check which resource copy must be synchronized.
2359 if (kind == resource_kind::buffer) { // Choose the branch matching this interface or resource access.
2360 gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2361 if (bytes()) // Check resource size or driver limits before accessing storage.
2362 gl.BufferSubData(SHADER_STORAGE_BUFFER, 0, gl_size(bytes()), host_pointer()); // Upload the current host buffer values.
2363 } else { // Handle the alternative resource or completion case.
2364 // Make upload independent of caller pixel unpack state and restore that state.
2365 GLint alignment = 0, row = 0, skip_rows = 0, skip_pixels = 0, pbo = 0; // Save the complete pixel-unpack layout and bound transfer buffer.
2366 gl.GetIntegerv(UNPACK_ALIGNMENT, &alignment); // Read a scalar device limit or current binding.
2367 gl.GetIntegerv(UNPACK_ROW_LENGTH, &row); // Read a scalar device limit or current binding.
2368 gl.GetIntegerv(UNPACK_SKIP_ROWS, &skip_rows); // Read a scalar device limit or current binding.
2369 gl.GetIntegerv(UNPACK_SKIP_PIXELS, &skip_pixels); // Read a scalar device limit or current binding.
2370 gl.GetIntegerv(0x88EF, &pbo); // GL_PIXEL_UNPACK_BUFFER_BINDING
2371 gl.BindBuffer(PIXEL_UNPACK_BUFFER, 0); // Select a buffer for allocation or transfer.
2372 gl.PixelStorei(UNPACK_ALIGNMENT, 1); // Set or restore the application pixel-transfer layout.
2373 gl.PixelStorei(UNPACK_ROW_LENGTH, 0); // Set or restore the application pixel-transfer layout.
2374 gl.PixelStorei(UNPACK_SKIP_ROWS, 0); // Set or restore the application pixel-transfer layout.
2375 gl.PixelStorei(UNPACK_SKIP_PIXELS, 0); // Set or restore the application pixel-transfer layout.
2376 gl.BindTexture(TEXTURE_2D, handle); // Select the image for allocation or upload.
2377 const GLenum channels = scalar == FLOAT // Choose the float or integer pixel-transfer channel representation.
2378 ? (components == 1 ? RED : RGBA) // Set the number of scalar values per pixel.
2379 : (components == 1 ? RED_INTEGER : RGBA_INTEGER); // Choose the upload pixel format matching integer channels.
2380 gl.TexSubImage2D(TEXTURE_2D, // Upload the current host pixel values.
2381 0, // Supply the next value for the current call or declaration.
2382 0, // Supply the next value for the current call or declaration.
2383 0, // Supply the next value for the current call or declaration.
2384 static_cast<GLsizei>(width), // Keep the image width in pixels.
2385 static_cast<GLsizei>(height), // Keep the image height in pixels.
2386 channels, // Supply the next value for the current call or declaration.
2387 scalar, // Keep the GL scalar representation.
2388 host_pointer()); // Expose this resource's borrowed or owned host storage.
2389 gl.PixelStorei(UNPACK_ALIGNMENT, alignment); // Set or restore the application pixel-transfer layout.
2390 gl.PixelStorei(UNPACK_ROW_LENGTH, row); // Set or restore the application pixel-transfer layout.
2391 gl.PixelStorei(UNPACK_SKIP_ROWS, skip_rows); // Set or restore the application pixel-transfer layout.
2392 gl.PixelStorei(UNPACK_SKIP_PIXELS, skip_pixels); // Set or restore the application pixel-transfer layout.
2393 gl.BindBuffer(PIXEL_UNPACK_BUFFER, static_cast<GLuint>(pbo)); // Select a buffer for allocation or transfer.
2394 } // End this scope in ensure gpu.
2395 gl.check("upload compute resource"); // Check for a driver error from the preceding GL operation.
2396 latest = authority::both; // Record which backend now owns the newest resource values.
2397 } // End this scope in ensure gpu.
2398 } // End this scope in ensure gpu.
2399}; // End this scope in runtime.
2400
2401 // Image readback uses a compute copy on both desktop GL and GLES.
2402inline void resource_state::ensure_host() { // Download newer GPU values only when host access needs them.
2403 if (latest != authority::gpu) // Check which resource copy must be synchronized.
2404 return; // Finish this operation.
2405 owner->collect(); // Run queued deletions and zero-time completion checks.
2406 const gl_api& gl = owner->gl; // Set the retained GL function table.
2407 if (!bytes()) { // Check resource size or driver limits before accessing storage.
2408 latest = authority::both; // Record which backend now owns the newest resource values.
2409 return; // Finish this operation.
2410 } // End this scope in ensure host.
2411 GLuint staging = 0, program = 0; // Track the temporary readback buffer and copy program for cleanup.
2412 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2413 gl.MemoryBarrier(ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
2414 if (kind == resource_kind::buffer) // Choose the branch matching this interface or resource access.
2415 gl.BindBuffer(SHADER_STORAGE_BUFFER, handle); // Select a buffer for allocation or transfer.
2416 else { // Handle the other resource, platform, or completion case.
2417 const char* scalar_name = scalar == FLOAT ? "float" : scalar == INT ? "int" : "uint"; // Choose the GLSL scalar spelling matching these image pixels.
2418 const char* vector_name = scalar == FLOAT ? "vec4" : scalar == INT ? "ivec4" : "uvec4"; // Choose the four-component GLSL value used by imageLoad.
2419 const char* image_name = scalar == FLOAT ? "image2D" // Choose the matching float, signed or unsigned storage-image type.
2420 : scalar == INT ? "iimage2D" // Choose the shader image type matching the resource's scalar representation.
2421 : "uimage2D"; // Choose the shader image type matching the resource's scalar representation.
2422 const char* format_name = components == 1 ? (scalar == FLOAT ? "r32f" // Choose the declared storage-image format for the copy shader.
2423 : scalar == INT ? "r32i" // Choose the shader format matching scalar type and channel count.
2424 : "r32ui") // Choose the shader format matching scalar type and channel count.
2425 : (scalar == FLOAT ? "rgba32f" // Choose the shader format matching scalar type and channel count.
2426 : scalar == INT ? "rgba32i" // Choose the shader format matching scalar type and channel count.
2427 : "rgba32ui"); // Choose the shader format matching scalar type and channel count.
2428 std::ostringstream body; // Download newer GPU values only when host access needs them.
2429 body << "SHDR_BEGIN(shdr_readback,8,8,1)\nSHDR_IMAGE2D(0," << format_name << ',' // Download newer GPU values only when host access needs them.
2430 << image_name << ",src,readonly)\n" // Download newer GPU values only when host access needs them.
2431 << "SHDR_BUFFER(0," << scalar_name // Download newer GPU values only when host access needs them.
2432 << ",dst,writeonly)\nSHDR_MAIN(){uvec2 p=gl_GlobalInvocationID.xy;" // Download newer GPU values only when host access needs them.
2433 << "ivec2 s=imageSize(src);if(p.x>=uint(s.x)||p.y>=uint(s.y))return;" // Download newer GPU values only when host access needs them.
2434 << vector_name << " v=imageLoad(src,ivec2(p));uint i=(p.y*uint(s.x)+p.x)*" // Download newer GPU values only when host access needs them.
2435 << components << "u;"; // Download newer GPU values only when host access needs them.
2436 for (unsigned c = 0; c < components; ++c) // Visit the values or interfaces needed by ensure host.
2437 body << "dst[i+" << c << "u]=v[" << c << "];"; // Download newer GPU values only when host access needs them.
2438 body << "} SHDR_END()\n"; // Download newer GPU values only when host access needs them.
2439 program = owner->compile(glsl_source(body.str(), owner->language), "image readback"); // Compile the portable image-to-buffer readback shader.
2440 gl.GenBuffers(1, &staging); // Allocate names for GL storage buffers.
2441 gl.BindBuffer(SHADER_STORAGE_BUFFER, staging); // Select a buffer for allocation or transfer.
2442 gl.BufferData(SHADER_STORAGE_BUFFER, gl_size(bytes()), 0, DYNAMIC_DRAW); // Allocate buffer storage and supply its initial host values.
2443 gl.UseProgram(program); // Select the compute program for the next dispatch.
2444 gl.BindBufferBase(SHADER_STORAGE_BUFFER, 0, staging); // Bind storage to the shader interface index.
2445 gl.BindImageTexture(0, handle, 0, 0, 0, READ_ONLY, format); // Bind a typed image to its shader interface index.
2446 gl.DispatchCompute((width + 7) / 8, (height + 7) / 8, 1); // Queue the shader workgroups.
2447 gl.MemoryBarrier(ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
2448 gl.check("copy image to host staging buffer"); // Check for a driver error from the preceding GL operation.
2449 gl.BindBuffer(SHADER_STORAGE_BUFFER, staging); // Select a buffer for allocation or transfer.
2450 } // End this scope in ensure host.
2451 void* mapped = gl.MapBufferRange(SHADER_STORAGE_BUFFER, 0, gl_size(bytes()), MAP_READ_BIT); // Map completed GPU buffer values for a host readback.
2452 if (!mapped) { // Check that GL returned a readable mapped range.
2453 gl.check("map compute readback"); // Check for a driver error from the preceding GL operation.
2454 throw error("cannot map compute readback"); // Report readback mapping failure.
2455 } // End this scope in ensure host.
2456 std::memcpy(host_pointer(), mapped, bytes()); // Copy the representation with the alias-safe byte-copy operation.
2457 if (!gl.UnmapBuffer(SHADER_STORAGE_BUFFER)) // Finish reading the mapped GPU buffer.
2458 throw error("compute readback buffer contents corrupted"); // Report compute readback buffer contents corrupted.
2459 gl.check("read back compute resource"); // Check for a driver error from the preceding GL operation.
2460 latest = authority::both; // Record which backend now owns the newest resource values.
2461 if (staging) // Choose this branch when staging.
2462 gl.DeleteBuffers(1, &staging); // Release owned GL buffer names.
2463 if (program) // Choose this branch when program.
2464 gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2465 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2466 if (staging) // Choose this branch when staging.
2467 gl.DeleteBuffers(1, &staging); // Release owned GL buffer names.
2468 if (program) // Choose this branch when program.
2469 gl.DeleteProgram(program); // Release the GL program after its owners finish using it.
2470 throw; // Rethrow the original failure after arranging the necessary cleanup.
2471 } // End this scope in ensure host.
2472} // End this scope in ensure host.
2473
2474 // Only layouts identical to std430 arrays are accepted. vec3, bool and arbitrary structs need explicit packing.
2475template <class T> // Select the scalar, dimension, or access type at compile time.
2476struct storage_type // Keep the storage type values and operations together.
2477 : std::integral_constant<bool, // Expose the following storage-layout checks as a compile-time boolean.
2478 std::is_same<T, float>::value || std::is_same<T, int>::value || // Accept the supported 32-bit float and signed integer storage types.
2479 std::is_same<T, unsigned>::value> {}; // Also accept the supported 32-bit unsigned storage type.
2480template <class T, std::size_t N> // Select the scalar, dimension, or access type at compile time.
2481struct storage_type<glsl::vec<T, N>> // Keep the storage type values and operations together.
2482 : std::integral_constant<bool, // Expose the following storage-layout checks as a compile-time boolean.
2483 storage_type<T>::value && (N == 2 || N == 4) && // Require a supported scalar and a two- or four-component vector.
2484 sizeof(glsl::vec<T, N>) == sizeof(T) * N> {}; // Require a tightly packed vector that matches its std430 array stride.
2485template <class T> struct buffer_state : resource_state { // Select the scalar, dimension, or access type at compile time.
2486 std::vector<T> owned; // Keep host storage allocated by this resource.
2487 T* external; // Point to application-owned host memory.
2488 std::size_t count; // Keep the element or configuration count.
2489 explicit buffer_state(std::size_t n) // Allocate owned host storage for this number of elements.
2490 : resource_state(resource_kind::buffer), owned(n), external(0), count(n) { // Initialize ownership and synchronization for one resource.
2491 } // End this scope in runtime.
2492 buffer_state(T* p, std::size_t n) // Retain a reference to an application-owned host range.
2493 : resource_state(resource_kind::buffer), external(p), count(n) { // Initialize ownership and synchronization for one resource.
2494 if (!p && n) // Require a valid pointer for a nonempty borrowed range.
2495 throw error("null borrowed CPU buffer"); // Report null borrowed cpu buffer.
2496 } // End this scope in runtime.
2497 void* host_pointer() override { // Expose this resource's borrowed or owned host storage.
2498 return external ? external : owned.data(); // Use borrowed host memory when present and owned memory otherwise.
2499 } // End this scope in runtime.
2500 std::size_t bytes() const override { // Report this resource's byte count with overflow checking.
2501 return checked_product(count, sizeof(T)); // Calculate the byte count with checked size arithmetic.
2502 } // End this scope in runtime.
2503}; // End this scope in runtime.
2504template <class T> struct image_state : resource_state { // Select the scalar, dimension, or access type at compile time.
2505 std::vector<T> owned; // Keep host storage allocated by this resource.
2506 image_state(unsigned w, unsigned h, unsigned c) : resource_state(resource_kind::image) { // Initialize ownership and synchronization for one resource.
2507 if (!w || !h || w > static_cast<unsigned>((std::numeric_limits<GLsizei>::max)()) || // Check resource size or driver limits before accessing storage.
2508 h > static_cast<unsigned>((std::numeric_limits<GLsizei>::max)())) // Require the image height to fit the GL signed dimension type.
2509 throw error("image dimensions must be positive GLsizei values"); // Report image dimensions must be positive glsizei values.
2510 width = w; // Set the image width in pixels.
2511 height = h; // Set the image height in pixels.
2512 components = c; // Set the number of scalar values per pixel.
2513 scalar = std::is_same<T, float>::value ? FLOAT // Set the GL scalar representation.
2514 : std::is_same<T, int>::value ? INT // Choose the GL scalar type matching the host pixel representation.
2515 : UNSIGNED_INT; // Choose the GL scalar type matching the host pixel representation.
2516 format = c == 1 ? (scalar == FLOAT ? R32F // Visit the values or interfaces needed by runtime.
2517 : scalar == INT ? R32I // Choose the GL internal image format matching scalar type and channel count.
2518 : R32UI) // Choose the GL internal image format matching scalar type and channel count.
2519 : (scalar == FLOAT ? RGBA32F // Choose the GL internal image format matching scalar type and channel count.
2520 : scalar == INT ? RGBA32I // Choose the GL internal image format matching scalar type and channel count.
2521 : RGBA32UI); // Choose the GL internal image format matching scalar type and channel count.
2522 owned.resize(checked_product(checked_product(w, h), c)); // Reject resource-size multiplication that would overflow.
2523 } // End this scope in runtime.
2524 void* host_pointer() override { // Expose this resource's borrowed or owned host storage.
2525 return owned.data(); // Expose the contiguous host storage owned by this resource.
2526 } // End this scope in runtime.
2527 std::size_t bytes() const override { // Report this resource's byte count with overflow checking.
2528 return checked_product(owned.size(), sizeof(T)); // Calculate the byte count with checked size arithmetic.
2529 } // End this scope in runtime.
2530}; // End this scope in runtime.
2531} // namespace detail
2532
2533/** @brief An application's current GL context, accessed through its function resolver.
2534 * The context must remain current on this thread during operations and destruction of GL objects.
2535 * The default header uses standard C++11 declarations. The optional
2536 * headless_device supplies EGL context creation when SHDR_ENABLE_EGL is enabled.
2537 */
2538class device { // Keep the device values and operations together.
2539 std::shared_ptr<detail::device_state> state_; // Keep the state shared by this wrapper and its retained owners.
2540
2541 public: // Expose the operations callers can use.
2542 /** @brief Load GL entry points and validate the current context against a profile.
2543 * @param resolver Callable returning the address of a named GL function, or null.
2544 * @param p Minimum GLSL and GL/ES profile. defaults to ES 3.1.
2545 * @throws error If function resolution or current-context validation fails.
2546 */
2547 explicit device(const std::function<void*(const char*)>& resolver, profile p = profile::es31) // Create a compute device using the caller's current context and function resolver.
2548 : state_(std::make_shared<detail::device_state>(resolver, p)) { // Retain the resolved GL functions, profile and device limits.
2549 } // End this scope in device.
2550 /** @brief Release deferred completion handles through context-thread cleanup.
2551 * Destroy devices on their context thread after CPU workers have stopped.
2552 */
2553 virtual ~device() noexcept { // Close pending retirement leases on the context thread.
2554 if (std::this_thread::get_id() == state_->context_thread) { // Check that the operation uses the context or lifecycle thread.
2555 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
2556 state_->close_retirements(); // Stop retaining new submission bundles during device teardown.
2557 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
2558 } // End this scope in device.
2559 } // End this scope in device.
2560 } // End this scope in device.
2561 device(const device&) = delete; // Prevent copying this object and duplicating its retained identity.
2562 device& operator=(const device&) = delete; // Prevent copying this object and duplicating its retained identity.
2563 /** @brief Return the shader language profile selected for this device. */
2564 profile shader_profile() const { // Return the device profile used to generate shader source.
2565 return state_->language; // Return the device profile used to generate shader source.
2566 } // End this scope in shader profile.
2567 /** @brief Wait for submitted GPU work to complete, including for accurate wall-clock benchmarks. */
2568 void synchronize() { // Explicitly wait for completed GPU commands.
2569 state_->collect(); // Run queued deletions and zero-time completion checks.
2570 state_->gl.Finish(); // Explicitly wait until queued GPU commands complete.
2571 state_->gl.check("wait for GPU completion"); // Check for a driver error from the preceding GL operation.
2572 } // End this scope in synchronize.
2573 /** @brief Delete GL objects retired by CPU workers and poll pending completions. */
2574 void collect_garbage() { // Collect deferred GL deletions and poll completion fences.
2575 state_->collect(); // Run queued deletions and zero-time completion checks.
2576 } // End this scope in collect garbage.
2577 /** @brief Current GL renderer name, for diagnostics and reproducible benchmark reports. */
2578 std::string renderer() const { // Read the current renderer name for reproducible diagnostics.
2579 state_->require_thread(); // Require the device context thread and activate its headless context.
2580 const unsigned char* s = state_->gl.GetString(0x1F01); // Read the driver version or renderer text.
2581 if (!s) // Validate the renderer query from the current context.
2582 throw error("no current GL context"); // Report that the renderer query requires a current GL context.
2583 return reinterpret_cast<const char*>(s); // Read the current renderer name for reproducible diagnostics.
2584 } // End this scope in renderer.
2585 /** @internal Runtime access to the retained GL function table and device limits. */
2586 const std::shared_ptr<detail::device_state>& state() const { // Expose retained runtime state to the resource and backend helpers.
2587 return state_; // Return the storage or execution state retained by this wrapper.
2588 } // End this scope in state.
2589}; // End this scope in runtime.
2590
2591/** @brief Shared typed std430 storage, owned or borrowed, with automatic CPU/GPU synchronization.
2592 * Copying a buffer shares its storage. Mutable data() marks host data authoritative.
2593 * Obtain a fresh data() pointer after a GPU dispatch before accessing host values.
2594 * GPU handles belong to one device.
2595 */
2596template <class T> class buffer { // Select the scalar, dimension, or access type at compile time.
2597 static_assert(detail::storage_type<T>::value, // Require a representation that matches the shader interface.
2598 "buffer requires float/int/uint or matching vec2/vec4 std430 layout"); // Explain which element types match the supported storage-buffer layout.
2599 static_assert(sizeof(float) == 4 && sizeof(int) == 4 && sizeof(unsigned) == 4, // Require a representation that matches the shader interface.
2600 "shdr requires 32-bit GLSL scalars"); // Require the host scalar representation to match GLSL storage.
2601 std::shared_ptr<detail::buffer_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2602
2603 public: // Expose the operations callers can use.
2604 /** @brief Allocate a zero-initialized host buffer containing n elements.
2605 * GPU storage is allocated lazily. Zero-length buffers are valid on the CPU.
2606 * GPU storage-buffer bindings require at least one element.
2607 */
2608 explicit buffer(std::size_t n = 0) : state_(std::make_shared<detail::buffer_state<T>>(n)) { // Create a typed buffer with owned host storage.
2609 if (n > static_cast<std::size_t>((std::numeric_limits<unsigned>::max)())) // Check resource size or driver limits before accessing storage.
2610 throw error("buffer length exceeds GLSL uint"); // Report buffer length exceeds glsl uint.
2611 detail::gl_size(state_->bytes()); // Require a byte count representable by the GL buffer API.
2612 } // End this scope in buffer.
2613 /** @brief Borrow n elements stored in application-owned host memory.
2614 * Keep the memory alive while any resource copy or shader port retains it.
2615 * Call mark_host_modified() after writing through the original pointer.
2616 */
2617 buffer(T* p, std::size_t n) : state_(std::make_shared<detail::buffer_state<T>>(p, n)) { // Initialize the typed resource storage and validate its size.
2618 if (n > static_cast<std::size_t>((std::numeric_limits<unsigned>::max)())) // Check resource size or driver limits before accessing storage.
2619 throw error("buffer length exceeds GLSL uint"); // Report buffer length exceeds glsl uint.
2620 detail::gl_size(state_->bytes()); // Require a byte count representable by the GL buffer API.
2621 } // End this scope in buffer.
2622 /** @brief Allocate owned host storage and copy an initializer list into it. */
2623 buffer(std::initializer_list<T> values) : buffer(values.size()) { // Initialize the typed resource storage and validate its size.
2624 std::copy(values.begin(), values.end(), data()); // Access host values after bringing their resource copy up to date.
2625 } // End this scope in buffer.
2626 /** @brief Return the stored element count. */
2627 std::size_t size() const { // Read the stored element or stage count.
2628 return state_->count; // Return the result of this check or operation.
2629 } // End this scope in runtime.
2630 /** @brief Synchronize newer GPU contents and return mutable host elements.
2631 * Marks host data modified. Reacquire this pointer after GPU work before using it.
2632 */
2633 T* data() { // Access host values after bringing their resource copy up to date.
2634 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2635 state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2636 return static_cast<T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2637 } // End this scope in data.
2638 /** @brief Synchronize newer GPU contents and return readonly host elements. */
2639 const T* data() const { // Access host values after bringing their resource copy up to date.
2640 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2641 return static_cast<const T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2642 } // End this scope in data.
2643 /** @brief Access one host element after synchronization. reject an out-of-range index. */
2644 T& operator[](std::size_t i) { // Bounds-check this host element before returning its typed reference.
2645 if (i >= size()) // Check resource size or driver limits before accessing storage.
2646 throw error("host buffer index out of range"); // Report host buffer index out of range.
2647 return data()[i]; // Return the result of this check or operation.
2648 } // End this scope in runtime.
2649 /** @brief Read one host element after synchronization. reject an out-of-range index. */
2650 const T& operator[](std::size_t i) const { // Bounds-check this host element before returning its typed reference.
2651 if (i >= size()) // Check resource size or driver limits before accessing storage.
2652 throw error("host buffer index out of range"); // Report host buffer index out of range.
2653 return data()[i]; // Return the result of this check or operation.
2654 } // End this scope in runtime.
2655 /** @brief Ensure this device has the latest contents, allocating or uploading as needed. */
2656 void upload(device& d) { // Explicitly make current host values available to the GPU.
2657 state_->ensure_gpu(d.state()); // Allocate or upload GPU storage when its host copy is newer.
2658 } // End this scope in upload.
2659 /** @brief Download newer GPU contents. reject a different owning device. */
2660 void download(device& d) { // Explicitly bring newer GPU values back to host storage.
2661 if (state_->owner && state_->owner != d.state()) // Check that this storage belongs to the requested device.
2662 throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2663 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2664 } // End this scope in download.
2665 /** @brief Obtain the synchronized GL SSBO handle for application interop. */
2666 unsigned gl_handle(device& d) { // Expose a synchronized GL resource handle for interoperation.
2667 upload(d); // Explicitly make current host values available to the GPU.
2668 return state_->handle; // Expose a synchronized GL resource handle for interoperation.
2669 } // End this scope in gl handle.
2670 /** @brief Notify shdr after the application writes the GL buffer. its context must be current. */
2671 void mark_gpu_modified(device& d) { // Record a write performed by application GL commands.
2672 if (state_->owner != d.state() || !state_->handle) // Check that this storage belongs to the requested device.
2673 throw error("resource has no handle on this device"); // Report a mismatch between the resource handle and the device.
2674 state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2675 } // End this scope in mark gpu modified.
2676 /** @brief Notify shdr after changing previously obtained or borrowed host memory.
2677 * Call data() before editing if GPU data must first be preserved.
2678 */
2679 void mark_host_modified() { // Record a write through retained or borrowed host memory.
2680 state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2681 } // End this scope in mark host modified.
2682 /** @brief Borrow an existing SSBO. Its contents initially belong to the GPU. caller retains ownership. */
2683 static buffer from_gl(device& d, unsigned handle, std::size_t count) { // Borrow an application-owned GL object.
2684 if (!handle) // Validate the resource handle before using it.
2685 throw error("cannot borrow GL buffer zero"); // Require a nonzero GL buffer handle.
2686 buffer result(count); // Keep the element or configuration count.
2687 result.state_->owner = d.state(); // Set the device that owns the GL resource.
2688 result.state_->handle = handle; // Set the GL buffer or texture name.
2689 result.state_->borrowed = true; // Set whether the application owns the supplied GL object.
2690 result.state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2691 return result; // Return the value returned by this operation.
2692 } // End this scope in from gl.
2693 /** @internal Runtime access to shared resource storage and synchronization state. */
2694 const std::shared_ptr<detail::buffer_state<T>>& state() const { // Expose retained runtime state to the resource and backend helpers.
2695 return state_; // Return the storage or execution state retained by this wrapper.
2696 } // End this scope in state.
2697}; // End this scope in runtime.
2698
2699/** @brief Interleaved 32-bit scalar or RGBA image shared between CPU and GPU.
2700 * C is 1 or 4. T is float, int, or unsigned. Use matching r32f/r32i/r32ui or
2701 * rgba32f/rgba32i/rgba32ui GLSL declarations. Copies and bound ports alias storage.
2702 */
2703template <class T, unsigned C = 1> class image2d { // Select the scalar, dimension, or access type at compile time.
2704 static_assert(detail::storage_type<T>::value && std::is_arithmetic<T>::value, // Require a representation that matches the shader interface.
2705 "image requires float/int/uint"); // Require an image scalar type supported by the runtime.
2706 static_assert(C == 1 || C == 4, "portable image formats have one or four components"); // Require a representation that matches the shader interface.
2707 std::shared_ptr<detail::image_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2708
2709 public: // Expose the operations callers can use.
2710 /** @brief Allocate a zero-initialized image with positive width and height in pixels. */
2711 image2d(unsigned w, unsigned h) : state_(std::make_shared<detail::image_state<T>>(w, h, C)) { // Initialize the image geometry and typed pixel storage.
2712 } // End this scope in image2d.
2713 /** @brief Return the stored number of pixels in each row. */
2714 unsigned width() const { // Return the image width in pixels.
2715 return state_->width; // Return the result of this check or operation.
2716 } // End this scope in runtime.
2717 /** @brief Return the stored number of pixel rows. */
2718 unsigned height() const { // Return the image height in pixels.
2719 return state_->height; // Return the result of this check or operation.
2720 } // End this scope in runtime.
2721 /** @brief Synchronize newer GPU contents and return mutable interleaved host pixels.
2722 * Index component c at (x,y) as data()[(y*width()+x)*C+c]. Marks host data
2723 * modified. reacquire the pointer after GPU work before using it.
2724 */
2725 T* data() { // Access host values after bringing their resource copy up to date.
2726 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2727 state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2728 return static_cast<T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2729 } // End this scope in data.
2730 /** @brief Synchronize newer GPU contents and return readonly interleaved host pixels. */
2731 const T* data() const { // Access host values after bringing their resource copy up to date.
2732 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2733 return static_cast<const T*>(state_->host_pointer()); // Access host values after bringing their resource copy up to date.
2734 } // End this scope in data.
2735 /** @brief Ensure this device has the latest pixels, allocating or uploading as needed. */
2736 void upload(device& d) { // Explicitly make current host values available to the GPU.
2737 state_->ensure_gpu(d.state()); // Allocate or upload GPU storage when its host copy is newer.
2738 } // End this scope in upload.
2739 /** @brief Download newer GPU pixels through a portable compute-to-buffer copy. */
2740 void download(device& d) { // Explicitly bring newer GPU values back to host storage.
2741 if (state_->owner && state_->owner != d.state()) // Check that this storage belongs to the requested device.
2742 throw error("resource belongs to a different device"); // Report resource belongs to a different device.
2743 state_->ensure_host(); // Download newer GPU values only when host access needs them.
2744 } // End this scope in download.
2745 /** @brief Obtain the synchronized level-zero GL texture handle for application interop. */
2746 unsigned gl_handle(device& d) { // Expose a synchronized GL resource handle for interoperation.
2747 upload(d); // Explicitly make current host values available to the GPU.
2748 return state_->handle; // Expose a synchronized GL resource handle for interoperation.
2749 } // End this scope in gl handle.
2750 /** @brief Notify shdr after the application writes the GL texture. its context must be current. */
2751 void mark_gpu_modified(device& d) { // Record a write performed by application GL commands.
2752 if (state_->owner != d.state() || !state_->handle) // Check that this storage belongs to the requested device.
2753 throw error("resource has no handle on this device"); // Report a mismatch between the resource handle and the device.
2754 state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2755 } // End this scope in mark gpu modified.
2756 /** @brief Notify shdr after changing a retained host pixel pointer. */
2757 void mark_host_modified() { // Record a write through retained or borrowed host memory.
2758 state_->latest = detail::authority::host; // Record which backend now owns the newest resource values.
2759 } // End this scope in mark host modified.
2760 /** @brief Borrow a matching immutable-format, level-zero 2D GL texture. caller retains ownership. */
2761 static image2d from_gl(device& d, unsigned handle, unsigned w, unsigned h) { // Borrow an application-owned GL object.
2762 if (!handle) // Validate the resource handle before using it.
2763 throw error("cannot borrow GL texture zero"); // Require a nonzero GL texture handle.
2764 image2d result(w, h); // Allocate host pixel storage before attaching the borrowed texture.
2765 result.state_->owner = d.state(); // Set the device that owns the GL resource.
2766 result.state_->handle = handle; // Set the GL buffer or texture name.
2767 result.state_->borrowed = true; // Set whether the application owns the supplied GL object.
2768 result.state_->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
2769 return result; // Return the value returned by this operation.
2770 } // End this scope in from gl.
2771 /** @internal Runtime access to shared image storage and synchronization state. */
2772 const std::shared_ptr<detail::image_state<T>>& state() const { // Expose retained runtime state to the resource and backend helpers.
2773 return state_; // Return the storage or execution state retained by this wrapper.
2774 } // End this scope in state.
2775}; // End this scope in runtime.
2776
2777class kernel; // Keep the kernel values and operations together.
2778namespace detail { // Group these definitions in the detail namespace.
2779enum class port_kind { buffer, image, uniform }; // Name the profile, access, or completion values accepted by this section.
2780struct port_base { // Keep the port base values and operations together.
2781 kernel& parent; // Keep the shader instance that owns this interface.
2782 std::string name; // Keep the resource or entry-point name.
2783 unsigned binding; // Keep the numeric shader resource binding.
2784 access mode; // Keep the declared shader resource access.
2785 port_kind kind; // Keep the buffer, image, or uniform interface kind.
2786 port_base(kernel&, const char*, unsigned, access, port_kind); // Register the named interface with its owning shader.
2787 virtual ~port_base() { // Allow typed interfaces to be destroyed through this base interface.
2788 } // End this scope in runtime.
2789 virtual std::shared_ptr<resource_state> resource() const { // Expose the retained storage used by this port.
2790 return std::shared_ptr<resource_state>(); // Represent a uniform-only interface with an empty resource reference.
2791 } // End this scope in runtime.
2792 virtual void bind_gpu(device_state&, GLuint) { // Bind this interface or assign its uniform before dispatch.
2793 } // End this scope in bind gpu.
2794 virtual void validate() const { // Check that this resource binding satisfies the shader declaration.
2795 } // End this scope in validate.
2796 virtual void copy_to(port_base&) const { // Copy the typed port into a matching snapshot interface.
2797 throw error("shader port does not support snapshots"); // Report that this port requires snapshot support.
2798 } // End this scope in copy to.
2799}; // End this scope in runtime.
2800} // namespace detail
2801
2802/** @brief Base for compiled shader objects, owning resource declarations and invocation builtins.
2803 * Shader objects are neither copyable nor movable because their ports refer to their instance.
2804 * CMake-generated adapters embed their native GLSL source automatically.
2805 */
2806class kernel { // Keep the kernel values and operations together.
2807 std::string name_, source_; // Keep the diagnostic shader name and its embedded GLSL text.
2808 extent local_; // Keep the fixed workgroup dimensions.
2809 std::vector<detail::port_base*> ports_; // Keep the registered resource and uniform interfaces.
2810 std::shared_ptr<detail::program_state> program_; // Keep the retained compiled compute program.
2811
2812 protected: // Allow derived kernels to initialize their embedded source.
2813 // Generated shader constructors install their build-embedded GLSL through this method.
2814 void set_embedded_source(const char* text) { // Retain the build-generated GLSL text inside the shader.
2815 source_ = text; // Set the automatically embedded shader text.
2816 } // End this scope in runtime.
2817
2818 public: // Expose the operations callers can use.
2819 glsl::uvec3 gl_GlobalInvocationID, gl_LocalInvocationID, gl_WorkGroupID, gl_NumWorkGroups, // Keep CPU global, local, group and dispatch coordinates for GLSL builtins.
2820 gl_WorkGroupSize; // Keep the fixed local dimensions exposed to CPU shader code.
2821 unsigned gl_LocalInvocationIndex; // Keep the flattened index within the current CPU work group.
2822 /** @brief Construct a kernel identity and positive local workgroup dimensions.
2823 * SHDR_BEGIN emits this constructor for shared shader classes.
2824 */
2825 kernel(const std::string& name, extent local) // Initialize the shader name, local dimensions, and invocation values.
2826 : name_(name), local_(local), gl_LocalInvocationIndex(0) { // Remember the shader name and local size with initially zero CPU invocation state.
2827 if (!local.x || !local.y || !local.z) // Require positive local dimensions on every axis.
2828 throw error("local work group dimensions must be positive"); // Report local work group dimensions must be positive.
2829 gl_WorkGroupSize = glsl::uvec3(local.x, local.y, local.z); // Publish the fixed local dimensions to CPU shader builtins.
2830 } // End this scope in kernel.
2831 virtual ~kernel() { // Allow derived shader instances to be destroyed through the base interface.
2832 } // End this scope in kernel.
2833 kernel(const kernel&) = delete; // Prevent copying this object and duplicating its retained identity.
2834 kernel& operator=(const kernel&) = delete; // Prevent copying this object and duplicating its retained identity.
2835 /** @brief Execute one CPU invocation. SHDR_MAIN supplies the override.
2836 * Dispatch through a stage or pipeline to initialize builtins and synchronize resources.
2837 */
2838 virtual void main() = 0; // Require a compiled shader to supply its CPU invocation method.
2839 /** @brief Make an independent shader instance with a snapshot of its resource bindings and uniforms. */
2840 virtual std::unique_ptr<kernel> clone() const { // Create an independent shader instance for deferred CPU execution.
2841 throw error("shader does not support snapshots"); // Report that this shader requires snapshot support.
2842 } // End this scope in runtime.
2843 /** @internal Copy registered interfaces into a newly constructed instance. */
2844 void copy_interfaces(kernel& destination) const { // Copy resource bindings and uniforms into a fresh shader clone.
2845 if (ports_.size() != destination.ports_.size()) // Check resource size or driver limits before accessing storage.
2846 throw error("shader snapshot interface mismatch"); // Report shader snapshot interface mismatch.
2847 for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
2848 ports_[i]->copy_to(*destination.ports_[i]); // Copy the typed port into a matching snapshot interface.
2849 } // End this scope in copy interfaces.
2850 /** @internal Retain all resources used by an enqueued dispatch. */
2851 std::vector<std::shared_ptr<detail::resource_state>> resources() const { // Collect the shared storage used by this shader.
2852 std::vector<std::shared_ptr<detail::resource_state>> result; // Keep the value returned by this operation.
2853 for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
2854 auto r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
2855 if (r) // Choose this branch when r.
2856 result.push_back(r); // Retain this entry in the ordered resource or work collection.
2857 } // End this scope in resources.
2858 return result; // Return the value returned by this operation.
2859 } // End this scope in resources.
2860 /** @internal Retain a compiled program during asynchronous execution. */
2861 const std::shared_ptr<detail::program_state>& program_state() const { // Expose the retained compiled program for asynchronous ownership.
2862 return program_; // Return the retained compiled compute program.
2863 } // End this scope in program state.
2864 /** @brief Return the kernel's diagnostic name. */
2865 const std::string& name() const { // Return the diagnostic shader name.
2866 return name_; // Return the kernel or registration name.
2867 } // End this scope in runtime.
2868 /** @brief Return the fixed local workgroup dimensions declared by SHDR_BEGIN. */
2869 extent local_size() const { // Return the fixed local work group dimensions.
2870 return local_; // Return the fixed workgroup dimensions.
2871 } // End this scope in runtime.
2872 /** @brief Export this shader's automatically embedded source for compiler diagnostics or tooling. */
2873 std::string glsl(profile p) const { // Export the embedded shader for the requested language profile.
2874 if (source_.empty()) // Choose this branch when source .empty().
2875 throw error("shader has no embedded GPU source: " + name_); // Report that this shader requires an embedded GPU program.
2876 return glsl_source(source_, p); // Return the result of this check or operation.
2877 } // End this scope in runtime.
2878 /** @internal Register declarations emitted by the shared shader macros. */
2879 void register_port(detail::port_base& port) { // Register one named resource or uniform with duplicate checks.
2880 for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
2881 if (ports_[i]->name == port.name) // Choose this branch when ports [i]->name equals port.name.
2882 throw error("duplicate shader port: " + port.name); // Report duplicate shader port: .
2883 if (port.kind != detail::port_kind::uniform && ports_[i]->kind == port.kind && // Choose the branch matching this interface or resource access.
2884 ports_[i]->binding == port.binding) // Set the numeric shader resource binding.
2885 throw error("duplicate shader resource binding: " + port.name); // Report duplicate shader resource binding: .
2886 } // End this scope in register port.
2887 ports_.push_back(&port); // Retain this entry in the ordered resource or work collection.
2888 } // End this scope in register port.
2889 /** @brief Bind by name, for runtime-selected shader modules. Type mismatches throw error. */
2890 template <class T> kernel& bind(const std::string& name, const buffer<T>& resource); // Select the scalar, dimension, or access type at compile time.
2891 /** @brief Bind an image by name. scalar type and component count must match its port. */
2892 template <class T, unsigned C> // Select the scalar, dimension, or access type at compile time.
2893 kernel& bind(const std::string& name, const image2d<T, C>& resource); // Rebind a named resource port while preserving its declared type.
2894 /** @brief Assign a uniform by name. T must exactly match its declared shader type. */
2895 template <class T> kernel& set(const std::string& name, const T& value); // Select the scalar, dimension, or access type at compile time.
2896 /** @internal Find a registered port for runtime binding and uniform assignment. */
2897 detail::port_base& find_port(const std::string& name) { // Resolve the named shader interface.
2898 for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
2899 if (ports_[i]->name == name) // Choose this branch when ports [i]->name equals name.
2900 return *ports_[i]; // Resolve the named shader interface.
2901 throw error("unknown shader port: " + name); // Report unknown shader port: .
2902 } // End this scope in find port.
2903 /** @brief Execute one dispatch with workgroup counts on a device, or on the CPU if null.
2904 * Normally called by pipeline.run(). GPU work uses the embedded shader and a current context.
2905 */
2906 void run(extent groups, device* d); // Keep the target device.
2907 /** @brief Compile and allocate GPU resources before entering a latency-sensitive dispatch loop. */
2908 void prepare(device& d); // Compile the program and prepare its bound GPU resources.
2909}; // End this scope in runtime.
2910
2911namespace detail { // Group these definitions in the detail namespace.
2912inline port_base::port_base(kernel& p, const char* n, unsigned b, access a, port_kind k) // Register the named interface with its owning shader.
2913 : parent(p), name(n), binding(b), mode(a), kind(k) { // Record the owning kernel, interface name, binding, access and resource kind.
2914 parent.register_port(*this); // Register one named resource or uniform with duplicate checks.
2915} // End this scope in runtime.
2916} // namespace detail
2917
2918/** @brief Typed shader SSBO declaration. assign a buffer to bind or rebind it. */
2919template <class T, access A = access::readwrite> class buffer_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
2920 std::shared_ptr<detail::buffer_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
2921 unsigned fixed_length_; // Keep the fixed array length declared by the shader.
2922
2923 public: // Expose the operations callers can use.
2924 /** @brief Declare a typed buffer port on a kernel, usually through SHDR_BUFFER. */
2925 buffer_port(kernel& p, unsigned b, const char* n, unsigned fixed = 0) // Register a typed buffer interface and any fixed shader array length.
2926 : port_base(p, n, b, A, detail::port_kind::buffer), fixed_length_(fixed) { // Record the buffer interface and its optional fixed shader length.
2927 } // End this scope in runtime.
2928 /** @brief Bind or rebind this port to the buffer's retained shared storage. */
2929 buffer_port& operator=(const buffer<T>& b) { // Retain the newly bound typed resource in this shader interface.
2930 state_ = b.state(); // Set the state shared by this wrapper and its retained owners.
2931 return *this; // Allow another operation to follow in the same expression.
2932 } // End this scope in runtime.
2933 void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
2934 buffer_port* p = dynamic_cast<buffer_port*>(&destination); // Require a snapshot port with the same buffer type and access qualifier.
2935 if (!p) // Validate the typed interface pointer before accessing it.
2936 throw error("buffer snapshot type mismatch: " + name); // Report buffer snapshot type mismatch: .
2937 p->state_ = state_; // Set the state shared by this wrapper and its retained owners.
2938 } // End this scope in copy to.
2939 /** @brief Return the bound buffer's element count, matching GLSL array length(). */
2940 unsigned length() const { // Return the GLSL-visible array length after validating its binding.
2941 validate(); // Check that this resource binding satisfies the shader declaration.
2942 return fixed_length_ ? fixed_length_ : static_cast<unsigned>(state_->count); // Return the GLSL-visible array length after validating its binding.
2943 } // End this scope in length.
2944 /** @brief Access an element during CPU execution, checking bounds and declared access.
2945 * Readonly ports return const references. Pipeline execution synchronizes host contents.
2946 */
2947 typename std::conditional<A == access::readonly, const T&, T&>::type operator[](std::size_t i) { // Expose a const component for readonly ports and a mutable one otherwise.
2948 validate(); // Check that this resource binding satisfies the shader declaration.
2949 const std::size_t limit = fixed_length_ ? fixed_length_ : state_->count; // Use the declared array size or the full bound buffer length.
2950 if (i >= limit) // Choose this branch when i >= limit.
2951 throw error("CPU SSBO index out of bounds: " + name); // Report cpu ssbo index out of bounds: .
2952 return static_cast<T*>(state_->host_pointer())[i]; // Return the result of this check or operation.
2953 } // End this scope in runtime.
2954 void validate() const override { // Check that this resource binding satisfies the shader declaration.
2955 if (!state_) // Require retained storage for this interface.
2956 throw error("unbound shader buffer: " + name); // Report unbound shader buffer: .
2957 if (fixed_length_ && state_->count < fixed_length_) // Check resource size or driver limits before accessing storage.
2958 throw error("buffer is smaller than the shader's fixed array: " + name); // Report buffer is smaller than the shader's fixed array: .
2959 } // End this scope in validate.
2960 std::shared_ptr<detail::resource_state> resource() const override { // Expose the retained storage used by this port.
2961 return state_; // Return the storage or execution state retained by this wrapper.
2962 } // End this scope in runtime.
2963 void bind_gpu(detail::device_state& d, unsigned) override { // Bind this interface or assign its uniform before dispatch.
2964 if (binding >= d.max_buffers) // Choose this branch when binding >= d.max buffers.
2965 throw error("SSBO binding exceeds device limit: " + name); // Report ssbo binding exceeds device limit: .
2966 if (!state_->bytes()) // Check resource size or driver limits before accessing storage.
2967 throw error("GPU SSBO bindings require a nonempty buffer: " + name); // Report gpu ssbo bindings require a nonempty buffer: .
2968 d.gl.BindBufferBase(detail::SHADER_STORAGE_BUFFER, binding, state_->handle); // Bind storage to the shader interface index.
2969 } // End this scope in bind gpu.
2970}; // End this scope in runtime.
2971
2972namespace detail { // Group these definitions in the detail namespace.
2973inline void uniform_value(gl_api& gl, GLint loc, float v) { // Send the typed uniform value through its matching GL call.
2974 gl.Uniform1f(loc, v); // Assign a float uniform.
2975} // End this scope in uniform value.
2976inline void uniform_value(gl_api& gl, GLint loc, int v) { // Send the typed uniform value through its matching GL call.
2977 gl.Uniform1i(loc, v); // Assign an integer or boolean uniform.
2978} // End this scope in uniform value.
2979inline void uniform_value(gl_api& gl, GLint loc, unsigned v) { // Send the typed uniform value through its matching GL call.
2980 gl.Uniform1ui(loc, v); // Assign an unsigned integer uniform.
2981} // End this scope in uniform value.
2982inline void uniform_value(gl_api& gl, GLint loc, bool v) { // Send the typed uniform value through its matching GL call.
2983 gl.Uniform1i(loc, v ? 1 : 0); // Assign an integer or boolean uniform.
2984} // End this scope in uniform value.
2985#define SHDR_UNIFORM_VEC(n, t, suffix) /* Define the SHDR_UNIFORM_VEC helper for this group of declarations. */ \
2986 inline void uniform_value(gl_api& gl, GLint loc, const glsl::vec<t, n>& v) { /* Send the typed uniform value through its matching GL call. */ \
2987 t packed[n]; /* Pack the vector components contiguously for the GL uniform call. */ \
2988 for (unsigned i = 0; i < n; ++i) /* Visit the values or interfaces needed by uniform value. */ \
2989 packed[i] = v[i]; /* Copy the component into the contiguous GL uniform payload. */ \
2990 gl.Uniform##n##suffix(loc, 1, packed); /* Send the packed vector components through their matching GL function. */ \
2991 } /* End this scope in uniform value. */
2992SHDR_UNIFORM_VEC(2, float, fv) // Define the listed float, signed or unsigned vector uniform overloads.
2993SHDR_UNIFORM_VEC(3, float, fv) SHDR_UNIFORM_VEC(4, float, fv) SHDR_UNIFORM_VEC(2, int, iv) // Define the listed float, signed or unsigned vector uniform overloads.
2994 SHDR_UNIFORM_VEC(3, int, iv) SHDR_UNIFORM_VEC(4, int, iv) SHDR_UNIFORM_VEC(2, unsigned, uiv) // Define the listed float, signed or unsigned vector uniform overloads.
2995 SHDR_UNIFORM_VEC(3, unsigned, uiv) SHDR_UNIFORM_VEC(4, unsigned, uiv) // Define the listed float, signed or unsigned vector uniform overloads.
2996#undef SHDR_UNIFORM_VEC // Remove this temporary macro after its declarations are complete.
2997 template <std::size_t N> // Select the scalar, dimension, or access type at compile time.
2998 inline void uniform_value(gl_api& gl, GLint loc, const glsl::vec<bool, N>& v) { // Send the typed uniform value through its matching GL call.
2999 GLint packed[N]; // Pack boolean components as the integer values expected by GL.
3000 for (unsigned i = 0; i < N; ++i) // Visit the values or interfaces needed by uniform value.
3001 packed[i] = v[i] ? 1 : 0; // Represent a boolean uniform component as a GL integer.
3002 if (N == 2) // Choose this branch when N equals 2.
3003 gl.Uniform2iv(loc, 1, packed); // Send two integer-represented boolean components to GL.
3004 else if (N == 3) // Choose this branch when N equals 3.
3005 gl.Uniform3iv(loc, 1, packed); // Send three integer-represented boolean components to GL.
3006 else // Handle the other resource, platform, or completion case.
3007 gl.Uniform4iv(loc, 1, packed); // Send four integer-represented boolean components to GL.
3008} // End this scope in uniform value.
3009#define SHDR_UNIFORM_MATRIX(c, r, n) /* Define the SHDR_UNIFORM_MATRIX helper for this group of declarations. */ \
3010 inline void uniform_value(gl_api& gl, GLint loc, const glsl::mat<float, c, r>& m) { /* Send the typed uniform value through its matching GL call. */ \
3011 float packed[c * r]; /* Send the typed uniform value through its matching GL call. */ \
3012 for (unsigned i = 0; i < c; ++i) /* Visit the values or interfaces needed by uniform value. */ \
3013 for (unsigned j = 0; j < r; ++j) /* Visit the values or interfaces needed by uniform value. */ \
3014 packed[i * r + j] = m[i][j]; /* Flatten the matrix in GLSL column order. */ \
3015 gl.UniformMatrix##n##fv(loc, 1, 0, packed); /* Upload the column-major matrix with the transpose flag set to false. */ \
3016 } /* End this scope in uniform value. */
3017SHDR_UNIFORM_MATRIX(2, 2, 2) // Define the listed column-major matrix uniform overloads.
3018SHDR_UNIFORM_MATRIX(3, 3, 3) SHDR_UNIFORM_MATRIX(4, 4, 4) SHDR_UNIFORM_MATRIX(2, 3, 2x3) // Define the listed column-major matrix uniform overloads.
3019 SHDR_UNIFORM_MATRIX(2, 4, 2x4) SHDR_UNIFORM_MATRIX(3, 2, 3x2) SHDR_UNIFORM_MATRIX(3, 4, 3x4) // Define the listed column-major matrix uniform overloads.
3020 SHDR_UNIFORM_MATRIX(4, 2, 4x2) SHDR_UNIFORM_MATRIX(4, 3, 4x3) // Define the listed column-major matrix uniform overloads.
3021#undef SHDR_UNIFORM_MATRIX // Remove this temporary macro after its declarations are complete.
3022} // namespace detail
3023
3024/** @brief A zero-initialized typed shader uniform, assigned with ordinary C++ syntax. */
3025template <class T> class uniform_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
3026 T owned_; // Keep the uniform value stored by the port.
3027 T* value_; // Keep the current uniform field.
3028
3029 public: // Expose the operations callers can use.
3030 /** @brief Declare a zero-initialized uniform backed by this port's own value. */
3031 uniform_port(kernel& p, const char* n) // Register a typed uniform backed by this port's own zero-initialized value.
3032 : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(), // Keep the uniform value stored by the port.
3033 value_(&owned_) { // Keep the uniform value stored by the port.
3034 } // End this scope in runtime.
3035 /** @brief Register an existing typed kernel field as a uniform. emitted by SHDR_UNIFORM. */
3036 uniform_port(kernel& p, const char* n, T& value) // Register a uniform and refer to its shader member value.
3037 : port_base(p, n, 0, access::readonly, detail::port_kind::uniform), owned_(), // Keep the uniform value stored by the port.
3038 value_(&value) { // Refer to the uniform member owned by this shader instance.
3039 } // End this scope in runtime.
3040 /** @brief Set the uniform value uploaded at the next dispatch. */
3041 uniform_port& operator=(const T& value) { // Assign the shader member referred to by this uniform interface.
3042 *value_ = value; // Set the current uniform field.
3043 return *this; // Allow another operation to follow in the same expression.
3044 } // End this scope in runtime.
3045 /** @brief Read the uniform as its declared shader type during CPU execution. */
3046 operator T() const { // Read the uniform member as an ordinary value of its declared type.
3047 return *value_; // Return the result of this check or operation.
3048 } // End this scope in runtime.
3049 /** @brief Return the stored uniform value. */
3050 const T& value() const { // Read the shader member referred to by this uniform port.
3051 return *value_; // Return the result of this check or operation.
3052 } // End this scope in runtime.
3053 void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
3054 uniform_port* p = dynamic_cast<uniform_port*>(&destination); // Require a snapshot port with the same uniform type.
3055 if (!p) // Validate the typed interface pointer before accessing it.
3056 throw error("uniform snapshot type mismatch: " + name); // Report uniform snapshot type mismatch: .
3057 *p->value_ = *value_; // Set the current uniform field.
3058 } // End this scope in copy to.
3059 void bind_gpu(detail::device_state& d, unsigned program) override { // Bind this interface or assign its uniform before dispatch.
3060 const int loc = d.gl.GetUniformLocation(program, name.c_str()); // Find a named uniform in the linked program.
3061 if (loc >= 0) // Choose this branch when loc >= 0.
3062 detail::uniform_value(d.gl, loc, *value_); // Send the typed uniform value through its matching GL call.
3063 } // End this scope in bind gpu.
3064}; // End this scope in runtime.
3065
3066/** @brief A typed image declaration with format/access matching its shared shader. */
3067template <class T, unsigned C, access A> class image_port : public detail::port_base { // Select the scalar, dimension, or access type at compile time.
3068 std::shared_ptr<detail::image_state<T>> state_; // Keep the state shared by this wrapper and its retained owners.
3069
3070 public: // Expose the operations callers can use.
3071 /** @brief Declare an image port, usually through SHDR_IMAGE2D. */
3072 image_port(kernel& p, unsigned b, const char* n) // Register a typed image interface at the specified binding.
3073 : port_base(p, n, b, A, detail::port_kind::image) { // Record the image interface and its declared access qualifier.
3074 } // End this scope in runtime.
3075 /** @brief Bind or rebind this port to the image's retained shared storage. */
3076 image_port& operator=(const image2d<T, C>& image) { // Retain the newly bound typed resource in this shader interface.
3077 state_ = image.state(); // Set the state shared by this wrapper and its retained owners.
3078 return *this; // Allow another operation to follow in the same expression.
3079 } // End this scope in runtime.
3080 void copy_to(detail::port_base& destination) const override { // Copy the typed port into a matching snapshot interface.
3081 image_port* p = dynamic_cast<image_port*>(&destination); // Require a snapshot port with the same image type and access qualifier.
3082 if (!p) // Validate the typed interface pointer before accessing it.
3083 throw error("image snapshot type mismatch: " + name); // Report image snapshot type mismatch: .
3084 p->state_ = state_; // Set the state shared by this wrapper and its retained owners.
3085 } // End this scope in copy to.
3086 void validate() const override { // Check that this resource binding satisfies the shader declaration.
3087 if (!state_) // Require retained storage for this interface.
3088 throw error("unbound shader image: " + name); // Report unbound shader image: .
3089 } // End this scope in validate.
3090 std::shared_ptr<detail::resource_state> resource() const override { // Expose the retained storage used by this port.
3091 return state_; // Return the storage or execution state retained by this wrapper.
3092 } // End this scope in runtime.
3093 /** @internal Read image state for the CPU imageLoad/imageStore/imageSize helpers. */
3094 const std::shared_ptr<detail::image_state<T>>& image_state() const { // Expose the validated image storage to CPU image helpers.
3095 validate(); // Check that this resource binding satisfies the shader declaration.
3096 return state_; // Return the storage or execution state retained by this wrapper.
3097 } // End this scope in runtime.
3098 void bind_gpu(detail::device_state& d, unsigned) override { // Bind this interface or assign its uniform before dispatch.
3099 if (binding >= d.max_images) // Choose this branch when binding >= d.max images.
3100 throw error("image binding exceeds device limit: " + name); // Report image binding exceeds device limit: .
3101 d.gl.BindImageTexture(binding, // Bind a typed image to its shader interface index.
3102 state_->handle, // Keep the GL buffer or texture name.
3103 0, // Supply the next value for the current call or declaration.
3104 0, // Supply the next value for the current call or declaration.
3105 0, // Supply the next value for the current call or declaration.
3106 A == access::readonly ? detail::READ_ONLY // Select the GL read or write qualifier matching this typed image port.
3107 : A == access::writeonly ? detail::WRITE_ONLY // Choose the GL image access matching the shader qualifier.
3108 : detail::READ_WRITE, // Choose the GL image access matching the shader qualifier.
3109 state_->format); // Keep the image storage format.
3110 } // End this scope in bind gpu.
3111}; // End this scope in runtime.
3112
3113/** @brief GLSL image dimensions in pixels. */
3114template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3115inline glsl::ivec2 imageSize(const image_port<T, C, A>& image) { // Return the bound image dimensions as GLSL integers.
3116 return glsl::ivec2(image.image_state()->width, image.image_state()->height); // Return the bound image dimensions as GLSL integers.
3117} // End this scope in imageSize.
3118/** @brief Load one texel. Missing RGB components are zero and missing alpha is one.
3119 * Out-of-range coordinates return zero. loading a writeonly image is a compile error.
3120 */
3121template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3122inline glsl::vec<T, 4> imageLoad(const image_port<T, C, A>& image, glsl::ivec2 pos) { // Load one pixel while enforcing readonly access and image bounds.
3123 static_assert(A != access::writeonly, "cannot imageLoad a writeonly image"); // Require a representation that matches the shader interface.
3124 const std::shared_ptr<detail::image_state<T>>& s = image.image_state(); // Access the retained image geometry and host pixel storage.
3125 if (pos.x < 0 || pos.y < 0 || static_cast<unsigned>(pos.x) >= s->width || // Choose this branch when pos.x < 0 or pos.y < 0 or static cast<unsigned>(pos.x) >= s->width or .
3126 static_cast<unsigned>(pos.y) >= s->height) // Reject an image row outside the allocated pixel storage.
3127 return glsl::vec<T, 4>(T(0)); // Load one pixel while enforcing readonly access and image bounds.
3128 glsl::vec<T, 4> result(T(0)); // Start the loaded texel with zero components before filling its channels.
3129 result[3] = T(1); // Set the value returned by this operation.
3130 const std::size_t start = // Set the beginning of the current token or range.
3131 (static_cast<std::size_t>(pos.y) * s->width + static_cast<unsigned>(pos.x)) * C; // Load one pixel while enforcing readonly access and image bounds.
3132 for (unsigned c = 0; c < C; ++c) // Visit the values or interfaces needed by imageLoad.
3133 result[c] = s->owned[start + c]; // Set the value returned by this operation.
3134 return result; // Return the value returned by this operation.
3135} // End this scope in imageLoad.
3136/** @brief Store a texel, ignoring out-of-range coordinates. Readonly stores are a compile error. */
3137template <class T, unsigned C, access A> // Select the scalar, dimension, or access type at compile time.
3138inline void imageStore(image_port<T, C, A>& image, glsl::ivec2 pos, const glsl::vec<T, 4>& value) { // Store one pixel while enforcing writable access and image bounds.
3139 static_assert(A != access::readonly, "cannot imageStore a readonly image"); // Require a representation that matches the shader interface.
3140 const std::shared_ptr<detail::image_state<T>>& s = image.image_state(); // Access the retained image geometry and host pixel storage.
3141 if (pos.x < 0 || pos.y < 0 || static_cast<unsigned>(pos.x) >= s->width || // Choose this branch when pos.x < 0 or pos.y < 0 or static cast<unsigned>(pos.x) >= s->width or .
3142 static_cast<unsigned>(pos.y) >= s->height) // Reject an image row outside the allocated pixel storage.
3143 return; // Finish this operation.
3144 const std::size_t start = // Set the beginning of the current token or range.
3145 (static_cast<std::size_t>(pos.y) * s->width + static_cast<unsigned>(pos.x)) * C; // Store one pixel while enforcing writable access and image bounds.
3146 for (unsigned c = 0; c < C; ++c) // Visit the values or interfaces needed by imageStore.
3147 s->owned[start + c] = value[c]; // Set host storage allocated by this resource.
3148} // End this scope in imageStore.
3149
3150template <class T> inline kernel& kernel::bind(const std::string& name, const buffer<T>& b) { // Select the scalar, dimension, or access type at compile time.
3151 detail::port_base& p = find_port(name); // Find the declared shader interface with this resource name.
3152 if (buffer_port<T, access::readonly>* v = dynamic_cast<buffer_port<T, access::readonly>*>(&p)) // Choose this branch when buffer port<T, access::readonly>* v = dynamic cast<buffer port<T, access::readonly>*>(&p).
3153 *v = b; // Store the current v value for this operation.
3154 else if (buffer_port<T, access::writeonly>* v = // Choose this branch when buffer port<T, access::writeonly>* v =.
3155 dynamic_cast<buffer_port<T, access::writeonly>*>(&p)) // Try the matching typed write-only buffer interface.
3156 *v = b; // Store the current v value for this operation.
3157 else if (buffer_port<T, access::readwrite>* v = // Choose this branch when buffer port<T, access::readwrite>* v =.
3158 dynamic_cast<buffer_port<T, access::readwrite>*>(&p)) // Try the matching typed read-write buffer interface.
3159 *v = b; // Store the current v value for this operation.
3160 else // Handle the other resource, platform, or completion case.
3161 throw error("buffer type mismatch: " + name); // Report buffer type mismatch: .
3162 return *this; // Allow another operation to follow in the same expression.
3163} // End this scope in runtime.
3164template <class T, unsigned C> // Select the scalar, dimension, or access type at compile time.
3165inline kernel& kernel::bind(const std::string& name, const image2d<T, C>& b) { // Rebind a named resource port while preserving its declared type.
3166 detail::port_base& p = find_port(name); // Find the declared shader interface with this resource name.
3167 if (image_port<T, C, access::readonly>* v = // Choose this branch when image port<T, C, access::readonly>* v =.
3168 dynamic_cast<image_port<T, C, access::readonly>*>(&p)) // Try the matching typed read-only image interface.
3169 *v = b; // Store the current v value for this operation.
3170 else if (image_port<T, C, access::writeonly>* v = // Choose this branch when image port<T, C, access::writeonly>* v =.
3171 dynamic_cast<image_port<T, C, access::writeonly>*>(&p)) // Try the matching typed write-only image interface.
3172 *v = b; // Store the current v value for this operation.
3173 else if (image_port<T, C, access::readwrite>* v = // Choose this branch when image port<T, C, access::readwrite>* v =.
3174 dynamic_cast<image_port<T, C, access::readwrite>*>(&p)) // Try the matching typed read-write image interface.
3175 *v = b; // Store the current v value for this operation.
3176 else // Handle the other resource, platform, or completion case.
3177 throw error("image type mismatch: " + name); // Report image type mismatch: .
3178 return *this; // Allow another operation to follow in the same expression.
3179} // End this scope in runtime.
3180template <class T> inline kernel& kernel::set(const std::string& name, const T& value) { // Select the scalar, dimension, or access type at compile time.
3181 uniform_port<T>* p = dynamic_cast<uniform_port<T>*>(&find_port(name)); // Require the named uniform to have the supplied value's type.
3182 if (!p) // Validate the typed interface pointer before accessing it.
3183 throw error("uniform type mismatch: " + name); // Report uniform type mismatch: .
3184 *p = value; // Update the typed uniform value for subsequent dispatches.
3185 return *this; // Allow another operation to follow in the same expression.
3186} // End this scope in runtime.
3187
3188inline void kernel::prepare(device& d) { // Compile the program and prepare its bound GPU resources.
3189 const auto& state = d.state(); // Set the shared device or worker state.
3190 state->collect(); // Run queued deletions and zero-time completion checks.
3191 for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
3192 ports_[i]->validate(); // Check that this resource binding satisfies the shader declaration.
3193 if (!program_) { // Compile the shader when its cached program is empty.
3194 if (source_.empty()) // Choose this branch when source .empty().
3195 throw error("shader has no embedded GPU source: " + name_); // Report that this shader requires an embedded GPU program.
3196 program_ = std::make_shared<detail::program_state>( // Set the retained compiled compute program.
3197 state, state->compile(glsl_source(source_, state->language), name_)); // Add the selected GLSL version and shared-declaration definitions.
3198 detail::GLint actual[3] = {0, 0, 0}; // Prepare all three local dimensions reported by the linked program.
3199 state->gl.GetProgramiv(program_->id, detail::COMPUTE_WORK_GROUP_SIZE, actual); // Read linked-program status, log length, or local dimensions.
3200 if (actual[0] != static_cast<int>(local_.x) || actual[1] != static_cast<int>(local_.y) || // Choose this branch when actual[0] differs from static cast<int>(local .x) or actual[1] differs from static cast<int>(local .y) or .
3201 actual[2] != static_cast<int>(local_.z)) { // Require the linked program's third local dimension to match the CPU shader.
3202 program_.reset(); // Release or replace the owned object at this lifecycle boundary.
3203 throw error("GPU source and C++ local sizes differ: " + name_); // Report gpu source and c++ local sizes differ: .
3204 } // End this scope in prepare.
3205 } // End this scope in prepare.
3206 if (program_->owner != state) // Check that this storage belongs to the requested device.
3207 throw error("shader program belongs to a different device; create a new shader instance"); // Report shader program belongs to a different device. create a new shader instance.
3208 for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3209 auto r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3210 if (r) // Choose this branch when r.
3211 r->ensure_gpu(state); // Allocate or upload GPU storage when its host copy is newer.
3212 } // End this scope in prepare.
3213} // End this scope in prepare.
3214
3215inline void kernel::run(extent groups, device* d) { // Keep the target device.
3216 if (!groups.x || !groups.y || !groups.z) // Finish an empty dispatch before submitting GL commands.
3217 return; // Finish this operation.
3218 const unsigned g[3] = {groups.x, groups.y, groups.z}, l[3] = {local_.x, local_.y, local_.z}; // Keep dispatch counts and local dimensions for validation and CPU indexing.
3219 for (unsigned i = 0; i < 3; ++i) // Validate or query each of the three compute dimensions.
3220 if (g[i] > (std::numeric_limits<unsigned>::max)() / l[i]) // Choose this branch when g[i] > (std::numeric limits<unsigned>::max)() / l[i].
3221 throw error("global invocation index overflow"); // Report global invocation index overflow.
3222 std::vector<std::shared_ptr<detail::resource_state>> outputs; // Retain the writable resources whose authority changes after this dispatch.
3223 for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3224 ports_[i]->validate(); // Check that this resource binding satisfies the shader declaration.
3225 std::shared_ptr<detail::resource_state> r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3226 if (r && ports_[i]->mode != access::readonly) // Choose the branch matching this interface or resource access.
3227 outputs.push_back(r); // Retain this entry in the ordered resource or work collection.
3228 } // End this scope in runtime.
3229 if (d) { // Choose this branch when d.
3230 const std::shared_ptr<detail::device_state>& state = d->state(); // Set the shared device or worker state.
3231 for (unsigned i = 0; i < 3; ++i) { // Validate or query each of the three compute dimensions.
3232 if (g[i] > state->max_groups[i]) // Choose this branch when g[i] > state->max groups[i].
3233 throw error("dispatch exceeds device work group count"); // Report dispatch exceeds device work group count.
3234 if (l[i] > state->max_local[i]) // Choose this branch when l[i] > state->max local[i].
3235 throw error("local work group dimension exceeds device limit"); // Report local work group dimension exceeds device limit.
3236 } // End this scope in runtime.
3237 const std::size_t invocations = // Count the shader invocations in one local work group.
3238 detail::checked_product(detail::checked_product(l[0], l[1]), l[2]); // Reject resource-size multiplication that would overflow.
3239 if (invocations > state->max_invocations) // Choose this branch when invocations > state->max invocations.
3240 throw error("local invocation count exceeds device limit"); // Report local invocation count exceeds device limit.
3241 prepare(*d); // Compile the program and prepare its bound GPU resources.
3242 state->gl.UseProgram(program_->id); // Select the compute program for the next dispatch.
3243 for (std::size_t i = 0; i < ports_.size(); ++i) // Visit every registered resource and uniform interface.
3244 ports_[i]->bind_gpu(*state, program_->id); // Bind this interface or assign its uniform before dispatch.
3245 state->gl.check("bind shader " + name_); // Keep the kernel or registration name.
3246 state->gl.DispatchCompute(groups.x, groups.y, groups.z); // Queue the shader workgroups.
3247 state->gl.MemoryBarrier(detail::ALL_BARRIER_BITS); // Make earlier resource writes visible to following GPU commands.
3248 // Conservatively record GPU authority even if an error follows a submitted dispatch.
3249 for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3250 outputs[i]->latest = detail::authority::gpu; // Record which backend now owns the newest resource values.
3251 state->gl.check("dispatch shader " + name_); // Keep the kernel or registration name.
3252 } else { // Handle the alternative resource or completion case.
3253 for (std::size_t i = 0; i < ports_.size(); ++i) { // Visit every registered resource and uniform interface.
3254 std::shared_ptr<detail::resource_state> r = ports_[i]->resource(); // Get the shared storage behind this resource interface.
3255 if (r) // Choose this branch when r.
3256 r->ensure_host(); // Download newer GPU values only when host access needs them.
3257 } // End this scope in runtime.
3258 gl_NumWorkGroups = glsl::uvec3(groups.x, groups.y, groups.z); // Publish the dispatch dimensions to CPU shader builtins.
3259 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3260 for (unsigned gz = 0; gz < groups.z; ++gz) // Visit this axis of the dispatch or current workgroup.
3261 for (unsigned gy = 0; gy < groups.y; ++gy) // Visit this axis of the dispatch or current workgroup.
3262 for (unsigned gx = 0; gx < groups.x; ++gx) { // Visit this axis of the dispatch or current workgroup.
3263 gl_WorkGroupID = glsl::uvec3(gx, gy, gz); // Publish the CPU work group currently being executed.
3264 for (unsigned z = 0; z < local_.z; ++z) // Visit this axis of the dispatch or current workgroup.
3265 for (unsigned y = 0; y < local_.y; ++y) // Visit this axis of the dispatch or current workgroup.
3266 for (unsigned x = 0; x < local_.x; ++x) { // Visit this axis of the dispatch or current workgroup.
3267 gl_LocalInvocationID = glsl::uvec3(x, y, z); // Publish the invocation coordinates inside this work group.
3268 gl_GlobalInvocationID = glsl::uvec3( // Combine work group and local coordinates into global indices.
3269 gx * local_.x + x, gy * local_.y + y, gz * local_.z + z); // Use the local size to place this invocation in the complete dispatch.
3270 gl_LocalInvocationIndex = (z * local_.y + y) * local_.x + x; // Flatten the local coordinates with X changing fastest.
3271 main(); // Execute the shader with all CPU invocation builtins initialized.
3272 } // End this scope in runtime.
3273 } // End this scope in runtime.
3274 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3275 for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3276 outputs[i]->latest = detail::authority::host; // Record which backend now owns the newest resource values.
3277 throw; // Rethrow the original failure after arranging the necessary cleanup.
3278 } // End this scope in runtime.
3279 for (std::size_t i = 0; i < outputs.size(); ++i) // Visit this axis of the dispatch or current workgroup.
3280 outputs[i]->latest = detail::authority::host; // Record which backend now owns the newest resource values.
3281 } // End this scope in runtime.
3282} // End this scope in runtime.
3283
3284/** @brief One dispatch retaining a reference to its shader. Keep that shader alive during execution. */
3285struct stage { // Keep the stage values and operations together.
3286 kernel* shader; // Keep the shader used by this dispatch.
3287 extent groups; // Keep the number of workgroups to dispatch.
3288 backend target; // Keep the chosen CPU or GPU backend.
3289 std::shared_ptr<kernel> owner; // Retain an owned kernel while this stage uses it.
3290 /** @brief Retain a kernel reference with workgroup counts and a backend override. */
3291 stage(kernel& k, extent g, backend b) : shader(&k), groups(g), target(b) { // Keep the shader reference, work group counts and backend choice.
3292 } // End this scope in runtime.
3293 stage(std::shared_ptr<kernel> k, extent g, backend b) // Keep the shader reference, work group counts and backend choice.
3294 : shader(k.get()), groups(g), target(b), owner(k) { // Retain the kernel owner together with dispatch dimensions and backend choice.
3295 if (!shader) // Require a retained kernel for this dispatch.
3296 throw error("cannot dispatch a null shader"); // Require a valid kernel for this dispatch.
3297 } // End this scope in runtime.
3298}; // End this scope in runtime.
3299/** @brief Build a dispatch using work group counts, with an optional per-stage backend override. */
3300inline stage dispatch(kernel& shader, extent groups, backend b = backend::automatic) { // Build one ordered dispatch with the requested backend choice.
3301 return stage(shader, groups, b); // Return the result of this check or operation.
3302} // End this scope in runtime.
3303/** @brief Build a dispatch that also retains ownership of its shader. */
3304inline stage // Return a dispatch value that retains its shader owner.
3305dispatch(std::shared_ptr<kernel> shader, extent groups, backend b = backend::automatic) { // Build one ordered dispatch with the requested backend choice.
3306 return stage(shader, groups, b); // Return the result of this check or operation.
3307} // End this scope in runtime.
3308
3309class submission; // Keep the submission values and operations together.
3310
3311/** @brief An ordered pipeline, composed with >> or +=. Resources link stages by shared storage.
3312 * GPU stages issue memory barriers. CPU/GPU transitions transfer authoritative resource contents.
3313 * Running again observes updated uniforms and resource bindings. CPU execution
3314 * completes each stage before returning. GPU execution queues stages in order.
3315 * Request host data or use an explicit wait to observe GPU completion.
3316 */
3317class pipeline { // Keep the pipeline values and operations together.
3318 std::vector<stage> stages_; // Keep the dispatches in execution order.
3319 void execute(device* d) const { // Run stages in order while honoring their backend choices.
3320 for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3321 const stage& s = stages_[i]; // Inspect the next dispatch, its dimensions and backend choice.
3322 if (s.target == backend::gpu && !d) // Require a device for an explicitly GPU stage.
3323 throw error("GPU stage requires a device"); // Report gpu stage requires a device.
3324 s.shader->run(s.groups, s.target == backend::cpu ? 0 : d); // Dispatch this stage on its selected CPU or GPU backend.
3325 } // End this scope in execute.
3326 } // End this scope in execute.
3327
3328 public: // Expose the operations callers can use.
3329 /** @brief Construct an empty pipeline. append dispatches with operator+=. */
3330 pipeline() { // Create the ordered dispatch container.
3331 } // End this scope in runtime.
3332 /** @brief Construct a pipeline containing one dispatch. */
3333 pipeline(stage s) { // Create a pipeline containing this initial dispatch.
3334 stages_.push_back(s); // Keep this dispatch at the end of the processing order.
3335 } // End this scope in runtime.
3336 /** @brief Append a dispatch in execution order and return this pipeline. */
3337 pipeline& operator+=(stage s) { // Append one dispatch while retaining its optional kernel owner.
3338 stages_.push_back(s); // Keep this dispatch at the end of the processing order.
3339 return *this; // Allow another operation to follow in the same expression.
3340 } // End this scope in runtime.
3341 /** @brief Append every dispatch from another pipeline, including a safe copy of this pipeline. */
3342 pipeline& operator+=(const pipeline& other) { // Compose complete processing blocks in their original stage order.
3343 const std::vector<stage> additions(other.stages_); // Preserve the source range before self-append can reallocate it.
3344 stages_.insert(stages_.end(), additions.begin(), additions.end()); // Retain each dispatch's kernel ownership and backend choice.
3345 return *this; // Allow another stage or pipeline to follow in the same expression.
3346 } // Appending copies dispatch references and preserves the stages for later execution.
3347 /** @brief Return the number of stages. */
3348 std::size_t size() const { // Read the stored element or stage count.
3349 return stages_.size(); // Return the result of this check or operation.
3350 } // End this scope in runtime.
3351 /** @brief Run automatic and CPU stages on the CPU. explicit GPU stages need a device. */
3352 void run() const { // Execute the pipeline using the selected CPU or GPU backend.
3353 execute(0); // Run stages in order while honoring their backend choices.
3354 } // End this scope in runtime.
3355 /** @brief Run automatic and GPU stages on the device, respecting explicit CPU stages.
3356 * Host readback completes queued GPU writes when resource data is requested.
3357 */
3358 void run(device& d) const { // Execute the pipeline using the selected CPU or GPU backend.
3359 execute(&d); // Run stages in order while honoring their backend choices.
3360 } // End this scope in runtime.
3361 /** @brief Compile GPU programs and upload resources before steady-state submission. */
3362 void prepare(device& d) const { // Compile the program and prepare its bound GPU resources.
3363 for (std::size_t i = 0; i < stages_.size(); ++i) // Visit every dispatch in processing order.
3364 if (stages_[i].target != backend::cpu) // Precompile and upload stages that can execute on the GPU.
3365 stages_[i].shader->prepare(d); // Compile the program and prepare its bound GPU resources.
3366 } // End this scope in prepare.
3367 /** @brief Enqueue GPU stages and return a fence for zero-timeout completion polls. */
3368 submission submit(device& d) const; // Queue compute work and return its completion handle.
3369 /** @internal Access dispatches for submission and snapshot handling. */
3370 const std::vector<stage>& stages() const { // Expose the ordered dispatches for submission and snapshot handling.
3371 return stages_; // Return the dispatches in execution order.
3372 } // End this scope in runtime.
3373 /** @brief Snapshot shader instances, uniforms and bindings for deferred CPU execution. */
3374 pipeline snapshot() const { // Clone kernels and retain the current binding and uniform values.
3375 pipeline result; // Keep the value returned by this operation.
3376 std::map<kernel*, std::shared_ptr<kernel>> copies; // Keep the shader clones reused by repeated stages.
3377 for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3378 const stage& s = stages_[i]; // Inspect the next dispatch, its dimensions and backend choice.
3379 auto& copy = copies[s.shader]; // Reuse one clone for every occurrence of the same source kernel.
3380 if (!copy) // Create a clone only on the source kernel's first occurrence.
3381 copy = std::shared_ptr<kernel>(s.shader->clone().release()); // Own an isolated clone of this kernel's current interfaces.
3382 result += stage(copy, s.groups, s.target); // Retain the cloned kernel with its original dimensions and backend choice.
3383 } // End this scope in snapshot.
3384 return result; // Return the value returned by this operation.
3385 } // End this scope in snapshot.
3386 /** @brief Validate CPU execution support and current host data for a deferred job. */
3387 void require_host_ready() const { // Validate CPU stages and host-ready resources.
3388 for (std::size_t i = 0; i < stages_.size(); ++i) { // Visit every dispatch in processing order.
3389 if (stages_[i].target == backend::gpu) // Reject GPU-only stages before submitting work to a CPU worker.
3390 throw error("CPU executor cannot execute a GPU-only stage"); // Require CPU-compatible stages for the CPU executor.
3391 auto resources = stages_[i].shader->resources(); // Inspect the resources bound to this stage.
3392 for (std::size_t r = 0; r < resources.size(); ++r) // Check every bound resource for data requiring GPU readback.
3393 if (resources[r]->latest == detail::authority::gpu) // Require the caller to download newer GPU contents on the context thread.
3394 throw error( // Report the invalid operation.
3395 "download GPU data on its context thread before submitting CPU work"); // Explain how to make this resource ready for CPU execution.
3396 } // End this scope in require host ready.
3397 } // End this scope in require host ready.
3398}; // End this scope in runtime.
3399/** @brief Compose ordered stages into a reusable pipeline. */
3400inline pipeline operator>>(stage a, stage b) { // Compose these dispatches in their execution order.
3401 pipeline p(a); // Start the pipeline with the first dispatch.
3402 p += b; // Append the following dispatch to the ordered pipeline.
3403 return p; // Return the composed pipeline for later execution.
3404} // End this scope in runtime.
3405/** @brief Append a stage to a pipeline value, retaining references to the same kernels. */
3406inline pipeline operator>>(pipeline p, stage b) { // Compose these dispatches in their execution order.
3407 p += b; // Append the following dispatch to the ordered pipeline.
3408 return p; // Return the composed pipeline for later execution.
3409} // End this scope in runtime.
3410/** @brief Prepend a stage to a pipeline while retaining the same linked shader resources. */
3411inline pipeline operator>>(stage a, const pipeline& b) { // Place the independent dispatch before all existing processing stages.
3412 pipeline result(a); // Start with the supplied dispatch and its retained kernel owner.
3413 result += b; // Append the complete processing block in its original order.
3414 return result; // Return the reusable pipeline for later execution.
3415} // The source pipeline remains available for further composition or execution.
3416/** @brief Join two complete processing pipelines in execution order. */
3417inline pipeline operator>>(pipeline a, const pipeline& b) { // Compose reusable algorithm blocks with ordinary shader dispatches.
3418 a += b; // Append a copy of the second block's dispatch references.
3419 return a; // Return the combined ordered processing plan.
3420} // Resource sharing follows the same rules as individual stage composition.
3421
3422namespace detail { // Group these definitions in the detail namespace.
3423typedef kernel* (*kernel_factory)(); // Name the representation used by this GL or shader interface.
3424inline std::map<std::string, std::vector<kernel_factory>>& shader_registry() { // Share the compiled shader factories discovered during startup.
3425 static std::map<std::string, std::vector<kernel_factory>> registry; // Keep the shared display lifetime registry.
3426 return registry; // Return the shared display lifetime registry.
3427} // End this scope in shader registry.
3428 // Generated shader translation units register factories directly in their target.
3429 // Unregistering makes plugin unload safe for future lookups. existing shader objects
3430 // still require the plugin to stay loaded through destruction.
3431class shader_registration { // Keep the shader registration values and operations together.
3432 std::string name_; // Keep the kernel or registration name.
3433 kernel_factory factory_; // Keep the compiled shader construction callback.
3434
3435 public: // Expose the operations callers can use.
3436 shader_registration(const char* name, kernel_factory factory) : name_(name), factory_(factory) { // Keep the callback used to create a registered shader.
3437 shader_registry()[name_].push_back(factory_); // Retain this entry in the ordered resource or work collection.
3438 } // End this scope in runtime.
3439 ~shader_registration() { // Unregister this factory before its dynamic module is unloaded.
3440 std::vector<kernel_factory>& entries = shader_registry()[name_]; // Find the registered factories using this shader name.
3441 const std::vector<kernel_factory>::iterator it = // Find this module's factory among the registrations.
3442 std::find(entries.begin(), entries.end(), factory_); // Keep the compiled shader construction callback.
3443 if (it != entries.end()) // Choose this branch when it differs from entries.end().
3444 entries.erase(it); // Remove this module's registration and preserve the other factories.
3445 if (entries.empty()) // Choose this branch when entries.empty().
3446 shader_registry().erase(name_); // Share the compiled shader factories discovered during startup.
3447 } // End this scope in runtime.
3448 shader_registration(const shader_registration&) = delete; // Prevent copying this object and duplicating its retained identity.
3449 shader_registration& operator=(const shader_registration&) = delete; // Prevent copying this object and duplicating its retained identity.
3450}; // End this scope in runtime.
3451} // namespace detail
3452
3453/** @brief Create a shader compiled and embedded by shdr_target_shaders during the CMake build.
3454 * A file named scale.cpp registers scale_kernel. The returned instance owns its CPU/GPU program
3455 * and exposes resource binding through bind() and set(). Both programs are part of the binary.
3456 * Unknown or ambiguous names throw error. Call from one application thread after startup.
3457 */
3458inline std::unique_ptr<kernel> make_kernel(const std::string& name) { // Create one automatically registered shader by its build-time name.
3459 const std::map<std::string, std::vector<detail::kernel_factory>>& registry = // Set the shared display lifetime registry.
3460 detail::shader_registry(); // Share the compiled shader factories discovered during startup.
3461 const std::map<std::string, std::vector<detail::kernel_factory>>::const_iterator it = // Find the unique compiled factory requested by the application.
3462 registry.find(name); // Keep the resource or entry-point name.
3463 if (it == registry.end()) // Choose this branch when it equals registry.end().
3464 throw error("unknown compiled shader: " + name); // Report unknown compiled shader: .
3465 if (it->second.size() != 1) // Check resource size or driver limits before accessing storage.
3466 throw error("ambiguous compiled shader name: " + name); // Report ambiguous compiled shader name: .
3467 return std::unique_ptr<kernel>(it->second.front()()); // Create one automatically registered shader by its build-time name.
3468} // End this scope in make kernel.
3469} // namespace shdr
3470
3471 // A short namespace alias keeps host-side mathematical expressions readable.
3472namespace glsl = shdr::glsl; // Group these definitions in the glsl namespace.
3473#endif // SHDR_RUNTIME_HPP
3474
3475// ---- async.hpp ----
3476/** @file async.hpp
3477 * @brief Nonblocking GPU completion handles and bounded CPU work queues.
3478 * Prepare GPU pipelines before a hot loop, keep a ring of independent resource
3479 * sets, and poll completion before reading or recycling a result. GPU calls
3480 * use the device's context thread. CPU workers execute independent snapshots
3481 * and require host-ready resources. Complete GPU readback on the context thread
3482 * before submitting a CPU job.
3483 */
3484#ifndef SHDR_ASYNC_HPP // Skip this section if it was already included.
3485#define SHDR_ASYNC_HPP /* Mark this section as included. */
3486#ifndef SHDR_RUNTIME_HPP // Skip this section if it was already included.
3487#include "math.hpp" // Use the portable GLSL scalar, vector, and matrix types.
3488#include "runtime.hpp" // Use the kernel, resource, and ordered pipeline definitions.
3489#endif // Finish this conditional section.
3490#include <chrono> // Express explicit waits and zero-time completion polls.
3491#include <condition_variable> // Wake CPU workers when jobs arrive or shutdown begins.
3492#include <deque> // Keep pending CPU jobs in submission order.
3493#include <exception> // Pass worker failures back through completion futures.
3494#include <future> // Give callers a completion result for each CPU job.
3495#include <mutex> // Protect shared work queues and deferred deletion.
3496#include <thread> // Track the context thread and start CPU workers.
3497#include <utility> // Move job and resource ownership between runtime objects.
3498
3499namespace shdr { // Group these definitions in the shdr namespace.
3500
3501/** @brief Result of a completion query: completed work or an expired timeout. */
3502enum class wait_status { ready, timeout }; // Name the two outcomes of a GPU completion query.
3503
3504namespace detail { // Group these definitions in the detail namespace.
3505struct submission_resources { // Keep the submission resources values and operations together.
3506 std::vector<std::shared_ptr<resource_state>> resources; // Keep the resource storage retained until queued work completes.
3507 std::vector<std::shared_ptr<program_state>> programs; // Keep the compiled programs retained by a submission.
3508}; // End this scope in async.
3509
3510struct submission_state { // Keep a GPU fence and its resources alive until retirement.
3511 std::shared_ptr<device_state> owner; // Keep the device that owns the GL resource.
3512 GLsync fence; // Keep the GL completion fence.
3513 std::shared_ptr<submission_resources> retained; // Keep the submission resource bundle.
3514 bool completed; // Cache whether this submission fence has already signaled.
3515 explicit submission_state(const std::shared_ptr<device_state>& d) // Retain the device, fence, and queued resource bundle.
3516 : owner(d), fence(0), retained(std::make_shared<submission_resources>()), completed(false) { // Retain the device and create an empty pending-completion resource bundle.
3517 } // End this scope in submission state.
3518 ~submission_state() noexcept { // Retire completed fences and defer pending fence cleanup.
3519 if (!fence) // Finish immediately for an empty fence.
3520 return; // Finish this operation.
3521 const GLsync sync = fence; // Copy the fence handle into the deferred cleanup callback.
3522 const std::shared_ptr<submission_resources> keep = retained; // Retain buffers and programs until deferred cleanup releases this bundle.
3523 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3524 if (completed) { // Retire a fence whose completion has already been observed.
3525 owner->retire([sync, keep](gl_api& gl) { // Delete on the context thread or defer deletion to that thread.
3526 gl.DeleteSync(sync); // Delete the GL completion fence.
3527 (void)keep; // Keep the resource references captured for this cleanup.
3528 }); // End this scope in submission state.
3529 } else { // Handle the alternative resource or completion case.
3530 // The context thread checks this retirement entry with a zero timeout.
3531 owner->defer_poll( // Retain a completion check until its fence signals.
3532 [sync, keep](gl_api& gl) -> bool { // Retain these captures until the queued callback finishes.
3533 const GLenum status = gl.ClientWaitSync(sync, 0, 0); // Poll the discarded fence with zero flags and a zero timeout.
3534 if (status == TIMEOUT_EXPIRED) // Check the driver result before marking GPU completion.
3535 return false; // Keep the discarded submission pending while its fence is unsignaled.
3536 gl.DeleteSync(sync); // Delete the GL completion fence.
3537 (void)keep; // Keep the resource references captured for this cleanup.
3538 return true; // Remove the retired fence and release its retained resource bundle.
3539 }, // End this scope in submission state.
3540 [sync](gl_api& gl) { // Keep only the fence handle for nonblocking shutdown cancellation.
3541 gl.DeleteSync(sync); // Delete the GL completion fence.
3542 }); // End this scope in submission state.
3543 } // End this scope in submission state.
3544 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3545 // Destruction defers pending fence cleanup. GL command references keep
3546 // already queued operations valid if allocating a retirement entry fails.
3547 } // End this scope in submission state.
3548 } // End this scope in submission state.
3549 wait_status query(GLuint64 timeout) { // Check completion with the requested driver timeout.
3550 owner->require_thread(); // Require the device context thread and activate its headless context.
3551 if (completed) // Reuse the cached completion result after checking the context thread.
3552 return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3553 const GLenum result = owner->gl.ClientWaitSync(fence, 0, timeout); // Check a GPU fence with the caller-selected timeout.
3554 if (result == ALREADY_SIGNALED || result == CONDITION_SATISFIED) { // Check the driver result before marking GPU completion.
3555 completed = true; // Set whether the GPU fence has already signaled.
3556 return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3557 } // End this scope in query.
3558 if (result == TIMEOUT_EXPIRED) // Check the driver result before marking GPU completion.
3559 return wait_status::timeout; // Tell the caller that the explicit wait expired before completion.
3560 owner->gl.check("query GPU submission"); // Check for a driver error from the preceding GL operation.
3561 throw error("GPU completion query failed"); // Report gpu completion query failed.
3562 } // End this scope in query.
3563}; // End this scope in async.
3564} // namespace detail
3565
3566/** @brief A movable handle for one queued GPU pipeline.
3567 * ready() performs a zero-timeout fence query. wait(timeout) bounds the requested
3568 * driver wait. wait() explicitly waits for completion. Destroying a handle
3569 * schedules pending fence and resource cleanup on the device context thread.
3570 * Device garbage collection releases those retained resources after completion.
3571 * Keep the GL context alive until retained work and resources have been retired.
3572 */
3573class submission { // Keep the submission values and operations together.
3574 std::unique_ptr<detail::submission_state> state_; // Own this completion handle and its retained GPU resources.
3575 explicit submission(std::unique_ptr<detail::submission_state> state) // Accept sole ownership of this fence and its retained resource bundle.
3576 : state_(std::move(state)) { // Move the fence state into this completion handle.
3577 } // End this scope in async.
3578 friend class pipeline; // Allow the related pipeline or resource helper to access this retained state.
3579
3580 public: // Expose the operations callers can use.
3581 /** @brief Construct an empty, already-complete handle. */
3582 submission() { // Create an empty handle that is already complete.
3583 } // End this scope in async.
3584 submission(submission&&) noexcept = default; // Move the completion state into the new handle.
3585 submission& operator=(submission&&) noexcept = default; // Retire the old handle and move in the new completion state.
3586 submission(const submission&) = delete; // Prevent copying this object and duplicating its retained identity.
3587 submission& operator=(const submission&) = delete; // Prevent copying this object and duplicating its retained identity.
3588 /** @brief Return whether this handle represents submitted GPU commands. */
3589 bool valid() const { // Check whether this handle represents actual submitted GPU work.
3590 return bool(state_); // Return whether this handle retains a submission state.
3591 } // End this scope in async.
3592 /** @brief Query completion with a zero timeout on the device context thread. */
3593 bool ready() { // Check whether queued work has completed using a zero-timeout poll.
3594 return !state_ || state_->query(0) == wait_status::ready; // Check whether queued work has completed using a zero-timeout poll.
3595 } // End this scope in ready.
3596 /** @brief Request a driver wait with a nonnegative timeout in nanoseconds. */
3597 wait_status wait(std::chrono::nanoseconds timeout) { // Apply the explicit completion wait selected by the caller.
3598 if (timeout.count() < 0) // Require a nonnegative wait duration.
3599 throw error("GPU submission timeout must be nonnegative"); // Report gpu submission timeout must be nonnegative.
3600 if (!state_) // Treat an empty handle as already completed.
3601 return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3602 return state_->query(static_cast<detail::GLuint64>(timeout.count())); // Apply the explicit completion wait selected by the caller.
3603 } // End this scope in wait.
3604 /** @brief Explicitly wait until submitted commands complete. */
3605 wait_status wait() { // Apply the explicit completion wait selected by the caller.
3606 if (!state_) // Treat an empty handle as already completed.
3607 return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3608 while (state_->query((std::numeric_limits<detail::GLuint64>::max)()) == // Use the caller's explicit blocking wait until the fence completes.
3609 wait_status::timeout) { // Repeat only if the implementation still reports an incomplete wait.
3610 } // End this scope in wait.
3611 return wait_status::ready; // Tell the caller that queued GPU commands have completed.
3612 } // End this scope in wait.
3613}; // End this scope in async.
3614
3615/** @brief Enqueue all GPU stages and return a fence for polling or explicit waits.
3616 * Each stage must support GPU execution. Call prepare()
3617 * before entering a latency-sensitive loop to compile shaders and allocate/upload
3618 * resources in advance. Subsequent host edits can still require an upload.
3619 * Uniform and binding changes after return affect subsequent submissions.
3620 */
3621inline submission pipeline::submit(device& d) const { // Queue compute work and return its completion handle.
3622 d.state()->require_thread(); // Require the device context thread and activate its headless context.
3623 const std::vector<stage>& commands = stages(); // Read the ordered stages that this submission will queue.
3624 for (std::size_t i = 0; i < commands.size(); ++i) // Visit each ordered GPU stage in this submission.
3625 if (commands[i].target == backend::cpu) // Reject explicit CPU stages before queueing any GPU commands.
3626 throw error("GPU submission cannot contain CPU stages"); // Require GPU stages for GPU submission.
3627 if (commands.empty()) // Skip fence creation for an empty pipeline.
3628 return submission(); // Represent an empty pipeline with an already completed handle.
3629 std::unique_ptr<detail::submission_state> completion(new detail::submission_state(d.state())); // Retain the device, fence, and queued resource bundle.
3630 completion->retained->programs.reserve(commands.size()); // Reserve room to retain one compiled program per stage.
3631 prepare(d); // Compile the program and prepare its bound GPU resources.
3632 for (std::size_t i = 0; i < commands.size(); ++i) { // Visit each ordered GPU stage in this submission.
3633 const std::vector<std::shared_ptr<detail::resource_state>> resources = // Set the resource storage retained until queued work completes.
3634 commands[i].shader->resources(); // Collect the shared storage used by this shader.
3635 completion->retained->resources.insert( // Retain this entry in the ordered resource or work collection.
3636 completion->retained->resources.end(), resources.begin(), resources.end()); // Keep the end of the current range.
3637 completion->retained->programs.push_back(commands[i].shader->program_state()); // Retain this entry in the ordered resource or work collection.
3638 } // End this scope in submit.
3639 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3640 run(d); // Queue all validated GPU stages in pipeline order.
3641 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3642 // A later dispatch can fail after an earlier dispatch was queued.
3643 completion->fence = d.state()->gl.FenceSync(detail::SYNC_GPU_COMMANDS_COMPLETE, 0); // Insert a completion fence after queued compute work.
3644 d.state()->gl.Flush(); // Flush queued GPU commands for driver execution.
3645 throw; // Rethrow the original failure after arranging the necessary cleanup.
3646 } // End this scope in submit.
3647 completion->fence = d.state()->gl.FenceSync(detail::SYNC_GPU_COMMANDS_COMPLETE, 0); // Insert a completion fence after queued compute work.
3648 if (!completion->fence) { // Check that the driver allocated a valid completion fence.
3649 d.state()->gl.check("create GPU submission fence"); // Expose retained runtime state to the resource and backend helpers.
3650 throw error("cannot create GPU submission fence"); // Report completion-fence allocation failure.
3651 } // End this scope in submit.
3652 d.state()->gl.Flush(); // Flush queued GPU commands for driver execution.
3653 d.state()->gl.check("submit GPU pipeline"); // Expose retained runtime state to the resource and backend helpers.
3654 return submission(std::move(completion)); // Queue compute work and return its completion handle.
3655} // End this scope in submit.
3656
3657/** @brief A bounded CPU executor for independent pipeline jobs.
3658 * Each submit() snapshots kernels, uniforms and resource bindings. Snapshots
3659 * have independent invocation state, while buffers and images retain shared
3660 * storage. Give concurrent jobs distinct writable resources, such as ring slots.
3661 * Queue saturation throws immediately. Futures report results or exceptions.
3662 * Destroying a future releases its result handle, while the executor retains
3663 * the job until completion. shutdown() drains accepted jobs and joins workers.
3664 * Executor destruction also drains and joins them.
3665 */
3666class executor { // Keep the executor values and operations together.
3667 struct job { // Keep the job values and operations together.
3668 std::function<void()> function; // Keep the application function executed by a CPU worker.
3669 std::promise<void> completion; // Keep the completion result that the caller will receive.
3670 explicit job(const std::function<void()>& fn) : function(fn) { // Keep the accepted CPU function and its promise result.
3671 } // End this scope in async.
3672 }; // End this scope in async.
3673 struct queue_state { // Share the bounded queue between its producer and workers.
3674 std::mutex mutex; // Keep the lock protecting shared state.
3675 std::condition_variable changed; // Wake sleeping workers when work or shutdown state changes.
3676 std::deque<std::shared_ptr<job>> jobs; // Keep accepted CPU work awaiting an available worker.
3677 std::vector<std::thread::id> worker_ids; // Keep the worker thread identifiers used to reject self-joining.
3678 std::size_t pending, capacity; // Keep the current pending count and the maximum queue size.
3679 bool closing; // Keep whether the CPU executor is draining for shutdown.
3680 explicit queue_state(std::size_t n) : pending(0), capacity(n), closing(false) { // Start an empty queue with the chosen pending-job capacity.
3681 } // End this scope in async.
3682 }; // End this scope in async.
3683 std::shared_ptr<queue_state> state_; // Share the bounded queue between the executor and its workers.
3684 std::vector<std::thread> workers_; // Keep the threads that execute accepted CPU jobs.
3685 std::mutex shutdown_mutex_; // Keep the lock that serializes executor shutdown.
3686
3687 static void consume(const std::shared_ptr<queue_state>& state) { // Take accepted jobs from the queue and execute them on this worker.
3688 for (;;) { // Keep this worker available until its queue is drained for shutdown.
3689 std::shared_ptr<job> next; // Keep the CPU job selected by this worker.
3690 { // Begin the protected scope for this operation.
3691 std::unique_lock<std::mutex> lock(state->mutex); // Hold the mutex while this shared state is accessed.
3692 state->changed.wait(lock, [&] { // Release the queue lock while sleeping until work or shutdown arrives.
3693 return state->closing || !state->jobs.empty(); // Wake the worker for a queued job or an explicit shutdown.
3694 }); // End this scope in consume.
3695 if (state->jobs.empty()) // Exit only when shutdown has awakened an empty queue.
3696 return; // Finish this operation.
3697 next = state->jobs.front(); // Set the CPU job selected by this worker.
3698 state->jobs.pop_front(); // Remove this accepted job from the pending queue.
3699 --state->pending; // Release its pending slot before executing the job.
3700 } // End this scope in consume.
3701 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3702 next->function(); // Execute the selected application function or CPU pipeline snapshot.
3703 next->function = std::function<void()>(); // Release kernel and resource captures before publishing completion.
3704 next->completion.set_value(); // Publish successful completion after the job releases its captures.
3705 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3706 const std::exception_ptr failure = std::current_exception(); // Set the exception captured from a CPU job.
3707 next->function = std::function<void()>(); // Release kernel and resource captures before publishing completion.
3708 next->completion.set_exception(failure); // Deliver the worker failure through the caller completion future.
3709 } // End this scope in consume.
3710 } // End this scope in consume.
3711 } // End this scope in consume.
3712 void reserve() { // Reserve capacity and report a full queue immediately.
3713 std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3714 if (state_->closing) // Check the queue state before accepting or executing work.
3715 throw error("CPU executor is shut down"); // Report cpu executor is shut down.
3716 if (state_->pending == state_->capacity) // Check the queue state before accepting or executing work.
3717 throw error("CPU executor queue is full"); // Report cpu executor queue is full.
3718 ++state_->pending; // Count the accepted job against the pending queue capacity.
3719 } // End this scope in reserve.
3720 void abandon() noexcept { // Release the reserved slot after a submission failure.
3721 std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3722 --state_->pending; // Return the queue slot reserved by an unsuccessful submission.
3723 } // End this scope in abandon.
3724 std::future<void> append_reserved(const std::function<void()>& function) { // Attach the accepted CPU job to its reserved queue slot.
3725 std::shared_ptr<job> work(new job(function)); // Keep the application function executed by a CPU worker.
3726 std::future<void> result = work->completion.get_future(); // Set the value returned by this operation.
3727 { // Begin the protected scope for this operation.
3728 std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3729 if (state_->closing) // Check the queue state before accepting or executing work.
3730 throw error("CPU executor is shut down"); // Report cpu executor is shut down.
3731 state_->jobs.push_back(work); // Retain this entry in the ordered resource or work collection.
3732 } // End this scope in append reserved.
3733 state_->changed.notify_one(); // Wake workers so they can observe new queue or shutdown state.
3734 return result; // Return the value returned by this operation.
3735 } // End this scope in append reserved.
3736
3737 public: // Expose the operations callers can use.
3738 /** @brief Start workers with room for at most capacity pending jobs.
3739 * Capacity counts jobs waiting for a worker. Both arguments must be positive.
3740 */
3741 explicit executor(std::size_t workers = 1, std::size_t capacity = 64) // Start a fixed number of workers with a bounded pending-job queue.
3742 : state_(std::make_shared<queue_state>(capacity)) { // Keep the maximum number of pending CPU jobs.
3743 if (!workers || !capacity) // Require positive worker and queue counts.
3744 throw error("CPU executor requires positive worker and queue counts"); // Report cpu executor requires positive worker and queue counts.
3745 workers_.reserve(workers); // Allocate space for every worker thread handle.
3746 state_->worker_ids.reserve(workers); // Allocate space for every worker thread identifier.
3747 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3748 for (std::size_t i = 0; i < workers; ++i) { // Visit this axis of the dispatch or current workgroup.
3749 const std::shared_ptr<queue_state> state = state_; // Set the shared device or worker state.
3750 workers_.push_back(std::thread([state] { // Retain this entry in the ordered resource or work collection.
3751 consume(state); // Take accepted jobs from the queue and execute them on this worker.
3752 })); // End this scope in executor.
3753 state_->worker_ids.push_back(workers_.back().get_id()); // Retain this entry in the ordered resource or work collection.
3754 } // End this scope in executor.
3755 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3756 shutdown(); // Drain accepted CPU work and join the workers from an application thread.
3757 throw; // Rethrow the original failure after arranging the necessary cleanup.
3758 } // End this scope in executor.
3759 } // End this scope in executor.
3760 ~executor() { // Drain accepted work and join the CPU workers at explicit pool teardown.
3761 shutdown(); // Drain accepted CPU work and join the workers from an application thread.
3762 } // End this scope in executor.
3763 executor(const executor&) = delete; // Prevent copying this object and duplicating its retained identity.
3764 executor& operator=(const executor&) = delete; // Prevent copying this object and duplicating its retained identity.
3765 /** @brief Snapshot a host-ready CPU pipeline, enqueue it and return a future.
3766 * Each stage must support CPU execution and have current host data.
3767 */
3768 std::future<void> submit(const pipeline& source) { // Queue compute work and return its completion handle.
3769 reserve(); // Reserve capacity and report a full queue immediately.
3770 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3771 source.require_host_ready(); // Validate CPU stages and host-ready resources before queueing.
3772 const pipeline copy = source.snapshot(); // Capture isolated kernel interfaces and the current bindings and uniforms.
3773 return append_reserved([copy] { // Queue compute work and return its completion handle.
3774 copy.run(); // Execute the retained CPU snapshot on its worker thread.
3775 }); // End this scope in submit.
3776 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3777 abandon(); // Release the reserved slot after a submission failure.
3778 throw; // Rethrow the original failure after arranging the necessary cleanup.
3779 } // End this scope in submit.
3780 } // End this scope in submit.
3781 /** @brief Enqueue an application CPU function on the same bounded queue.
3782 * Run host operations in the callback and keep device operations on their context thread.
3783 */
3784 template <class Function> std::future<void> enqueue(Function function) { // Select the scalar, dimension, or access type at compile time.
3785 reserve(); // Reserve capacity and report a full queue immediately.
3786 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3787 return append_reserved(std::function<void()>(function)); // Queue the application callback on the bounded CPU executor.
3788 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3789 abandon(); // Release the reserved slot after a submission failure.
3790 throw; // Rethrow the original failure after arranging the necessary cleanup.
3791 } // End this scope in enqueue.
3792 } // End this scope in enqueue.
3793 /** @brief Return the count of queued or currently being constructed jobs. */
3794 std::size_t pending() const { // Read the count of jobs waiting for a worker.
3795 std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3796 return state_->pending; // Read the count of jobs waiting for a worker.
3797 } // End this scope in pending.
3798 /** @brief Return the maximum number of pending jobs. */
3799 std::size_t capacity() const { // Return the configured pending-job limit.
3800 return state_->capacity; // Return the configured pending-job limit.
3801 } // End this scope in capacity.
3802 /** @brief Return the number of worker threads. */
3803 std::size_t workers() const { // Return the number of worker threads.
3804 return workers_.size(); // Return the number of worker threads.
3805 } // End this scope in workers.
3806 /** @brief Drain accepted jobs and join all workers. later submissions fail.
3807 * Call from an application thread so it can join every worker.
3808 */
3809 void shutdown() { // Drain accepted CPU work and join the workers from an application thread.
3810 if (std::find(state_->worker_ids.begin(), // Choose this branch when std::find(state ->worker ids.begin(),.
3811 state_->worker_ids.end(), // Keep the end of the current range.
3812 std::this_thread::get_id()) != state_->worker_ids.end()) // Reject joining the current executor worker from its own job.
3813 throw error("CPU executor shutdown requires an application thread"); // Report cpu executor shutdown requires an application thread.
3814 std::lock_guard<std::mutex> lifecycle(shutdown_mutex_); // Hold the mutex while this shared state is accessed.
3815 { // Begin the protected scope for this operation.
3816 std::lock_guard<std::mutex> lock(state_->mutex); // Hold the mutex while this shared state is accessed.
3817 state_->closing = true; // Set whether the CPU executor is draining for shutdown.
3818 } // End this scope in shutdown.
3819 state_->changed.notify_all(); // Wake workers so they can observe new queue or shutdown state.
3820 for (std::size_t i = 0; i < workers_.size(); ++i) // Visit each CPU worker during lifecycle handling.
3821 if (workers_[i].joinable()) // Choose this branch when workers [i].joinable().
3822 workers_[i].join(); // Join this CPU worker after accepted work has drained.
3823 } // End this scope in shutdown.
3824}; // End this scope in async.
3825} // namespace shdr
3826#endif // SHDR_ASYNC_HPP
3827
3828// ---- egl.hpp ----
3829#ifndef SHDR_EGL_HPP // Skip this section if it was already included.
3830#define SHDR_EGL_HPP /* Mark this section as included. */
3831
3832 // Enable this optional backend before including shdr.h and link an EGL library.
3833#if defined(SHDR_ENABLE_EGL) && SHDR_ENABLE_EGL // Compile this branch only when its platform or backend condition holds.
3834#include <EGL/egl.h> // Load the EGL display, context, and surface API.
3835#include <EGL/eglext.h> // Use the available EGL context and platform extensions.
3836
3837namespace shdr { // Group these definitions in the shdr namespace.
3838
3839/** @brief The requested graphics backend or context is unavailable.
3840 * This exception identifies display, configuration, context and GL entry-point
3841 * failures. Shader compilation and dispatch errors remain ordinary shdr::error.
3842 */
3843class backend_unavailable : public error { // Keep the backend unavailable values and operations together.
3844 public: // Expose the operations callers can use.
3845 /** @brief Describe the unavailable graphics infrastructure. */
3846 explicit backend_unavailable(const std::string& message) : error(message) { // Keep the graphics initialization failure as an ordinary exception.
3847 } // End this scope in egl.
3848}; // End this scope in egl.
3849
3850namespace detail { // Group these definitions in the detail namespace.
3851
3852inline backend_unavailable egl_failure(const char* operation) { // Build a readable diagnostic from the EGL error code.
3853 const EGLint code = eglGetError(); // Read the EGL error belonging to the failed context operation.
3854 std::ostringstream message; // Build a readable diagnostic from the EGL error code.
3855 message << operation << " unavailable (EGL error 0x" << std::hex << code << ')'; // Build a readable diagnostic from the EGL error code.
3856 return backend_unavailable(message.str()); // Build a readable diagnostic from the EGL error code.
3857} // End this scope in egl failure.
3858
3859 // Initialization and the last termination share a lock, including during weak-pointer expiry.
3860struct egl_display_registry { // Keep the egl display registry values and operations together.
3861 std::mutex mutex; // Keep the lock protecting shared state.
3862 EGLDisplay display; // Keep the initialized EGL display.
3863 std::size_t owners; // Keep the number of contexts retaining this display.
3864 egl_display_registry() : display(EGL_NO_DISPLAY), owners(0) { // Start the initialized-display owner count at zero.
3865 } // End this scope in egl.
3866}; // End this scope in egl.
3867inline egl_display_registry& egl_displays() { // Share the display-lifetime registry among headless devices.
3868 static egl_display_registry registry; // Keep the shared display lifetime registry.
3869 return registry; // Return the shared display lifetime registry.
3870} // End this scope in egl displays.
3871
3872 // Contexts share one initialized display. the last context releases it.
3873struct egl_display_state { // Keep the egl display state values and operations together.
3874 EGLDisplay display; // Keep the initialized EGL display.
3875 egl_display_state() : display(EGL_NO_DISPLAY) { // Retain one initialized EGL display for living contexts.
3876 egl_display_registry& registry = egl_displays(); // Set the shared display lifetime registry.
3877 std::lock_guard<std::mutex> lock(registry.mutex); // Hold the mutex while this shared state is accessed.
3878 if (registry.owners) { // Reuse this display when another context already retains its initialization.
3879 display = registry.display; // Set the initialized EGL display.
3880 ++registry.owners; // Retain the existing initialized display for this new owner.
3881 return; // Finish this operation.
3882 } // End this scope in egl display state.
3883 typedef EGLDisplay(EGLAPIENTRYP platform_display_fn)(EGLenum, void*, const EGLint*); // Name the representation used by this GL or shader interface.
3884 const platform_display_fn platform_display = // Resolve the optional surfaceless display entry point.
3885 reinterpret_cast<platform_display_fn>(eglGetProcAddress("eglGetPlatformDisplayEXT")); // Look up the requested GL entry point through EGL.
3886 if (platform_display) { // Choose this branch when platform display.
3887 // Mesa's surfaceless platform creates an offscreen display on supported drivers.
3888 display = platform_display(0x31DD, EGL_DEFAULT_DISPLAY, 0); // Set the initialized EGL display.
3889 if (display != EGL_NO_DISPLAY && !eglInitialize(display, 0, 0)) // Prepare the default-display fallback if surfaceless initialization fails.
3890 display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3891 } // End this scope in egl display state.
3892 if (display == EGL_NO_DISPLAY) { // Try the default display after the surfaceless path.
3893 display = eglGetDisplay(EGL_DEFAULT_DISPLAY); // Set the initialized EGL display.
3894 if (display == EGL_NO_DISPLAY || !eglInitialize(display, 0, 0)) { // Report failure to acquire and initialize the default display.
3895 display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3896 throw egl_failure("EGL display"); // Report egl display.
3897 } // End this scope in egl display state.
3898 } // End this scope in egl display state.
3899 registry.display = display; // Set the initialized EGL display.
3900 registry.owners = 1; // Set the number of contexts retaining this display.
3901 } // End this scope in egl display state.
3902 ~egl_display_state() { // Release this object's owned resources at teardown.
3903 egl_display_registry& registry = egl_displays(); // Set the shared display lifetime registry.
3904 std::lock_guard<std::mutex> lock(registry.mutex); // Hold the mutex while this shared state is accessed.
3905 if (display != EGL_NO_DISPLAY && --registry.owners == 0) { // Terminate an initialized display after its final context owner releases it.
3906 eglTerminate(display); // Terminate the display after its last context owner is released.
3907 registry.display = EGL_NO_DISPLAY; // Set the initialized EGL display.
3908 } // End this scope in egl display state.
3909 } // End this scope in egl display state.
3910 egl_display_state(const egl_display_state&) = delete; // Prevent copying this object and duplicating its retained identity.
3911 egl_display_state& operator=(const egl_display_state&) = delete; // Prevent copying this object and duplicating its retained identity.
3912}; // End this scope in egl.
3913
3914inline std::shared_ptr<egl_display_state> acquire_egl_display() { // Reuse the initialized display while any context retains it.
3915 static std::mutex mutex; // Keep the lock protecting shared state.
3916 static std::weak_ptr<egl_display_state> cached; // Keep the weak reference to the shared EGL display.
3917 std::lock_guard<std::mutex> lock(mutex); // Hold the mutex while this shared state is accessed.
3918 std::shared_ptr<egl_display_state> display = cached.lock(); // Set the initialized EGL display.
3919 if (!display) { // Create the shared display state for its first owner.
3920 display = std::make_shared<egl_display_state>(); // Set the initialized EGL display.
3921 cached = display; // Set the weak reference to the shared EGL display.
3922 } // End this scope in acquire egl display.
3923 return display; // Return the initialized EGL display.
3924} // End this scope in acquire egl display.
3925
3926struct egl_context_state { // Retain one headless EGL display, context, and pbuffer.
3927 std::shared_ptr<egl_display_state> display; // Keep the initialized EGL display.
3928 EGLContext context; // Keep the EGL context used for compute commands.
3929 EGLSurface surface; // Keep the one-pixel EGL pbuffer.
3930 EGLenum api; // Keep the selected desktop GL or GLES API.
3931 std::thread::id thread; // Keep the thread that created this EGL context.
3932
3933 explicit egl_context_state(profile p) // Create a pbuffer context for the requested shader profile.
3934 : display(acquire_egl_display()), context(EGL_NO_CONTEXT), surface(EGL_NO_SURFACE), // Reuse the initialized display while any context retains it.
3935 api(p == profile::es31 || p == profile::es32 ? EGL_OPENGL_ES_API : EGL_OPENGL_API), // Choose the EGL client API matching the requested shader profile.
3936 thread(std::this_thread::get_id()) { // Remember the only thread allowed to use this EGL context.
3937 try { // Keep cleanup available if an allocation, shader, or driver operation fails.
3938 const bool desktop = p != profile::es31 && p != profile::es32; // Select the API family for the requested profile.
3939 if (!eglBindAPI(api)) // Check that EGL accepts the selected graphics API.
3940 throw egl_failure("EGL graphics API"); // Report egl graphics api.
3941 const EGLint config_attributes[] = {EGL_SURFACE_TYPE, // Request a pbuffer configuration with the chosen client API.
3942 EGL_PBUFFER_BIT, // Request a configuration capable of creating a small offscreen surface.
3943 EGL_RENDERABLE_TYPE, // Select the client API supported by the framebuffer configuration.
3944 desktop ? EGL_OPENGL_BIT : 0x0040, // Request desktop GL or an OpenGL ES 3-capable configuration.
3945 EGL_RED_SIZE, // Specify the number of red bits in the offscreen surface.
3946 8, // Request eight bits for this color component.
3947 EGL_GREEN_SIZE, // Specify the number of green bits in the offscreen surface.
3948 8, // Request eight bits for this color component.
3949 EGL_BLUE_SIZE, // Specify the number of blue bits in the offscreen surface.
3950 8, // Request eight bits for this color component.
3951 EGL_NONE}; // Create a pbuffer context for the requested shader profile.
3952 EGLConfig config = 0; // Set the selected EGL framebuffer configuration.
3953 EGLint count = 0; // Set the element or configuration count.
3954 if (!eglChooseConfig(display->display, config_attributes, &config, 1, &count) || !count) // Check resource size or driver limits before accessing storage.
3955 throw egl_failure("EGL framebuffer configuration"); // Report egl framebuffer configuration.
3956 const EGLint major = desktop ? 4 : 3; // Set the GL major version.
3957 const EGLint minor = p == profile::es31 ? 1 // Set the GL minor version.
3958 : p == profile::es32 ? 2 // Select the version associated with this shader profile.
3959 : p == profile::gl43 ? 3 // Select the version associated with this shader profile.
3960 : p == profile::gl45 ? 5 // Select the version associated with this shader profile.
3961 : 6; // Select minor version six for the desktop GL 4.6 profile.
3962 // These KHR_create_context attributes are also core in EGL 1.5.
3963 const EGLint desktop_attributes[] = { // Request the selected desktop version and core profile.
3964 0x3098, major, 0x30FB, minor, 0x30FD, 0x00000001, EGL_NONE}; // Create a pbuffer context for the requested shader profile.
3965 const EGLint es_attributes[] = {0x3098, major, 0x30FB, minor, EGL_NONE}; // Request the selected GLES major and minor versions.
3966 context = eglCreateContext(display->display, // Create a compute context for the requested GL or GLES version.
3967 config, // Keep the selected EGL framebuffer configuration.
3968 EGL_NO_CONTEXT, // Create a context with its own GL object namespace.
3969 desktop ? desktop_attributes : es_attributes); // Create a pbuffer context for the requested shader profile.
3970 if (context == EGL_NO_CONTEXT) // Check that the driver created the requested context.
3971 throw egl_failure("Requested GL context"); // Report requested gl context.
3972 const EGLint surface_attributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; // Create a one-pixel offscreen pbuffer for compute commands.
3973 surface = eglCreatePbufferSurface(display->display, config, surface_attributes); // Set the one-pixel EGL pbuffer.
3974 if (surface == EGL_NO_SURFACE) // Check that the driver created the offscreen pbuffer.
3975 throw egl_failure("EGL pbuffer"); // Report egl pbuffer.
3976 make_current(); // Select this context on its creating thread.
3977 } catch (...) { // Preserve cleanup or exception propagation for this failed operation.
3978 release(); // Release this surface and context while preserving other active contexts.
3979 throw; // Rethrow the original failure after arranging the necessary cleanup.
3980 } // End this scope in egl context state.
3981 } // End this scope in egl context state.
3982 void make_current() const { // Select this context on its creating thread.
3983 if (std::this_thread::get_id() != thread) // Check that the operation uses the context or lifecycle thread.
3984 throw error("headless EGL operations require the context's creating thread"); // Report headless egl operations require the context's creating thread.
3985 if (!eglBindAPI(api)) // Check that EGL accepts the selected graphics API.
3986 throw egl_failure("EGL graphics API"); // Report egl graphics api.
3987 if (eglGetCurrentContext() == context && eglGetCurrentDisplay() == display->display) // Choose this branch when eglGetCurrentContext() equals context and eglGetCurrentDisplay() equals display->display.
3988 return; // Finish this operation.
3989 if (!eglMakeCurrent(display->display, surface, surface, context)) // Check that EGL activates this context and its pbuffer.
3990 throw egl_failure("Current EGL context"); // Report current egl context.
3991 } // End this scope in make current.
3992 void release() { // Release this surface and context while preserving other active contexts.
3993 // Unbind this context only when it is current on this thread.
3994 const EGLenum previous_api = eglQueryAPI(); // Set the EGL API current before context release.
3995 eglBindAPI(api); // Select the desktop GL or GLES API for this EGL operation.
3996 if (context != EGL_NO_CONTEXT && eglGetCurrentContext() == context) // Unbind this context when it is current.
3997 eglMakeCurrent(display->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // Make this pbuffer context current on its owning thread.
3998 if (surface != EGL_NO_SURFACE) // Destroy the pbuffer allocated by this state.
3999 eglDestroySurface(display->display, surface); // Release the EGL object after its context-thread owners finish.
4000 if (context != EGL_NO_CONTEXT) // Destroy the context allocated by this state.
4001 eglDestroyContext(display->display, context); // Release the EGL object after its context-thread owners finish.
4002 if (previous_api != api) // Choose this branch when previous api differs from api.
4003 eglBindAPI(previous_api); // Restore the API binding that belonged to the other live context.
4004 surface = EGL_NO_SURFACE; // Set the one-pixel EGL pbuffer.
4005 context = EGL_NO_CONTEXT; // Set the EGL context used for compute commands.
4006 } // End this scope in release.
4007 ~egl_context_state() { // Release this object's owned resources at teardown.
4008 release(); // Release this surface and context while preserving other active contexts.
4009 } // End this scope in egl context state.
4010 egl_context_state(const egl_context_state&) = delete; // Prevent copying this object and duplicating its retained identity.
4011 egl_context_state& operator=(const egl_context_state&) = delete; // Prevent copying this object and duplicating its retained identity.
4012}; // End this scope in egl.
4013
4014inline std::shared_ptr<egl_context_state> make_egl_context(profile p) { // Create and retain the headless EGL context.
4015 return std::make_shared<egl_context_state>(p); // Create and retain the headless EGL context.
4016} // End this scope in make egl context.
4017} // namespace detail
4018
4019/** @brief An optional, headless EGL pbuffer context for a selected compute profile.
4020 * Define SHDR_ENABLE_EGL=1 before including shdr.h and link EGL to use this class.
4021 * It prefers a surfaceless display and otherwise uses EGL's default display.
4022 * Create, use and finally release the context on its creating thread. Displays
4023 * are shared among living shdr contexts. Let shdr manage their display lifetime.
4024 */
4025class headless_context { // Keep the headless context values and operations together.
4026 std::shared_ptr<detail::egl_context_state> context_; // Keep the retained headless context state.
4027
4028 public: // Expose the operations callers can use.
4029 /** @brief Create a 1-by-1 pbuffer and make its context current.
4030 * @param p Minimum GL or GLES version. defaults to OpenGL ES 3.1.
4031 * @throws backend_unavailable If backend initialization fails.
4032 */
4033 explicit headless_context(profile p = profile::es31) : context_(detail::make_egl_context(p)) { // Create and retain an EGL context for the requested compute profile.
4034 } // End this scope in egl.
4035 /** @brief Make this context current on its creating thread. */
4036 void make_current() const { // Select this context on its creating thread.
4037 context_->make_current(); // Select this context on its creating thread.
4038 } // End this scope in make current.
4039 /** @brief Resolve a GL entry point through EGL, for shdr::device or external GL calls. */
4040 static void* resolve(const char* name) { // Resolve a named GL function through EGL.
4041 const __eglMustCastToProperFunctionPointerType function = eglGetProcAddress(name); // Look up the requested GL entry point through EGL.
4042 static_assert(sizeof(function) == sizeof(void*), // Require a representation that matches the shader interface.
4043 "EGL function addresses must fit in void*"); // Require EGL function addresses to fit the portable resolver representation.
4044 void* address = 0; // Set the resolved GL function address.
4045 std::memcpy(&address, &function, sizeof(address)); // Copy the representation with the alias-safe byte-copy operation.
4046 return address; // Return the resolved GL function address.
4047 } // End this scope in resolve.
4048 headless_context(const headless_context&) = delete; // Prevent copying this object and duplicating its retained identity.
4049 headless_context& operator=(const headless_context&) = delete; // Prevent copying this object and duplicating its retained identity.
4050}; // End this scope in egl.
4051
4052/** @brief A compute device that creates and retains its own headless EGL context.
4053 * Define SHDR_ENABLE_EGL=1 and link EGL. Construct this device on the thread that
4054 * performs its GPU operations. Its context remains alive while GPU resources,
4055 * programs and submissions retain the device state. release those objects on
4056 * that thread before shutdown. CPU execution uses host resources.
4057 */
4058class headless_device : public device { // Keep the headless device values and operations together.
4059 std::shared_ptr<detail::egl_context_state> context_; // Keep the retained headless context state.
4060 headless_device(const std::shared_ptr<detail::egl_context_state>& context, profile p) try // Connect the retained EGL context to the GL runtime.
4061 : device(headless_context::resolve, p), context_(context) { // Retain a validated GL device state.
4062 state()->context_keepalive = context; // Set the retained headless context.
4063 state()->activate_context = [context] { // Set the callback that makes this device context current.
4064 context->make_current(); // Select this context on its creating thread.
4065 }; // End this scope in state.
4066 } catch (const backend_unavailable&) { // Clean up objects allocated before the operation failed.
4067 throw; // Rethrow the original failure after arranging the necessary cleanup.
4068 } catch (const error& failure) { // Translate device-initialization failures into an unavailable-backend result.
4069 throw backend_unavailable(failure.what()); // Preserve the initialization diagnostic in the backend exception.
4070 } // End this scope in egl.
4071
4072 public: // Expose the operations callers can use.
4073 /** @brief Create a headless context and initialize its compute device.
4074 * @param p Minimum shader and context profile. defaults to OpenGL ES 3.1.
4075 * @throws backend_unavailable If context creation or entry-point loading fails.
4076 */
4077 explicit headless_device(profile p = profile::es31) // Create a compute device with its own retained EGL context.
4078 : headless_device(detail::make_egl_context(p), p) { // Connect the retained EGL context to the GL runtime.
4079 } // End this scope in headless device.
4080 /** @brief Make the owned context current for external GL interoperability. */
4081 void make_current() const { // Select this context on its creating thread.
4082 context_->make_current(); // Select this context on its creating thread.
4083 } // End this scope in make current.
4084 headless_device(const headless_device&) = delete; // Prevent copying this object and duplicating its retained identity.
4085 headless_device& operator=(const headless_device&) = delete; // Prevent copying this object and duplicating its retained identity.
4086}; // End this scope in egl.
4087
4088} // namespace shdr
4089#endif // SHDR_ENABLE_EGL
4090#endif // SHDR_EGL_HPP
4091
4092// ---- macros.hpp ----
4093#ifndef SHDR_MACROS_HPP // Include these helper macros only once.
4094#define SHDR_MACROS_HPP // Remember that the helper macros are available.
4095
4096/** @brief Begin one shared shader declaration with a fixed local work group size. */
4097#define SHDR_BEGIN(name, x, y, z) /* Start the shared shader type and its CPU snapshot method. */ \
4098 using namespace ::shdr::glsl; /* Make the GLSL math names available inside this shader. */ \
4099 struct name : ::shdr::kernel { /* Give the shared shader the CPU kernel interface. */ \
4100 name() : ::shdr::kernel(#name, ::shdr::extent(x, y, z)) { /* Store the shader name and fixed local work group size. */ \
4101 } /* Close the generated method or shader declaration. */ \
4102 std::unique_ptr<::shdr::kernel> clone() const override { /* Build an independent CPU instance for deferred execution. */ \
4103 std::unique_ptr<name> copy(new name); /* Allocate the shader instance that will hold the snapshot. */ \
4104 copy_interfaces(*copy); /* Copy uniform values and resource bindings into that instance. */ \
4105 return std::unique_ptr<::shdr::kernel>(copy.release()); /* Return ownership through the common kernel interface. */ \
4106 } /* Close the generated method or shader declaration. */
4107/** @brief End a shared shader declaration. */
4108#define SHDR_END() /* Close the shared shader type. */ \
4109 } /* Close the generated method or shader declaration. */ \
4110 ; /* Finish the generated shader type declaration. */
4111/** @brief Declare the shared entry point, executed once per invocation on CPU or GPU. */
4112#define SHDR_MAIN() void main() override // Make the shader entry point override the CPU kernel method.
4113/** @brief Declare a typed std430 SSBO with readonly/writeonly/readwrite access. */
4114#define SHDR_BUFFER(binding, type, name, mode) /* Create a named storage buffer port with the chosen access mode. */ \
4115 ::shdr::buffer_port<type, ::shdr::access::mode> name{*this, binding, #name}; /* Register this typed buffer port with its owning shader. */
4116/** @brief Declare a typed scalar, vector or float matrix uniform. */
4117#define SHDR_UNIFORM(type, name) /* Create a uniform value and its binding descriptor. */ \
4118 type name{}; /* Initialize the uniform value to its default value. */ \
4119 ::shdr::uniform_port<type> shdr_uniform_##name{*this, #name, name}; /* Register the uniform so host code can set it by name. */
4120/** @brief Declare a 2D storage image. Supported formats are r32f/i/ui and rgba32f/i/ui. */
4121#define SHDR_IMAGE2D(binding, format, type, name, mode) /* Choose the matching image scalar type and component count. */ \
4122 SHDR_DETAIL_IMAGE_##type(::shdr::access::mode, SHDR_DETAIL_FORMAT_##format, name, binding) /* Expand the selected image helper with its access and binding. */
4123#define SHDR_DETAIL_IMAGE_image2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4124 ::shdr::image_port<float, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4125#define SHDR_DETAIL_IMAGE_iimage2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4126 ::shdr::image_port<int, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4127#define SHDR_DETAIL_IMAGE_uimage2D(mode, format, name, binding) /* Define the CPU image port for this GLSL image type. */ \
4128 ::shdr::image_port<unsigned, format, mode> name{*this, binding, #name}; /* Register the image port with its owning shader. */
4129#define SHDR_DETAIL_FORMAT_r32f 1 // Use one scalar component for this image format.
4130#define SHDR_DETAIL_FORMAT_r32i 1 // Use one scalar component for this image format.
4131#define SHDR_DETAIL_FORMAT_r32ui 1 // Use one scalar component for this image format.
4132#define SHDR_DETAIL_FORMAT_rgba32f 4 // Use four scalar components for this image format.
4133#define SHDR_DETAIL_FORMAT_rgba32i 4 // Use four scalar components for this image format.
4134#define SHDR_DETAIL_FORMAT_rgba32ui 4 // Use four scalar components for this image format.
4135/** @brief GLSL-style component selection, with safe simultaneous CPU swizzle assignment.
4136 * Use xyzw, rgba or stpq consistently. Duplicate components are read-only.
4137 */
4138#define SHDR_SWIZZLE(value, pattern) (value).template swizzle<SHDR_DETAIL_SWIZZLE_##pattern>() // Translate component letters into a safe CPU component selection.
4139/** @brief Portable spelling of GLSL's boolean vector not builtin. */
4140#define SHDR_NOT(value) ::shdr::glsl::logicalNot(value) // Invert every component of a boolean vector.
4141/** @brief Declare a shared helper function input parameter. */
4142#define SHDR_IN(type, name) const type& name // Pass a helper input through a const reference.
4143/** @brief Declare a shared helper function output parameter. */
4144#define SHDR_OUT(type, name) type& name // Let the helper write its output argument.
4145/** @brief Declare a shared helper function input/output parameter. */
4146#define SHDR_INOUT(type, name) type& name // Let the helper read and update its argument.
4147#define SHDR_DETAIL_SWIZZLE_x 0 // Select the x component.
4148#define SHDR_DETAIL_SWIZZLE_y 1 // Select the y component.
4149#define SHDR_DETAIL_SWIZZLE_z 2 // Select the z component.
4150#define SHDR_DETAIL_SWIZZLE_w 3 // Select the w component.
4151#define SHDR_DETAIL_SWIZZLE_xx 0, 0 // Select x, then x in that order.
4152#define SHDR_DETAIL_SWIZZLE_xy 0, 1 // Select x, then y in that order.
4153#define SHDR_DETAIL_SWIZZLE_xz 0, 2 // Select x, then z in that order.
4154#define SHDR_DETAIL_SWIZZLE_xw 0, 3 // Select x, then w in that order.
4155#define SHDR_DETAIL_SWIZZLE_yx 1, 0 // Select y, then x in that order.
4156#define SHDR_DETAIL_SWIZZLE_yy 1, 1 // Select y, then y in that order.
4157#define SHDR_DETAIL_SWIZZLE_yz 1, 2 // Select y, then z in that order.
4158#define SHDR_DETAIL_SWIZZLE_yw 1, 3 // Select y, then w in that order.
4159#define SHDR_DETAIL_SWIZZLE_zx 2, 0 // Select z, then x in that order.
4160#define SHDR_DETAIL_SWIZZLE_zy 2, 1 // Select z, then y in that order.
4161#define SHDR_DETAIL_SWIZZLE_zz 2, 2 // Select z, then z in that order.
4162#define SHDR_DETAIL_SWIZZLE_zw 2, 3 // Select z, then w in that order.
4163#define SHDR_DETAIL_SWIZZLE_wx 3, 0 // Select w, then x in that order.
4164#define SHDR_DETAIL_SWIZZLE_wy 3, 1 // Select w, then y in that order.
4165#define SHDR_DETAIL_SWIZZLE_wz 3, 2 // Select w, then z in that order.
4166#define SHDR_DETAIL_SWIZZLE_ww 3, 3 // Select w, then w in that order.
4167#define SHDR_DETAIL_SWIZZLE_xxx 0, 0, 0 // Select x, then x, then x in that order.
4168#define SHDR_DETAIL_SWIZZLE_xxy 0, 0, 1 // Select x, then x, then y in that order.
4169#define SHDR_DETAIL_SWIZZLE_xxz 0, 0, 2 // Select x, then x, then z in that order.
4170#define SHDR_DETAIL_SWIZZLE_xxw 0, 0, 3 // Select x, then x, then w in that order.
4171#define SHDR_DETAIL_SWIZZLE_xyx 0, 1, 0 // Select x, then y, then x in that order.
4172#define SHDR_DETAIL_SWIZZLE_xyy 0, 1, 1 // Select x, then y, then y in that order.
4173#define SHDR_DETAIL_SWIZZLE_xyz 0, 1, 2 // Select x, then y, then z in that order.
4174#define SHDR_DETAIL_SWIZZLE_xyw 0, 1, 3 // Select x, then y, then w in that order.
4175#define SHDR_DETAIL_SWIZZLE_xzx 0, 2, 0 // Select x, then z, then x in that order.
4176#define SHDR_DETAIL_SWIZZLE_xzy 0, 2, 1 // Select x, then z, then y in that order.
4177#define SHDR_DETAIL_SWIZZLE_xzz 0, 2, 2 // Select x, then z, then z in that order.
4178#define SHDR_DETAIL_SWIZZLE_xzw 0, 2, 3 // Select x, then z, then w in that order.
4179#define SHDR_DETAIL_SWIZZLE_xwx 0, 3, 0 // Select x, then w, then x in that order.
4180#define SHDR_DETAIL_SWIZZLE_xwy 0, 3, 1 // Select x, then w, then y in that order.
4181#define SHDR_DETAIL_SWIZZLE_xwz 0, 3, 2 // Select x, then w, then z in that order.
4182#define SHDR_DETAIL_SWIZZLE_xww 0, 3, 3 // Select x, then w, then w in that order.
4183#define SHDR_DETAIL_SWIZZLE_yxx 1, 0, 0 // Select y, then x, then x in that order.
4184#define SHDR_DETAIL_SWIZZLE_yxy 1, 0, 1 // Select y, then x, then y in that order.
4185#define SHDR_DETAIL_SWIZZLE_yxz 1, 0, 2 // Select y, then x, then z in that order.
4186#define SHDR_DETAIL_SWIZZLE_yxw 1, 0, 3 // Select y, then x, then w in that order.
4187#define SHDR_DETAIL_SWIZZLE_yyx 1, 1, 0 // Select y, then y, then x in that order.
4188#define SHDR_DETAIL_SWIZZLE_yyy 1, 1, 1 // Select y, then y, then y in that order.
4189#define SHDR_DETAIL_SWIZZLE_yyz 1, 1, 2 // Select y, then y, then z in that order.
4190#define SHDR_DETAIL_SWIZZLE_yyw 1, 1, 3 // Select y, then y, then w in that order.
4191#define SHDR_DETAIL_SWIZZLE_yzx 1, 2, 0 // Select y, then z, then x in that order.
4192#define SHDR_DETAIL_SWIZZLE_yzy 1, 2, 1 // Select y, then z, then y in that order.
4193#define SHDR_DETAIL_SWIZZLE_yzz 1, 2, 2 // Select y, then z, then z in that order.
4194#define SHDR_DETAIL_SWIZZLE_yzw 1, 2, 3 // Select y, then z, then w in that order.
4195#define SHDR_DETAIL_SWIZZLE_ywx 1, 3, 0 // Select y, then w, then x in that order.
4196#define SHDR_DETAIL_SWIZZLE_ywy 1, 3, 1 // Select y, then w, then y in that order.
4197#define SHDR_DETAIL_SWIZZLE_ywz 1, 3, 2 // Select y, then w, then z in that order.
4198#define SHDR_DETAIL_SWIZZLE_yww 1, 3, 3 // Select y, then w, then w in that order.
4199#define SHDR_DETAIL_SWIZZLE_zxx 2, 0, 0 // Select z, then x, then x in that order.
4200#define SHDR_DETAIL_SWIZZLE_zxy 2, 0, 1 // Select z, then x, then y in that order.
4201#define SHDR_DETAIL_SWIZZLE_zxz 2, 0, 2 // Select z, then x, then z in that order.
4202#define SHDR_DETAIL_SWIZZLE_zxw 2, 0, 3 // Select z, then x, then w in that order.
4203#define SHDR_DETAIL_SWIZZLE_zyx 2, 1, 0 // Select z, then y, then x in that order.
4204#define SHDR_DETAIL_SWIZZLE_zyy 2, 1, 1 // Select z, then y, then y in that order.
4205#define SHDR_DETAIL_SWIZZLE_zyz 2, 1, 2 // Select z, then y, then z in that order.
4206#define SHDR_DETAIL_SWIZZLE_zyw 2, 1, 3 // Select z, then y, then w in that order.
4207#define SHDR_DETAIL_SWIZZLE_zzx 2, 2, 0 // Select z, then z, then x in that order.
4208#define SHDR_DETAIL_SWIZZLE_zzy 2, 2, 1 // Select z, then z, then y in that order.
4209#define SHDR_DETAIL_SWIZZLE_zzz 2, 2, 2 // Select z, then z, then z in that order.
4210#define SHDR_DETAIL_SWIZZLE_zzw 2, 2, 3 // Select z, then z, then w in that order.
4211#define SHDR_DETAIL_SWIZZLE_zwx 2, 3, 0 // Select z, then w, then x in that order.
4212#define SHDR_DETAIL_SWIZZLE_zwy 2, 3, 1 // Select z, then w, then y in that order.
4213#define SHDR_DETAIL_SWIZZLE_zwz 2, 3, 2 // Select z, then w, then z in that order.
4214#define SHDR_DETAIL_SWIZZLE_zww 2, 3, 3 // Select z, then w, then w in that order.
4215#define SHDR_DETAIL_SWIZZLE_wxx 3, 0, 0 // Select w, then x, then x in that order.
4216#define SHDR_DETAIL_SWIZZLE_wxy 3, 0, 1 // Select w, then x, then y in that order.
4217#define SHDR_DETAIL_SWIZZLE_wxz 3, 0, 2 // Select w, then x, then z in that order.
4218#define SHDR_DETAIL_SWIZZLE_wxw 3, 0, 3 // Select w, then x, then w in that order.
4219#define SHDR_DETAIL_SWIZZLE_wyx 3, 1, 0 // Select w, then y, then x in that order.
4220#define SHDR_DETAIL_SWIZZLE_wyy 3, 1, 1 // Select w, then y, then y in that order.
4221#define SHDR_DETAIL_SWIZZLE_wyz 3, 1, 2 // Select w, then y, then z in that order.
4222#define SHDR_DETAIL_SWIZZLE_wyw 3, 1, 3 // Select w, then y, then w in that order.
4223#define SHDR_DETAIL_SWIZZLE_wzx 3, 2, 0 // Select w, then z, then x in that order.
4224#define SHDR_DETAIL_SWIZZLE_wzy 3, 2, 1 // Select w, then z, then y in that order.
4225#define SHDR_DETAIL_SWIZZLE_wzz 3, 2, 2 // Select w, then z, then z in that order.
4226#define SHDR_DETAIL_SWIZZLE_wzw 3, 2, 3 // Select w, then z, then w in that order.
4227#define SHDR_DETAIL_SWIZZLE_wwx 3, 3, 0 // Select w, then w, then x in that order.
4228#define SHDR_DETAIL_SWIZZLE_wwy 3, 3, 1 // Select w, then w, then y in that order.
4229#define SHDR_DETAIL_SWIZZLE_wwz 3, 3, 2 // Select w, then w, then z in that order.
4230#define SHDR_DETAIL_SWIZZLE_www 3, 3, 3 // Select w, then w, then w in that order.
4231#define SHDR_DETAIL_SWIZZLE_xxxx 0, 0, 0, 0 // Select x, then x, then x, then x in that order.
4232#define SHDR_DETAIL_SWIZZLE_xxxy 0, 0, 0, 1 // Select x, then x, then x, then y in that order.
4233#define SHDR_DETAIL_SWIZZLE_xxxz 0, 0, 0, 2 // Select x, then x, then x, then z in that order.
4234#define SHDR_DETAIL_SWIZZLE_xxxw 0, 0, 0, 3 // Select x, then x, then x, then w in that order.
4235#define SHDR_DETAIL_SWIZZLE_xxyx 0, 0, 1, 0 // Select x, then x, then y, then x in that order.
4236#define SHDR_DETAIL_SWIZZLE_xxyy 0, 0, 1, 1 // Select x, then x, then y, then y in that order.
4237#define SHDR_DETAIL_SWIZZLE_xxyz 0, 0, 1, 2 // Select x, then x, then y, then z in that order.
4238#define SHDR_DETAIL_SWIZZLE_xxyw 0, 0, 1, 3 // Select x, then x, then y, then w in that order.
4239#define SHDR_DETAIL_SWIZZLE_xxzx 0, 0, 2, 0 // Select x, then x, then z, then x in that order.
4240#define SHDR_DETAIL_SWIZZLE_xxzy 0, 0, 2, 1 // Select x, then x, then z, then y in that order.
4241#define SHDR_DETAIL_SWIZZLE_xxzz 0, 0, 2, 2 // Select x, then x, then z, then z in that order.
4242#define SHDR_DETAIL_SWIZZLE_xxzw 0, 0, 2, 3 // Select x, then x, then z, then w in that order.
4243#define SHDR_DETAIL_SWIZZLE_xxwx 0, 0, 3, 0 // Select x, then x, then w, then x in that order.
4244#define SHDR_DETAIL_SWIZZLE_xxwy 0, 0, 3, 1 // Select x, then x, then w, then y in that order.
4245#define SHDR_DETAIL_SWIZZLE_xxwz 0, 0, 3, 2 // Select x, then x, then w, then z in that order.
4246#define SHDR_DETAIL_SWIZZLE_xxww 0, 0, 3, 3 // Select x, then x, then w, then w in that order.
4247#define SHDR_DETAIL_SWIZZLE_xyxx 0, 1, 0, 0 // Select x, then y, then x, then x in that order.
4248#define SHDR_DETAIL_SWIZZLE_xyxy 0, 1, 0, 1 // Select x, then y, then x, then y in that order.
4249#define SHDR_DETAIL_SWIZZLE_xyxz 0, 1, 0, 2 // Select x, then y, then x, then z in that order.
4250#define SHDR_DETAIL_SWIZZLE_xyxw 0, 1, 0, 3 // Select x, then y, then x, then w in that order.
4251#define SHDR_DETAIL_SWIZZLE_xyyx 0, 1, 1, 0 // Select x, then y, then y, then x in that order.
4252#define SHDR_DETAIL_SWIZZLE_xyyy 0, 1, 1, 1 // Select x, then y, then y, then y in that order.
4253#define SHDR_DETAIL_SWIZZLE_xyyz 0, 1, 1, 2 // Select x, then y, then y, then z in that order.
4254#define SHDR_DETAIL_SWIZZLE_xyyw 0, 1, 1, 3 // Select x, then y, then y, then w in that order.
4255#define SHDR_DETAIL_SWIZZLE_xyzx 0, 1, 2, 0 // Select x, then y, then z, then x in that order.
4256#define SHDR_DETAIL_SWIZZLE_xyzy 0, 1, 2, 1 // Select x, then y, then z, then y in that order.
4257#define SHDR_DETAIL_SWIZZLE_xyzz 0, 1, 2, 2 // Select x, then y, then z, then z in that order.
4258#define SHDR_DETAIL_SWIZZLE_xyzw 0, 1, 2, 3 // Select x, then y, then z, then w in that order.
4259#define SHDR_DETAIL_SWIZZLE_xywx 0, 1, 3, 0 // Select x, then y, then w, then x in that order.
4260#define SHDR_DETAIL_SWIZZLE_xywy 0, 1, 3, 1 // Select x, then y, then w, then y in that order.
4261#define SHDR_DETAIL_SWIZZLE_xywz 0, 1, 3, 2 // Select x, then y, then w, then z in that order.
4262#define SHDR_DETAIL_SWIZZLE_xyww 0, 1, 3, 3 // Select x, then y, then w, then w in that order.
4263#define SHDR_DETAIL_SWIZZLE_xzxx 0, 2, 0, 0 // Select x, then z, then x, then x in that order.
4264#define SHDR_DETAIL_SWIZZLE_xzxy 0, 2, 0, 1 // Select x, then z, then x, then y in that order.
4265#define SHDR_DETAIL_SWIZZLE_xzxz 0, 2, 0, 2 // Select x, then z, then x, then z in that order.
4266#define SHDR_DETAIL_SWIZZLE_xzxw 0, 2, 0, 3 // Select x, then z, then x, then w in that order.
4267#define SHDR_DETAIL_SWIZZLE_xzyx 0, 2, 1, 0 // Select x, then z, then y, then x in that order.
4268#define SHDR_DETAIL_SWIZZLE_xzyy 0, 2, 1, 1 // Select x, then z, then y, then y in that order.
4269#define SHDR_DETAIL_SWIZZLE_xzyz 0, 2, 1, 2 // Select x, then z, then y, then z in that order.
4270#define SHDR_DETAIL_SWIZZLE_xzyw 0, 2, 1, 3 // Select x, then z, then y, then w in that order.
4271#define SHDR_DETAIL_SWIZZLE_xzzx 0, 2, 2, 0 // Select x, then z, then z, then x in that order.
4272#define SHDR_DETAIL_SWIZZLE_xzzy 0, 2, 2, 1 // Select x, then z, then z, then y in that order.
4273#define SHDR_DETAIL_SWIZZLE_xzzz 0, 2, 2, 2 // Select x, then z, then z, then z in that order.
4274#define SHDR_DETAIL_SWIZZLE_xzzw 0, 2, 2, 3 // Select x, then z, then z, then w in that order.
4275#define SHDR_DETAIL_SWIZZLE_xzwx 0, 2, 3, 0 // Select x, then z, then w, then x in that order.
4276#define SHDR_DETAIL_SWIZZLE_xzwy 0, 2, 3, 1 // Select x, then z, then w, then y in that order.
4277#define SHDR_DETAIL_SWIZZLE_xzwz 0, 2, 3, 2 // Select x, then z, then w, then z in that order.
4278#define SHDR_DETAIL_SWIZZLE_xzww 0, 2, 3, 3 // Select x, then z, then w, then w in that order.
4279#define SHDR_DETAIL_SWIZZLE_xwxx 0, 3, 0, 0 // Select x, then w, then x, then x in that order.
4280#define SHDR_DETAIL_SWIZZLE_xwxy 0, 3, 0, 1 // Select x, then w, then x, then y in that order.
4281#define SHDR_DETAIL_SWIZZLE_xwxz 0, 3, 0, 2 // Select x, then w, then x, then z in that order.
4282#define SHDR_DETAIL_SWIZZLE_xwxw 0, 3, 0, 3 // Select x, then w, then x, then w in that order.
4283#define SHDR_DETAIL_SWIZZLE_xwyx 0, 3, 1, 0 // Select x, then w, then y, then x in that order.
4284#define SHDR_DETAIL_SWIZZLE_xwyy 0, 3, 1, 1 // Select x, then w, then y, then y in that order.
4285#define SHDR_DETAIL_SWIZZLE_xwyz 0, 3, 1, 2 // Select x, then w, then y, then z in that order.
4286#define SHDR_DETAIL_SWIZZLE_xwyw 0, 3, 1, 3 // Select x, then w, then y, then w in that order.
4287#define SHDR_DETAIL_SWIZZLE_xwzx 0, 3, 2, 0 // Select x, then w, then z, then x in that order.
4288#define SHDR_DETAIL_SWIZZLE_xwzy 0, 3, 2, 1 // Select x, then w, then z, then y in that order.
4289#define SHDR_DETAIL_SWIZZLE_xwzz 0, 3, 2, 2 // Select x, then w, then z, then z in that order.
4290#define SHDR_DETAIL_SWIZZLE_xwzw 0, 3, 2, 3 // Select x, then w, then z, then w in that order.
4291#define SHDR_DETAIL_SWIZZLE_xwwx 0, 3, 3, 0 // Select x, then w, then w, then x in that order.
4292#define SHDR_DETAIL_SWIZZLE_xwwy 0, 3, 3, 1 // Select x, then w, then w, then y in that order.
4293#define SHDR_DETAIL_SWIZZLE_xwwz 0, 3, 3, 2 // Select x, then w, then w, then z in that order.
4294#define SHDR_DETAIL_SWIZZLE_xwww 0, 3, 3, 3 // Select x, then w, then w, then w in that order.
4295#define SHDR_DETAIL_SWIZZLE_yxxx 1, 0, 0, 0 // Select y, then x, then x, then x in that order.
4296#define SHDR_DETAIL_SWIZZLE_yxxy 1, 0, 0, 1 // Select y, then x, then x, then y in that order.
4297#define SHDR_DETAIL_SWIZZLE_yxxz 1, 0, 0, 2 // Select y, then x, then x, then z in that order.
4298#define SHDR_DETAIL_SWIZZLE_yxxw 1, 0, 0, 3 // Select y, then x, then x, then w in that order.
4299#define SHDR_DETAIL_SWIZZLE_yxyx 1, 0, 1, 0 // Select y, then x, then y, then x in that order.
4300#define SHDR_DETAIL_SWIZZLE_yxyy 1, 0, 1, 1 // Select y, then x, then y, then y in that order.
4301#define SHDR_DETAIL_SWIZZLE_yxyz 1, 0, 1, 2 // Select y, then x, then y, then z in that order.
4302#define SHDR_DETAIL_SWIZZLE_yxyw 1, 0, 1, 3 // Select y, then x, then y, then w in that order.
4303#define SHDR_DETAIL_SWIZZLE_yxzx 1, 0, 2, 0 // Select y, then x, then z, then x in that order.
4304#define SHDR_DETAIL_SWIZZLE_yxzy 1, 0, 2, 1 // Select y, then x, then z, then y in that order.
4305#define SHDR_DETAIL_SWIZZLE_yxzz 1, 0, 2, 2 // Select y, then x, then z, then z in that order.
4306#define SHDR_DETAIL_SWIZZLE_yxzw 1, 0, 2, 3 // Select y, then x, then z, then w in that order.
4307#define SHDR_DETAIL_SWIZZLE_yxwx 1, 0, 3, 0 // Select y, then x, then w, then x in that order.
4308#define SHDR_DETAIL_SWIZZLE_yxwy 1, 0, 3, 1 // Select y, then x, then w, then y in that order.
4309#define SHDR_DETAIL_SWIZZLE_yxwz 1, 0, 3, 2 // Select y, then x, then w, then z in that order.
4310#define SHDR_DETAIL_SWIZZLE_yxww 1, 0, 3, 3 // Select y, then x, then w, then w in that order.
4311#define SHDR_DETAIL_SWIZZLE_yyxx 1, 1, 0, 0 // Select y, then y, then x, then x in that order.
4312#define SHDR_DETAIL_SWIZZLE_yyxy 1, 1, 0, 1 // Select y, then y, then x, then y in that order.
4313#define SHDR_DETAIL_SWIZZLE_yyxz 1, 1, 0, 2 // Select y, then y, then x, then z in that order.
4314#define SHDR_DETAIL_SWIZZLE_yyxw 1, 1, 0, 3 // Select y, then y, then x, then w in that order.
4315#define SHDR_DETAIL_SWIZZLE_yyyx 1, 1, 1, 0 // Select y, then y, then y, then x in that order.
4316#define SHDR_DETAIL_SWIZZLE_yyyy 1, 1, 1, 1 // Select y, then y, then y, then y in that order.
4317#define SHDR_DETAIL_SWIZZLE_yyyz 1, 1, 1, 2 // Select y, then y, then y, then z in that order.
4318#define SHDR_DETAIL_SWIZZLE_yyyw 1, 1, 1, 3 // Select y, then y, then y, then w in that order.
4319#define SHDR_DETAIL_SWIZZLE_yyzx 1, 1, 2, 0 // Select y, then y, then z, then x in that order.
4320#define SHDR_DETAIL_SWIZZLE_yyzy 1, 1, 2, 1 // Select y, then y, then z, then y in that order.
4321#define SHDR_DETAIL_SWIZZLE_yyzz 1, 1, 2, 2 // Select y, then y, then z, then z in that order.
4322#define SHDR_DETAIL_SWIZZLE_yyzw 1, 1, 2, 3 // Select y, then y, then z, then w in that order.
4323#define SHDR_DETAIL_SWIZZLE_yywx 1, 1, 3, 0 // Select y, then y, then w, then x in that order.
4324#define SHDR_DETAIL_SWIZZLE_yywy 1, 1, 3, 1 // Select y, then y, then w, then y in that order.
4325#define SHDR_DETAIL_SWIZZLE_yywz 1, 1, 3, 2 // Select y, then y, then w, then z in that order.
4326#define SHDR_DETAIL_SWIZZLE_yyww 1, 1, 3, 3 // Select y, then y, then w, then w in that order.
4327#define SHDR_DETAIL_SWIZZLE_yzxx 1, 2, 0, 0 // Select y, then z, then x, then x in that order.
4328#define SHDR_DETAIL_SWIZZLE_yzxy 1, 2, 0, 1 // Select y, then z, then x, then y in that order.
4329#define SHDR_DETAIL_SWIZZLE_yzxz 1, 2, 0, 2 // Select y, then z, then x, then z in that order.
4330#define SHDR_DETAIL_SWIZZLE_yzxw 1, 2, 0, 3 // Select y, then z, then x, then w in that order.
4331#define SHDR_DETAIL_SWIZZLE_yzyx 1, 2, 1, 0 // Select y, then z, then y, then x in that order.
4332#define SHDR_DETAIL_SWIZZLE_yzyy 1, 2, 1, 1 // Select y, then z, then y, then y in that order.
4333#define SHDR_DETAIL_SWIZZLE_yzyz 1, 2, 1, 2 // Select y, then z, then y, then z in that order.
4334#define SHDR_DETAIL_SWIZZLE_yzyw 1, 2, 1, 3 // Select y, then z, then y, then w in that order.
4335#define SHDR_DETAIL_SWIZZLE_yzzx 1, 2, 2, 0 // Select y, then z, then z, then x in that order.
4336#define SHDR_DETAIL_SWIZZLE_yzzy 1, 2, 2, 1 // Select y, then z, then z, then y in that order.
4337#define SHDR_DETAIL_SWIZZLE_yzzz 1, 2, 2, 2 // Select y, then z, then z, then z in that order.
4338#define SHDR_DETAIL_SWIZZLE_yzzw 1, 2, 2, 3 // Select y, then z, then z, then w in that order.
4339#define SHDR_DETAIL_SWIZZLE_yzwx 1, 2, 3, 0 // Select y, then z, then w, then x in that order.
4340#define SHDR_DETAIL_SWIZZLE_yzwy 1, 2, 3, 1 // Select y, then z, then w, then y in that order.
4341#define SHDR_DETAIL_SWIZZLE_yzwz 1, 2, 3, 2 // Select y, then z, then w, then z in that order.
4342#define SHDR_DETAIL_SWIZZLE_yzww 1, 2, 3, 3 // Select y, then z, then w, then w in that order.
4343#define SHDR_DETAIL_SWIZZLE_ywxx 1, 3, 0, 0 // Select y, then w, then x, then x in that order.
4344#define SHDR_DETAIL_SWIZZLE_ywxy 1, 3, 0, 1 // Select y, then w, then x, then y in that order.
4345#define SHDR_DETAIL_SWIZZLE_ywxz 1, 3, 0, 2 // Select y, then w, then x, then z in that order.
4346#define SHDR_DETAIL_SWIZZLE_ywxw 1, 3, 0, 3 // Select y, then w, then x, then w in that order.
4347#define SHDR_DETAIL_SWIZZLE_ywyx 1, 3, 1, 0 // Select y, then w, then y, then x in that order.
4348#define SHDR_DETAIL_SWIZZLE_ywyy 1, 3, 1, 1 // Select y, then w, then y, then y in that order.
4349#define SHDR_DETAIL_SWIZZLE_ywyz 1, 3, 1, 2 // Select y, then w, then y, then z in that order.
4350#define SHDR_DETAIL_SWIZZLE_ywyw 1, 3, 1, 3 // Select y, then w, then y, then w in that order.
4351#define SHDR_DETAIL_SWIZZLE_ywzx 1, 3, 2, 0 // Select y, then w, then z, then x in that order.
4352#define SHDR_DETAIL_SWIZZLE_ywzy 1, 3, 2, 1 // Select y, then w, then z, then y in that order.
4353#define SHDR_DETAIL_SWIZZLE_ywzz 1, 3, 2, 2 // Select y, then w, then z, then z in that order.
4354#define SHDR_DETAIL_SWIZZLE_ywzw 1, 3, 2, 3 // Select y, then w, then z, then w in that order.
4355#define SHDR_DETAIL_SWIZZLE_ywwx 1, 3, 3, 0 // Select y, then w, then w, then x in that order.
4356#define SHDR_DETAIL_SWIZZLE_ywwy 1, 3, 3, 1 // Select y, then w, then w, then y in that order.
4357#define SHDR_DETAIL_SWIZZLE_ywwz 1, 3, 3, 2 // Select y, then w, then w, then z in that order.
4358#define SHDR_DETAIL_SWIZZLE_ywww 1, 3, 3, 3 // Select y, then w, then w, then w in that order.
4359#define SHDR_DETAIL_SWIZZLE_zxxx 2, 0, 0, 0 // Select z, then x, then x, then x in that order.
4360#define SHDR_DETAIL_SWIZZLE_zxxy 2, 0, 0, 1 // Select z, then x, then x, then y in that order.
4361#define SHDR_DETAIL_SWIZZLE_zxxz 2, 0, 0, 2 // Select z, then x, then x, then z in that order.
4362#define SHDR_DETAIL_SWIZZLE_zxxw 2, 0, 0, 3 // Select z, then x, then x, then w in that order.
4363#define SHDR_DETAIL_SWIZZLE_zxyx 2, 0, 1, 0 // Select z, then x, then y, then x in that order.
4364#define SHDR_DETAIL_SWIZZLE_zxyy 2, 0, 1, 1 // Select z, then x, then y, then y in that order.
4365#define SHDR_DETAIL_SWIZZLE_zxyz 2, 0, 1, 2 // Select z, then x, then y, then z in that order.
4366#define SHDR_DETAIL_SWIZZLE_zxyw 2, 0, 1, 3 // Select z, then x, then y, then w in that order.
4367#define SHDR_DETAIL_SWIZZLE_zxzx 2, 0, 2, 0 // Select z, then x, then z, then x in that order.
4368#define SHDR_DETAIL_SWIZZLE_zxzy 2, 0, 2, 1 // Select z, then x, then z, then y in that order.
4369#define SHDR_DETAIL_SWIZZLE_zxzz 2, 0, 2, 2 // Select z, then x, then z, then z in that order.
4370#define SHDR_DETAIL_SWIZZLE_zxzw 2, 0, 2, 3 // Select z, then x, then z, then w in that order.
4371#define SHDR_DETAIL_SWIZZLE_zxwx 2, 0, 3, 0 // Select z, then x, then w, then x in that order.
4372#define SHDR_DETAIL_SWIZZLE_zxwy 2, 0, 3, 1 // Select z, then x, then w, then y in that order.
4373#define SHDR_DETAIL_SWIZZLE_zxwz 2, 0, 3, 2 // Select z, then x, then w, then z in that order.
4374#define SHDR_DETAIL_SWIZZLE_zxww 2, 0, 3, 3 // Select z, then x, then w, then w in that order.
4375#define SHDR_DETAIL_SWIZZLE_zyxx 2, 1, 0, 0 // Select z, then y, then x, then x in that order.
4376#define SHDR_DETAIL_SWIZZLE_zyxy 2, 1, 0, 1 // Select z, then y, then x, then y in that order.
4377#define SHDR_DETAIL_SWIZZLE_zyxz 2, 1, 0, 2 // Select z, then y, then x, then z in that order.
4378#define SHDR_DETAIL_SWIZZLE_zyxw 2, 1, 0, 3 // Select z, then y, then x, then w in that order.
4379#define SHDR_DETAIL_SWIZZLE_zyyx 2, 1, 1, 0 // Select z, then y, then y, then x in that order.
4380#define SHDR_DETAIL_SWIZZLE_zyyy 2, 1, 1, 1 // Select z, then y, then y, then y in that order.
4381#define SHDR_DETAIL_SWIZZLE_zyyz 2, 1, 1, 2 // Select z, then y, then y, then z in that order.
4382#define SHDR_DETAIL_SWIZZLE_zyyw 2, 1, 1, 3 // Select z, then y, then y, then w in that order.
4383#define SHDR_DETAIL_SWIZZLE_zyzx 2, 1, 2, 0 // Select z, then y, then z, then x in that order.
4384#define SHDR_DETAIL_SWIZZLE_zyzy 2, 1, 2, 1 // Select z, then y, then z, then y in that order.
4385#define SHDR_DETAIL_SWIZZLE_zyzz 2, 1, 2, 2 // Select z, then y, then z, then z in that order.
4386#define SHDR_DETAIL_SWIZZLE_zyzw 2, 1, 2, 3 // Select z, then y, then z, then w in that order.
4387#define SHDR_DETAIL_SWIZZLE_zywx 2, 1, 3, 0 // Select z, then y, then w, then x in that order.
4388#define SHDR_DETAIL_SWIZZLE_zywy 2, 1, 3, 1 // Select z, then y, then w, then y in that order.
4389#define SHDR_DETAIL_SWIZZLE_zywz 2, 1, 3, 2 // Select z, then y, then w, then z in that order.
4390#define SHDR_DETAIL_SWIZZLE_zyww 2, 1, 3, 3 // Select z, then y, then w, then w in that order.
4391#define SHDR_DETAIL_SWIZZLE_zzxx 2, 2, 0, 0 // Select z, then z, then x, then x in that order.
4392#define SHDR_DETAIL_SWIZZLE_zzxy 2, 2, 0, 1 // Select z, then z, then x, then y in that order.
4393#define SHDR_DETAIL_SWIZZLE_zzxz 2, 2, 0, 2 // Select z, then z, then x, then z in that order.
4394#define SHDR_DETAIL_SWIZZLE_zzxw 2, 2, 0, 3 // Select z, then z, then x, then w in that order.
4395#define SHDR_DETAIL_SWIZZLE_zzyx 2, 2, 1, 0 // Select z, then z, then y, then x in that order.
4396#define SHDR_DETAIL_SWIZZLE_zzyy 2, 2, 1, 1 // Select z, then z, then y, then y in that order.
4397#define SHDR_DETAIL_SWIZZLE_zzyz 2, 2, 1, 2 // Select z, then z, then y, then z in that order.
4398#define SHDR_DETAIL_SWIZZLE_zzyw 2, 2, 1, 3 // Select z, then z, then y, then w in that order.
4399#define SHDR_DETAIL_SWIZZLE_zzzx 2, 2, 2, 0 // Select z, then z, then z, then x in that order.
4400#define SHDR_DETAIL_SWIZZLE_zzzy 2, 2, 2, 1 // Select z, then z, then z, then y in that order.
4401#define SHDR_DETAIL_SWIZZLE_zzzz 2, 2, 2, 2 // Select z, then z, then z, then z in that order.
4402#define SHDR_DETAIL_SWIZZLE_zzzw 2, 2, 2, 3 // Select z, then z, then z, then w in that order.
4403#define SHDR_DETAIL_SWIZZLE_zzwx 2, 2, 3, 0 // Select z, then z, then w, then x in that order.
4404#define SHDR_DETAIL_SWIZZLE_zzwy 2, 2, 3, 1 // Select z, then z, then w, then y in that order.
4405#define SHDR_DETAIL_SWIZZLE_zzwz 2, 2, 3, 2 // Select z, then z, then w, then z in that order.
4406#define SHDR_DETAIL_SWIZZLE_zzww 2, 2, 3, 3 // Select z, then z, then w, then w in that order.
4407#define SHDR_DETAIL_SWIZZLE_zwxx 2, 3, 0, 0 // Select z, then w, then x, then x in that order.
4408#define SHDR_DETAIL_SWIZZLE_zwxy 2, 3, 0, 1 // Select z, then w, then x, then y in that order.
4409#define SHDR_DETAIL_SWIZZLE_zwxz 2, 3, 0, 2 // Select z, then w, then x, then z in that order.
4410#define SHDR_DETAIL_SWIZZLE_zwxw 2, 3, 0, 3 // Select z, then w, then x, then w in that order.
4411#define SHDR_DETAIL_SWIZZLE_zwyx 2, 3, 1, 0 // Select z, then w, then y, then x in that order.
4412#define SHDR_DETAIL_SWIZZLE_zwyy 2, 3, 1, 1 // Select z, then w, then y, then y in that order.
4413#define SHDR_DETAIL_SWIZZLE_zwyz 2, 3, 1, 2 // Select z, then w, then y, then z in that order.
4414#define SHDR_DETAIL_SWIZZLE_zwyw 2, 3, 1, 3 // Select z, then w, then y, then w in that order.
4415#define SHDR_DETAIL_SWIZZLE_zwzx 2, 3, 2, 0 // Select z, then w, then z, then x in that order.
4416#define SHDR_DETAIL_SWIZZLE_zwzy 2, 3, 2, 1 // Select z, then w, then z, then y in that order.
4417#define SHDR_DETAIL_SWIZZLE_zwzz 2, 3, 2, 2 // Select z, then w, then z, then z in that order.
4418#define SHDR_DETAIL_SWIZZLE_zwzw 2, 3, 2, 3 // Select z, then w, then z, then w in that order.
4419#define SHDR_DETAIL_SWIZZLE_zwwx 2, 3, 3, 0 // Select z, then w, then w, then x in that order.
4420#define SHDR_DETAIL_SWIZZLE_zwwy 2, 3, 3, 1 // Select z, then w, then w, then y in that order.
4421#define SHDR_DETAIL_SWIZZLE_zwwz 2, 3, 3, 2 // Select z, then w, then w, then z in that order.
4422#define SHDR_DETAIL_SWIZZLE_zwww 2, 3, 3, 3 // Select z, then w, then w, then w in that order.
4423#define SHDR_DETAIL_SWIZZLE_wxxx 3, 0, 0, 0 // Select w, then x, then x, then x in that order.
4424#define SHDR_DETAIL_SWIZZLE_wxxy 3, 0, 0, 1 // Select w, then x, then x, then y in that order.
4425#define SHDR_DETAIL_SWIZZLE_wxxz 3, 0, 0, 2 // Select w, then x, then x, then z in that order.
4426#define SHDR_DETAIL_SWIZZLE_wxxw 3, 0, 0, 3 // Select w, then x, then x, then w in that order.
4427#define SHDR_DETAIL_SWIZZLE_wxyx 3, 0, 1, 0 // Select w, then x, then y, then x in that order.
4428#define SHDR_DETAIL_SWIZZLE_wxyy 3, 0, 1, 1 // Select w, then x, then y, then y in that order.
4429#define SHDR_DETAIL_SWIZZLE_wxyz 3, 0, 1, 2 // Select w, then x, then y, then z in that order.
4430#define SHDR_DETAIL_SWIZZLE_wxyw 3, 0, 1, 3 // Select w, then x, then y, then w in that order.
4431#define SHDR_DETAIL_SWIZZLE_wxzx 3, 0, 2, 0 // Select w, then x, then z, then x in that order.
4432#define SHDR_DETAIL_SWIZZLE_wxzy 3, 0, 2, 1 // Select w, then x, then z, then y in that order.
4433#define SHDR_DETAIL_SWIZZLE_wxzz 3, 0, 2, 2 // Select w, then x, then z, then z in that order.
4434#define SHDR_DETAIL_SWIZZLE_wxzw 3, 0, 2, 3 // Select w, then x, then z, then w in that order.
4435#define SHDR_DETAIL_SWIZZLE_wxwx 3, 0, 3, 0 // Select w, then x, then w, then x in that order.
4436#define SHDR_DETAIL_SWIZZLE_wxwy 3, 0, 3, 1 // Select w, then x, then w, then y in that order.
4437#define SHDR_DETAIL_SWIZZLE_wxwz 3, 0, 3, 2 // Select w, then x, then w, then z in that order.
4438#define SHDR_DETAIL_SWIZZLE_wxww 3, 0, 3, 3 // Select w, then x, then w, then w in that order.
4439#define SHDR_DETAIL_SWIZZLE_wyxx 3, 1, 0, 0 // Select w, then y, then x, then x in that order.
4440#define SHDR_DETAIL_SWIZZLE_wyxy 3, 1, 0, 1 // Select w, then y, then x, then y in that order.
4441#define SHDR_DETAIL_SWIZZLE_wyxz 3, 1, 0, 2 // Select w, then y, then x, then z in that order.
4442#define SHDR_DETAIL_SWIZZLE_wyxw 3, 1, 0, 3 // Select w, then y, then x, then w in that order.
4443#define SHDR_DETAIL_SWIZZLE_wyyx 3, 1, 1, 0 // Select w, then y, then y, then x in that order.
4444#define SHDR_DETAIL_SWIZZLE_wyyy 3, 1, 1, 1 // Select w, then y, then y, then y in that order.
4445#define SHDR_DETAIL_SWIZZLE_wyyz 3, 1, 1, 2 // Select w, then y, then y, then z in that order.
4446#define SHDR_DETAIL_SWIZZLE_wyyw 3, 1, 1, 3 // Select w, then y, then y, then w in that order.
4447#define SHDR_DETAIL_SWIZZLE_wyzx 3, 1, 2, 0 // Select w, then y, then z, then x in that order.
4448#define SHDR_DETAIL_SWIZZLE_wyzy 3, 1, 2, 1 // Select w, then y, then z, then y in that order.
4449#define SHDR_DETAIL_SWIZZLE_wyzz 3, 1, 2, 2 // Select w, then y, then z, then z in that order.
4450#define SHDR_DETAIL_SWIZZLE_wyzw 3, 1, 2, 3 // Select w, then y, then z, then w in that order.
4451#define SHDR_DETAIL_SWIZZLE_wywx 3, 1, 3, 0 // Select w, then y, then w, then x in that order.
4452#define SHDR_DETAIL_SWIZZLE_wywy 3, 1, 3, 1 // Select w, then y, then w, then y in that order.
4453#define SHDR_DETAIL_SWIZZLE_wywz 3, 1, 3, 2 // Select w, then y, then w, then z in that order.
4454#define SHDR_DETAIL_SWIZZLE_wyww 3, 1, 3, 3 // Select w, then y, then w, then w in that order.
4455#define SHDR_DETAIL_SWIZZLE_wzxx 3, 2, 0, 0 // Select w, then z, then x, then x in that order.
4456#define SHDR_DETAIL_SWIZZLE_wzxy 3, 2, 0, 1 // Select w, then z, then x, then y in that order.
4457#define SHDR_DETAIL_SWIZZLE_wzxz 3, 2, 0, 2 // Select w, then z, then x, then z in that order.
4458#define SHDR_DETAIL_SWIZZLE_wzxw 3, 2, 0, 3 // Select w, then z, then x, then w in that order.
4459#define SHDR_DETAIL_SWIZZLE_wzyx 3, 2, 1, 0 // Select w, then z, then y, then x in that order.
4460#define SHDR_DETAIL_SWIZZLE_wzyy 3, 2, 1, 1 // Select w, then z, then y, then y in that order.
4461#define SHDR_DETAIL_SWIZZLE_wzyz 3, 2, 1, 2 // Select w, then z, then y, then z in that order.
4462#define SHDR_DETAIL_SWIZZLE_wzyw 3, 2, 1, 3 // Select w, then z, then y, then w in that order.
4463#define SHDR_DETAIL_SWIZZLE_wzzx 3, 2, 2, 0 // Select w, then z, then z, then x in that order.
4464#define SHDR_DETAIL_SWIZZLE_wzzy 3, 2, 2, 1 // Select w, then z, then z, then y in that order.
4465#define SHDR_DETAIL_SWIZZLE_wzzz 3, 2, 2, 2 // Select w, then z, then z, then z in that order.
4466#define SHDR_DETAIL_SWIZZLE_wzzw 3, 2, 2, 3 // Select w, then z, then z, then w in that order.
4467#define SHDR_DETAIL_SWIZZLE_wzwx 3, 2, 3, 0 // Select w, then z, then w, then x in that order.
4468#define SHDR_DETAIL_SWIZZLE_wzwy 3, 2, 3, 1 // Select w, then z, then w, then y in that order.
4469#define SHDR_DETAIL_SWIZZLE_wzwz 3, 2, 3, 2 // Select w, then z, then w, then z in that order.
4470#define SHDR_DETAIL_SWIZZLE_wzww 3, 2, 3, 3 // Select w, then z, then w, then w in that order.
4471#define SHDR_DETAIL_SWIZZLE_wwxx 3, 3, 0, 0 // Select w, then w, then x, then x in that order.
4472#define SHDR_DETAIL_SWIZZLE_wwxy 3, 3, 0, 1 // Select w, then w, then x, then y in that order.
4473#define SHDR_DETAIL_SWIZZLE_wwxz 3, 3, 0, 2 // Select w, then w, then x, then z in that order.
4474#define SHDR_DETAIL_SWIZZLE_wwxw 3, 3, 0, 3 // Select w, then w, then x, then w in that order.
4475#define SHDR_DETAIL_SWIZZLE_wwyx 3, 3, 1, 0 // Select w, then w, then y, then x in that order.
4476#define SHDR_DETAIL_SWIZZLE_wwyy 3, 3, 1, 1 // Select w, then w, then y, then y in that order.
4477#define SHDR_DETAIL_SWIZZLE_wwyz 3, 3, 1, 2 // Select w, then w, then y, then z in that order.
4478#define SHDR_DETAIL_SWIZZLE_wwyw 3, 3, 1, 3 // Select w, then w, then y, then w in that order.
4479#define SHDR_DETAIL_SWIZZLE_wwzx 3, 3, 2, 0 // Select w, then w, then z, then x in that order.
4480#define SHDR_DETAIL_SWIZZLE_wwzy 3, 3, 2, 1 // Select w, then w, then z, then y in that order.
4481#define SHDR_DETAIL_SWIZZLE_wwzz 3, 3, 2, 2 // Select w, then w, then z, then z in that order.
4482#define SHDR_DETAIL_SWIZZLE_wwzw 3, 3, 2, 3 // Select w, then w, then z, then w in that order.
4483#define SHDR_DETAIL_SWIZZLE_wwwx 3, 3, 3, 0 // Select w, then w, then w, then x in that order.
4484#define SHDR_DETAIL_SWIZZLE_wwwy 3, 3, 3, 1 // Select w, then w, then w, then y in that order.
4485#define SHDR_DETAIL_SWIZZLE_wwwz 3, 3, 3, 2 // Select w, then w, then w, then z in that order.
4486#define SHDR_DETAIL_SWIZZLE_wwww 3, 3, 3, 3 // Select w, then w, then w, then w in that order.
4487#define SHDR_DETAIL_SWIZZLE_r 0 // Select the r component.
4488#define SHDR_DETAIL_SWIZZLE_g 1 // Select the g component.
4489#define SHDR_DETAIL_SWIZZLE_b 2 // Select the b component.
4490#define SHDR_DETAIL_SWIZZLE_a 3 // Select the a component.
4491#define SHDR_DETAIL_SWIZZLE_rr 0, 0 // Select r, then r in that order.
4492#define SHDR_DETAIL_SWIZZLE_rg 0, 1 // Select r, then g in that order.
4493#define SHDR_DETAIL_SWIZZLE_rb 0, 2 // Select r, then b in that order.
4494#define SHDR_DETAIL_SWIZZLE_ra 0, 3 // Select r, then a in that order.
4495#define SHDR_DETAIL_SWIZZLE_gr 1, 0 // Select g, then r in that order.
4496#define SHDR_DETAIL_SWIZZLE_gg 1, 1 // Select g, then g in that order.
4497#define SHDR_DETAIL_SWIZZLE_gb 1, 2 // Select g, then b in that order.
4498#define SHDR_DETAIL_SWIZZLE_ga 1, 3 // Select g, then a in that order.
4499#define SHDR_DETAIL_SWIZZLE_br 2, 0 // Select b, then r in that order.
4500#define SHDR_DETAIL_SWIZZLE_bg 2, 1 // Select b, then g in that order.
4501#define SHDR_DETAIL_SWIZZLE_bb 2, 2 // Select b, then b in that order.
4502#define SHDR_DETAIL_SWIZZLE_ba 2, 3 // Select b, then a in that order.
4503#define SHDR_DETAIL_SWIZZLE_ar 3, 0 // Select a, then r in that order.
4504#define SHDR_DETAIL_SWIZZLE_ag 3, 1 // Select a, then g in that order.
4505#define SHDR_DETAIL_SWIZZLE_ab 3, 2 // Select a, then b in that order.
4506#define SHDR_DETAIL_SWIZZLE_aa 3, 3 // Select a, then a in that order.
4507#define SHDR_DETAIL_SWIZZLE_rrr 0, 0, 0 // Select r, then r, then r in that order.
4508#define SHDR_DETAIL_SWIZZLE_rrg 0, 0, 1 // Select r, then r, then g in that order.
4509#define SHDR_DETAIL_SWIZZLE_rrb 0, 0, 2 // Select r, then r, then b in that order.
4510#define SHDR_DETAIL_SWIZZLE_rra 0, 0, 3 // Select r, then r, then a in that order.
4511#define SHDR_DETAIL_SWIZZLE_rgr 0, 1, 0 // Select r, then g, then r in that order.
4512#define SHDR_DETAIL_SWIZZLE_rgg 0, 1, 1 // Select r, then g, then g in that order.
4513#define SHDR_DETAIL_SWIZZLE_rgb 0, 1, 2 // Select r, then g, then b in that order.
4514#define SHDR_DETAIL_SWIZZLE_rga 0, 1, 3 // Select r, then g, then a in that order.
4515#define SHDR_DETAIL_SWIZZLE_rbr 0, 2, 0 // Select r, then b, then r in that order.
4516#define SHDR_DETAIL_SWIZZLE_rbg 0, 2, 1 // Select r, then b, then g in that order.
4517#define SHDR_DETAIL_SWIZZLE_rbb 0, 2, 2 // Select r, then b, then b in that order.
4518#define SHDR_DETAIL_SWIZZLE_rba 0, 2, 3 // Select r, then b, then a in that order.
4519#define SHDR_DETAIL_SWIZZLE_rar 0, 3, 0 // Select r, then a, then r in that order.
4520#define SHDR_DETAIL_SWIZZLE_rag 0, 3, 1 // Select r, then a, then g in that order.
4521#define SHDR_DETAIL_SWIZZLE_rab 0, 3, 2 // Select r, then a, then b in that order.
4522#define SHDR_DETAIL_SWIZZLE_raa 0, 3, 3 // Select r, then a, then a in that order.
4523#define SHDR_DETAIL_SWIZZLE_grr 1, 0, 0 // Select g, then r, then r in that order.
4524#define SHDR_DETAIL_SWIZZLE_grg 1, 0, 1 // Select g, then r, then g in that order.
4525#define SHDR_DETAIL_SWIZZLE_grb 1, 0, 2 // Select g, then r, then b in that order.
4526#define SHDR_DETAIL_SWIZZLE_gra 1, 0, 3 // Select g, then r, then a in that order.
4527#define SHDR_DETAIL_SWIZZLE_ggr 1, 1, 0 // Select g, then g, then r in that order.
4528#define SHDR_DETAIL_SWIZZLE_ggg 1, 1, 1 // Select g, then g, then g in that order.
4529#define SHDR_DETAIL_SWIZZLE_ggb 1, 1, 2 // Select g, then g, then b in that order.
4530#define SHDR_DETAIL_SWIZZLE_gga 1, 1, 3 // Select g, then g, then a in that order.
4531#define SHDR_DETAIL_SWIZZLE_gbr 1, 2, 0 // Select g, then b, then r in that order.
4532#define SHDR_DETAIL_SWIZZLE_gbg 1, 2, 1 // Select g, then b, then g in that order.
4533#define SHDR_DETAIL_SWIZZLE_gbb 1, 2, 2 // Select g, then b, then b in that order.
4534#define SHDR_DETAIL_SWIZZLE_gba 1, 2, 3 // Select g, then b, then a in that order.
4535#define SHDR_DETAIL_SWIZZLE_gar 1, 3, 0 // Select g, then a, then r in that order.
4536#define SHDR_DETAIL_SWIZZLE_gag 1, 3, 1 // Select g, then a, then g in that order.
4537#define SHDR_DETAIL_SWIZZLE_gab 1, 3, 2 // Select g, then a, then b in that order.
4538#define SHDR_DETAIL_SWIZZLE_gaa 1, 3, 3 // Select g, then a, then a in that order.
4539#define SHDR_DETAIL_SWIZZLE_brr 2, 0, 0 // Select b, then r, then r in that order.
4540#define SHDR_DETAIL_SWIZZLE_brg 2, 0, 1 // Select b, then r, then g in that order.
4541#define SHDR_DETAIL_SWIZZLE_brb 2, 0, 2 // Select b, then r, then b in that order.
4542#define SHDR_DETAIL_SWIZZLE_bra 2, 0, 3 // Select b, then r, then a in that order.
4543#define SHDR_DETAIL_SWIZZLE_bgr 2, 1, 0 // Select b, then g, then r in that order.
4544#define SHDR_DETAIL_SWIZZLE_bgg 2, 1, 1 // Select b, then g, then g in that order.
4545#define SHDR_DETAIL_SWIZZLE_bgb 2, 1, 2 // Select b, then g, then b in that order.
4546#define SHDR_DETAIL_SWIZZLE_bga 2, 1, 3 // Select b, then g, then a in that order.
4547#define SHDR_DETAIL_SWIZZLE_bbr 2, 2, 0 // Select b, then b, then r in that order.
4548#define SHDR_DETAIL_SWIZZLE_bbg 2, 2, 1 // Select b, then b, then g in that order.
4549#define SHDR_DETAIL_SWIZZLE_bbb 2, 2, 2 // Select b, then b, then b in that order.
4550#define SHDR_DETAIL_SWIZZLE_bba 2, 2, 3 // Select b, then b, then a in that order.
4551#define SHDR_DETAIL_SWIZZLE_bar 2, 3, 0 // Select b, then a, then r in that order.
4552#define SHDR_DETAIL_SWIZZLE_bag 2, 3, 1 // Select b, then a, then g in that order.
4553#define SHDR_DETAIL_SWIZZLE_bab 2, 3, 2 // Select b, then a, then b in that order.
4554#define SHDR_DETAIL_SWIZZLE_baa 2, 3, 3 // Select b, then a, then a in that order.
4555#define SHDR_DETAIL_SWIZZLE_arr 3, 0, 0 // Select a, then r, then r in that order.
4556#define SHDR_DETAIL_SWIZZLE_arg 3, 0, 1 // Select a, then r, then g in that order.
4557#define SHDR_DETAIL_SWIZZLE_arb 3, 0, 2 // Select a, then r, then b in that order.
4558#define SHDR_DETAIL_SWIZZLE_ara 3, 0, 3 // Select a, then r, then a in that order.
4559#define SHDR_DETAIL_SWIZZLE_agr 3, 1, 0 // Select a, then g, then r in that order.
4560#define SHDR_DETAIL_SWIZZLE_agg 3, 1, 1 // Select a, then g, then g in that order.
4561#define SHDR_DETAIL_SWIZZLE_agb 3, 1, 2 // Select a, then g, then b in that order.
4562#define SHDR_DETAIL_SWIZZLE_aga 3, 1, 3 // Select a, then g, then a in that order.
4563#define SHDR_DETAIL_SWIZZLE_abr 3, 2, 0 // Select a, then b, then r in that order.
4564#define SHDR_DETAIL_SWIZZLE_abg 3, 2, 1 // Select a, then b, then g in that order.
4565#define SHDR_DETAIL_SWIZZLE_abb 3, 2, 2 // Select a, then b, then b in that order.
4566#define SHDR_DETAIL_SWIZZLE_aba 3, 2, 3 // Select a, then b, then a in that order.
4567#define SHDR_DETAIL_SWIZZLE_aar 3, 3, 0 // Select a, then a, then r in that order.
4568#define SHDR_DETAIL_SWIZZLE_aag 3, 3, 1 // Select a, then a, then g in that order.
4569#define SHDR_DETAIL_SWIZZLE_aab 3, 3, 2 // Select a, then a, then b in that order.
4570#define SHDR_DETAIL_SWIZZLE_aaa 3, 3, 3 // Select a, then a, then a in that order.
4571#define SHDR_DETAIL_SWIZZLE_rrrr 0, 0, 0, 0 // Select r, then r, then r, then r in that order.
4572#define SHDR_DETAIL_SWIZZLE_rrrg 0, 0, 0, 1 // Select r, then r, then r, then g in that order.
4573#define SHDR_DETAIL_SWIZZLE_rrrb 0, 0, 0, 2 // Select r, then r, then r, then b in that order.
4574#define SHDR_DETAIL_SWIZZLE_rrra 0, 0, 0, 3 // Select r, then r, then r, then a in that order.
4575#define SHDR_DETAIL_SWIZZLE_rrgr 0, 0, 1, 0 // Select r, then r, then g, then r in that order.
4576#define SHDR_DETAIL_SWIZZLE_rrgg 0, 0, 1, 1 // Select r, then r, then g, then g in that order.
4577#define SHDR_DETAIL_SWIZZLE_rrgb 0, 0, 1, 2 // Select r, then r, then g, then b in that order.
4578#define SHDR_DETAIL_SWIZZLE_rrga 0, 0, 1, 3 // Select r, then r, then g, then a in that order.
4579#define SHDR_DETAIL_SWIZZLE_rrbr 0, 0, 2, 0 // Select r, then r, then b, then r in that order.
4580#define SHDR_DETAIL_SWIZZLE_rrbg 0, 0, 2, 1 // Select r, then r, then b, then g in that order.
4581#define SHDR_DETAIL_SWIZZLE_rrbb 0, 0, 2, 2 // Select r, then r, then b, then b in that order.
4582#define SHDR_DETAIL_SWIZZLE_rrba 0, 0, 2, 3 // Select r, then r, then b, then a in that order.
4583#define SHDR_DETAIL_SWIZZLE_rrar 0, 0, 3, 0 // Select r, then r, then a, then r in that order.
4584#define SHDR_DETAIL_SWIZZLE_rrag 0, 0, 3, 1 // Select r, then r, then a, then g in that order.
4585#define SHDR_DETAIL_SWIZZLE_rrab 0, 0, 3, 2 // Select r, then r, then a, then b in that order.
4586#define SHDR_DETAIL_SWIZZLE_rraa 0, 0, 3, 3 // Select r, then r, then a, then a in that order.
4587#define SHDR_DETAIL_SWIZZLE_rgrr 0, 1, 0, 0 // Select r, then g, then r, then r in that order.
4588#define SHDR_DETAIL_SWIZZLE_rgrg 0, 1, 0, 1 // Select r, then g, then r, then g in that order.
4589#define SHDR_DETAIL_SWIZZLE_rgrb 0, 1, 0, 2 // Select r, then g, then r, then b in that order.
4590#define SHDR_DETAIL_SWIZZLE_rgra 0, 1, 0, 3 // Select r, then g, then r, then a in that order.
4591#define SHDR_DETAIL_SWIZZLE_rggr 0, 1, 1, 0 // Select r, then g, then g, then r in that order.
4592#define SHDR_DETAIL_SWIZZLE_rggg 0, 1, 1, 1 // Select r, then g, then g, then g in that order.
4593#define SHDR_DETAIL_SWIZZLE_rggb 0, 1, 1, 2 // Select r, then g, then g, then b in that order.
4594#define SHDR_DETAIL_SWIZZLE_rgga 0, 1, 1, 3 // Select r, then g, then g, then a in that order.
4595#define SHDR_DETAIL_SWIZZLE_rgbr 0, 1, 2, 0 // Select r, then g, then b, then r in that order.
4596#define SHDR_DETAIL_SWIZZLE_rgbg 0, 1, 2, 1 // Select r, then g, then b, then g in that order.
4597#define SHDR_DETAIL_SWIZZLE_rgbb 0, 1, 2, 2 // Select r, then g, then b, then b in that order.
4598#define SHDR_DETAIL_SWIZZLE_rgba 0, 1, 2, 3 // Select r, then g, then b, then a in that order.
4599#define SHDR_DETAIL_SWIZZLE_rgar 0, 1, 3, 0 // Select r, then g, then a, then r in that order.
4600#define SHDR_DETAIL_SWIZZLE_rgag 0, 1, 3, 1 // Select r, then g, then a, then g in that order.
4601#define SHDR_DETAIL_SWIZZLE_rgab 0, 1, 3, 2 // Select r, then g, then a, then b in that order.
4602#define SHDR_DETAIL_SWIZZLE_rgaa 0, 1, 3, 3 // Select r, then g, then a, then a in that order.
4603#define SHDR_DETAIL_SWIZZLE_rbrr 0, 2, 0, 0 // Select r, then b, then r, then r in that order.
4604#define SHDR_DETAIL_SWIZZLE_rbrg 0, 2, 0, 1 // Select r, then b, then r, then g in that order.
4605#define SHDR_DETAIL_SWIZZLE_rbrb 0, 2, 0, 2 // Select r, then b, then r, then b in that order.
4606#define SHDR_DETAIL_SWIZZLE_rbra 0, 2, 0, 3 // Select r, then b, then r, then a in that order.
4607#define SHDR_DETAIL_SWIZZLE_rbgr 0, 2, 1, 0 // Select r, then b, then g, then r in that order.
4608#define SHDR_DETAIL_SWIZZLE_rbgg 0, 2, 1, 1 // Select r, then b, then g, then g in that order.
4609#define SHDR_DETAIL_SWIZZLE_rbgb 0, 2, 1, 2 // Select r, then b, then g, then b in that order.
4610#define SHDR_DETAIL_SWIZZLE_rbga 0, 2, 1, 3 // Select r, then b, then g, then a in that order.
4611#define SHDR_DETAIL_SWIZZLE_rbbr 0, 2, 2, 0 // Select r, then b, then b, then r in that order.
4612#define SHDR_DETAIL_SWIZZLE_rbbg 0, 2, 2, 1 // Select r, then b, then b, then g in that order.
4613#define SHDR_DETAIL_SWIZZLE_rbbb 0, 2, 2, 2 // Select r, then b, then b, then b in that order.
4614#define SHDR_DETAIL_SWIZZLE_rbba 0, 2, 2, 3 // Select r, then b, then b, then a in that order.
4615#define SHDR_DETAIL_SWIZZLE_rbar 0, 2, 3, 0 // Select r, then b, then a, then r in that order.
4616#define SHDR_DETAIL_SWIZZLE_rbag 0, 2, 3, 1 // Select r, then b, then a, then g in that order.
4617#define SHDR_DETAIL_SWIZZLE_rbab 0, 2, 3, 2 // Select r, then b, then a, then b in that order.
4618#define SHDR_DETAIL_SWIZZLE_rbaa 0, 2, 3, 3 // Select r, then b, then a, then a in that order.
4619#define SHDR_DETAIL_SWIZZLE_rarr 0, 3, 0, 0 // Select r, then a, then r, then r in that order.
4620#define SHDR_DETAIL_SWIZZLE_rarg 0, 3, 0, 1 // Select r, then a, then r, then g in that order.
4621#define SHDR_DETAIL_SWIZZLE_rarb 0, 3, 0, 2 // Select r, then a, then r, then b in that order.
4622#define SHDR_DETAIL_SWIZZLE_rara 0, 3, 0, 3 // Select r, then a, then r, then a in that order.
4623#define SHDR_DETAIL_SWIZZLE_ragr 0, 3, 1, 0 // Select r, then a, then g, then r in that order.
4624#define SHDR_DETAIL_SWIZZLE_ragg 0, 3, 1, 1 // Select r, then a, then g, then g in that order.
4625#define SHDR_DETAIL_SWIZZLE_ragb 0, 3, 1, 2 // Select r, then a, then g, then b in that order.
4626#define SHDR_DETAIL_SWIZZLE_raga 0, 3, 1, 3 // Select r, then a, then g, then a in that order.
4627#define SHDR_DETAIL_SWIZZLE_rabr 0, 3, 2, 0 // Select r, then a, then b, then r in that order.
4628#define SHDR_DETAIL_SWIZZLE_rabg 0, 3, 2, 1 // Select r, then a, then b, then g in that order.
4629#define SHDR_DETAIL_SWIZZLE_rabb 0, 3, 2, 2 // Select r, then a, then b, then b in that order.
4630#define SHDR_DETAIL_SWIZZLE_raba 0, 3, 2, 3 // Select r, then a, then b, then a in that order.
4631#define SHDR_DETAIL_SWIZZLE_raar 0, 3, 3, 0 // Select r, then a, then a, then r in that order.
4632#define SHDR_DETAIL_SWIZZLE_raag 0, 3, 3, 1 // Select r, then a, then a, then g in that order.
4633#define SHDR_DETAIL_SWIZZLE_raab 0, 3, 3, 2 // Select r, then a, then a, then b in that order.
4634#define SHDR_DETAIL_SWIZZLE_raaa 0, 3, 3, 3 // Select r, then a, then a, then a in that order.
4635#define SHDR_DETAIL_SWIZZLE_grrr 1, 0, 0, 0 // Select g, then r, then r, then r in that order.
4636#define SHDR_DETAIL_SWIZZLE_grrg 1, 0, 0, 1 // Select g, then r, then r, then g in that order.
4637#define SHDR_DETAIL_SWIZZLE_grrb 1, 0, 0, 2 // Select g, then r, then r, then b in that order.
4638#define SHDR_DETAIL_SWIZZLE_grra 1, 0, 0, 3 // Select g, then r, then r, then a in that order.
4639#define SHDR_DETAIL_SWIZZLE_grgr 1, 0, 1, 0 // Select g, then r, then g, then r in that order.
4640#define SHDR_DETAIL_SWIZZLE_grgg 1, 0, 1, 1 // Select g, then r, then g, then g in that order.
4641#define SHDR_DETAIL_SWIZZLE_grgb 1, 0, 1, 2 // Select g, then r, then g, then b in that order.
4642#define SHDR_DETAIL_SWIZZLE_grga 1, 0, 1, 3 // Select g, then r, then g, then a in that order.
4643#define SHDR_DETAIL_SWIZZLE_grbr 1, 0, 2, 0 // Select g, then r, then b, then r in that order.
4644#define SHDR_DETAIL_SWIZZLE_grbg 1, 0, 2, 1 // Select g, then r, then b, then g in that order.
4645#define SHDR_DETAIL_SWIZZLE_grbb 1, 0, 2, 2 // Select g, then r, then b, then b in that order.
4646#define SHDR_DETAIL_SWIZZLE_grba 1, 0, 2, 3 // Select g, then r, then b, then a in that order.
4647#define SHDR_DETAIL_SWIZZLE_grar 1, 0, 3, 0 // Select g, then r, then a, then r in that order.
4648#define SHDR_DETAIL_SWIZZLE_grag 1, 0, 3, 1 // Select g, then r, then a, then g in that order.
4649#define SHDR_DETAIL_SWIZZLE_grab 1, 0, 3, 2 // Select g, then r, then a, then b in that order.
4650#define SHDR_DETAIL_SWIZZLE_graa 1, 0, 3, 3 // Select g, then r, then a, then a in that order.
4651#define SHDR_DETAIL_SWIZZLE_ggrr 1, 1, 0, 0 // Select g, then g, then r, then r in that order.
4652#define SHDR_DETAIL_SWIZZLE_ggrg 1, 1, 0, 1 // Select g, then g, then r, then g in that order.
4653#define SHDR_DETAIL_SWIZZLE_ggrb 1, 1, 0, 2 // Select g, then g, then r, then b in that order.
4654#define SHDR_DETAIL_SWIZZLE_ggra 1, 1, 0, 3 // Select g, then g, then r, then a in that order.
4655#define SHDR_DETAIL_SWIZZLE_gggr 1, 1, 1, 0 // Select g, then g, then g, then r in that order.
4656#define SHDR_DETAIL_SWIZZLE_gggg 1, 1, 1, 1 // Select g, then g, then g, then g in that order.
4657#define SHDR_DETAIL_SWIZZLE_gggb 1, 1, 1, 2 // Select g, then g, then g, then b in that order.
4658#define SHDR_DETAIL_SWIZZLE_ggga 1, 1, 1, 3 // Select g, then g, then g, then a in that order.
4659#define SHDR_DETAIL_SWIZZLE_ggbr 1, 1, 2, 0 // Select g, then g, then b, then r in that order.
4660#define SHDR_DETAIL_SWIZZLE_ggbg 1, 1, 2, 1 // Select g, then g, then b, then g in that order.
4661#define SHDR_DETAIL_SWIZZLE_ggbb 1, 1, 2, 2 // Select g, then g, then b, then b in that order.
4662#define SHDR_DETAIL_SWIZZLE_ggba 1, 1, 2, 3 // Select g, then g, then b, then a in that order.
4663#define SHDR_DETAIL_SWIZZLE_ggar 1, 1, 3, 0 // Select g, then g, then a, then r in that order.
4664#define SHDR_DETAIL_SWIZZLE_ggag 1, 1, 3, 1 // Select g, then g, then a, then g in that order.
4665#define SHDR_DETAIL_SWIZZLE_ggab 1, 1, 3, 2 // Select g, then g, then a, then b in that order.
4666#define SHDR_DETAIL_SWIZZLE_ggaa 1, 1, 3, 3 // Select g, then g, then a, then a in that order.
4667#define SHDR_DETAIL_SWIZZLE_gbrr 1, 2, 0, 0 // Select g, then b, then r, then r in that order.
4668#define SHDR_DETAIL_SWIZZLE_gbrg 1, 2, 0, 1 // Select g, then b, then r, then g in that order.
4669#define SHDR_DETAIL_SWIZZLE_gbrb 1, 2, 0, 2 // Select g, then b, then r, then b in that order.
4670#define SHDR_DETAIL_SWIZZLE_gbra 1, 2, 0, 3 // Select g, then b, then r, then a in that order.
4671#define SHDR_DETAIL_SWIZZLE_gbgr 1, 2, 1, 0 // Select g, then b, then g, then r in that order.
4672#define SHDR_DETAIL_SWIZZLE_gbgg 1, 2, 1, 1 // Select g, then b, then g, then g in that order.
4673#define SHDR_DETAIL_SWIZZLE_gbgb 1, 2, 1, 2 // Select g, then b, then g, then b in that order.
4674#define SHDR_DETAIL_SWIZZLE_gbga 1, 2, 1, 3 // Select g, then b, then g, then a in that order.
4675#define SHDR_DETAIL_SWIZZLE_gbbr 1, 2, 2, 0 // Select g, then b, then b, then r in that order.
4676#define SHDR_DETAIL_SWIZZLE_gbbg 1, 2, 2, 1 // Select g, then b, then b, then g in that order.
4677#define SHDR_DETAIL_SWIZZLE_gbbb 1, 2, 2, 2 // Select g, then b, then b, then b in that order.
4678#define SHDR_DETAIL_SWIZZLE_gbba 1, 2, 2, 3 // Select g, then b, then b, then a in that order.
4679#define SHDR_DETAIL_SWIZZLE_gbar 1, 2, 3, 0 // Select g, then b, then a, then r in that order.
4680#define SHDR_DETAIL_SWIZZLE_gbag 1, 2, 3, 1 // Select g, then b, then a, then g in that order.
4681#define SHDR_DETAIL_SWIZZLE_gbab 1, 2, 3, 2 // Select g, then b, then a, then b in that order.
4682#define SHDR_DETAIL_SWIZZLE_gbaa 1, 2, 3, 3 // Select g, then b, then a, then a in that order.
4683#define SHDR_DETAIL_SWIZZLE_garr 1, 3, 0, 0 // Select g, then a, then r, then r in that order.
4684#define SHDR_DETAIL_SWIZZLE_garg 1, 3, 0, 1 // Select g, then a, then r, then g in that order.
4685#define SHDR_DETAIL_SWIZZLE_garb 1, 3, 0, 2 // Select g, then a, then r, then b in that order.
4686#define SHDR_DETAIL_SWIZZLE_gara 1, 3, 0, 3 // Select g, then a, then r, then a in that order.
4687#define SHDR_DETAIL_SWIZZLE_gagr 1, 3, 1, 0 // Select g, then a, then g, then r in that order.
4688#define SHDR_DETAIL_SWIZZLE_gagg 1, 3, 1, 1 // Select g, then a, then g, then g in that order.
4689#define SHDR_DETAIL_SWIZZLE_gagb 1, 3, 1, 2 // Select g, then a, then g, then b in that order.
4690#define SHDR_DETAIL_SWIZZLE_gaga 1, 3, 1, 3 // Select g, then a, then g, then a in that order.
4691#define SHDR_DETAIL_SWIZZLE_gabr 1, 3, 2, 0 // Select g, then a, then b, then r in that order.
4692#define SHDR_DETAIL_SWIZZLE_gabg 1, 3, 2, 1 // Select g, then a, then b, then g in that order.
4693#define SHDR_DETAIL_SWIZZLE_gabb 1, 3, 2, 2 // Select g, then a, then b, then b in that order.
4694#define SHDR_DETAIL_SWIZZLE_gaba 1, 3, 2, 3 // Select g, then a, then b, then a in that order.
4695#define SHDR_DETAIL_SWIZZLE_gaar 1, 3, 3, 0 // Select g, then a, then a, then r in that order.
4696#define SHDR_DETAIL_SWIZZLE_gaag 1, 3, 3, 1 // Select g, then a, then a, then g in that order.
4697#define SHDR_DETAIL_SWIZZLE_gaab 1, 3, 3, 2 // Select g, then a, then a, then b in that order.
4698#define SHDR_DETAIL_SWIZZLE_gaaa 1, 3, 3, 3 // Select g, then a, then a, then a in that order.
4699#define SHDR_DETAIL_SWIZZLE_brrr 2, 0, 0, 0 // Select b, then r, then r, then r in that order.
4700#define SHDR_DETAIL_SWIZZLE_brrg 2, 0, 0, 1 // Select b, then r, then r, then g in that order.
4701#define SHDR_DETAIL_SWIZZLE_brrb 2, 0, 0, 2 // Select b, then r, then r, then b in that order.
4702#define SHDR_DETAIL_SWIZZLE_brra 2, 0, 0, 3 // Select b, then r, then r, then a in that order.
4703#define SHDR_DETAIL_SWIZZLE_brgr 2, 0, 1, 0 // Select b, then r, then g, then r in that order.
4704#define SHDR_DETAIL_SWIZZLE_brgg 2, 0, 1, 1 // Select b, then r, then g, then g in that order.
4705#define SHDR_DETAIL_SWIZZLE_brgb 2, 0, 1, 2 // Select b, then r, then g, then b in that order.
4706#define SHDR_DETAIL_SWIZZLE_brga 2, 0, 1, 3 // Select b, then r, then g, then a in that order.
4707#define SHDR_DETAIL_SWIZZLE_brbr 2, 0, 2, 0 // Select b, then r, then b, then r in that order.
4708#define SHDR_DETAIL_SWIZZLE_brbg 2, 0, 2, 1 // Select b, then r, then b, then g in that order.
4709#define SHDR_DETAIL_SWIZZLE_brbb 2, 0, 2, 2 // Select b, then r, then b, then b in that order.
4710#define SHDR_DETAIL_SWIZZLE_brba 2, 0, 2, 3 // Select b, then r, then b, then a in that order.
4711#define SHDR_DETAIL_SWIZZLE_brar 2, 0, 3, 0 // Select b, then r, then a, then r in that order.
4712#define SHDR_DETAIL_SWIZZLE_brag 2, 0, 3, 1 // Select b, then r, then a, then g in that order.
4713#define SHDR_DETAIL_SWIZZLE_brab 2, 0, 3, 2 // Select b, then r, then a, then b in that order.
4714#define SHDR_DETAIL_SWIZZLE_braa 2, 0, 3, 3 // Select b, then r, then a, then a in that order.
4715#define SHDR_DETAIL_SWIZZLE_bgrr 2, 1, 0, 0 // Select b, then g, then r, then r in that order.
4716#define SHDR_DETAIL_SWIZZLE_bgrg 2, 1, 0, 1 // Select b, then g, then r, then g in that order.
4717#define SHDR_DETAIL_SWIZZLE_bgrb 2, 1, 0, 2 // Select b, then g, then r, then b in that order.
4718#define SHDR_DETAIL_SWIZZLE_bgra 2, 1, 0, 3 // Select b, then g, then r, then a in that order.
4719#define SHDR_DETAIL_SWIZZLE_bggr 2, 1, 1, 0 // Select b, then g, then g, then r in that order.
4720#define SHDR_DETAIL_SWIZZLE_bggg 2, 1, 1, 1 // Select b, then g, then g, then g in that order.
4721#define SHDR_DETAIL_SWIZZLE_bggb 2, 1, 1, 2 // Select b, then g, then g, then b in that order.
4722#define SHDR_DETAIL_SWIZZLE_bgga 2, 1, 1, 3 // Select b, then g, then g, then a in that order.
4723#define SHDR_DETAIL_SWIZZLE_bgbr 2, 1, 2, 0 // Select b, then g, then b, then r in that order.
4724#define SHDR_DETAIL_SWIZZLE_bgbg 2, 1, 2, 1 // Select b, then g, then b, then g in that order.
4725#define SHDR_DETAIL_SWIZZLE_bgbb 2, 1, 2, 2 // Select b, then g, then b, then b in that order.
4726#define SHDR_DETAIL_SWIZZLE_bgba 2, 1, 2, 3 // Select b, then g, then b, then a in that order.
4727#define SHDR_DETAIL_SWIZZLE_bgar 2, 1, 3, 0 // Select b, then g, then a, then r in that order.
4728#define SHDR_DETAIL_SWIZZLE_bgag 2, 1, 3, 1 // Select b, then g, then a, then g in that order.
4729#define SHDR_DETAIL_SWIZZLE_bgab 2, 1, 3, 2 // Select b, then g, then a, then b in that order.
4730#define SHDR_DETAIL_SWIZZLE_bgaa 2, 1, 3, 3 // Select b, then g, then a, then a in that order.
4731#define SHDR_DETAIL_SWIZZLE_bbrr 2, 2, 0, 0 // Select b, then b, then r, then r in that order.
4732#define SHDR_DETAIL_SWIZZLE_bbrg 2, 2, 0, 1 // Select b, then b, then r, then g in that order.
4733#define SHDR_DETAIL_SWIZZLE_bbrb 2, 2, 0, 2 // Select b, then b, then r, then b in that order.
4734#define SHDR_DETAIL_SWIZZLE_bbra 2, 2, 0, 3 // Select b, then b, then r, then a in that order.
4735#define SHDR_DETAIL_SWIZZLE_bbgr 2, 2, 1, 0 // Select b, then b, then g, then r in that order.
4736#define SHDR_DETAIL_SWIZZLE_bbgg 2, 2, 1, 1 // Select b, then b, then g, then g in that order.
4737#define SHDR_DETAIL_SWIZZLE_bbgb 2, 2, 1, 2 // Select b, then b, then g, then b in that order.
4738#define SHDR_DETAIL_SWIZZLE_bbga 2, 2, 1, 3 // Select b, then b, then g, then a in that order.
4739#define SHDR_DETAIL_SWIZZLE_bbbr 2, 2, 2, 0 // Select b, then b, then b, then r in that order.
4740#define SHDR_DETAIL_SWIZZLE_bbbg 2, 2, 2, 1 // Select b, then b, then b, then g in that order.
4741#define SHDR_DETAIL_SWIZZLE_bbbb 2, 2, 2, 2 // Select b, then b, then b, then b in that order.
4742#define SHDR_DETAIL_SWIZZLE_bbba 2, 2, 2, 3 // Select b, then b, then b, then a in that order.
4743#define SHDR_DETAIL_SWIZZLE_bbar 2, 2, 3, 0 // Select b, then b, then a, then r in that order.
4744#define SHDR_DETAIL_SWIZZLE_bbag 2, 2, 3, 1 // Select b, then b, then a, then g in that order.
4745#define SHDR_DETAIL_SWIZZLE_bbab 2, 2, 3, 2 // Select b, then b, then a, then b in that order.
4746#define SHDR_DETAIL_SWIZZLE_bbaa 2, 2, 3, 3 // Select b, then b, then a, then a in that order.
4747#define SHDR_DETAIL_SWIZZLE_barr 2, 3, 0, 0 // Select b, then a, then r, then r in that order.
4748#define SHDR_DETAIL_SWIZZLE_barg 2, 3, 0, 1 // Select b, then a, then r, then g in that order.
4749#define SHDR_DETAIL_SWIZZLE_barb 2, 3, 0, 2 // Select b, then a, then r, then b in that order.
4750#define SHDR_DETAIL_SWIZZLE_bara 2, 3, 0, 3 // Select b, then a, then r, then a in that order.
4751#define SHDR_DETAIL_SWIZZLE_bagr 2, 3, 1, 0 // Select b, then a, then g, then r in that order.
4752#define SHDR_DETAIL_SWIZZLE_bagg 2, 3, 1, 1 // Select b, then a, then g, then g in that order.
4753#define SHDR_DETAIL_SWIZZLE_bagb 2, 3, 1, 2 // Select b, then a, then g, then b in that order.
4754#define SHDR_DETAIL_SWIZZLE_baga 2, 3, 1, 3 // Select b, then a, then g, then a in that order.
4755#define SHDR_DETAIL_SWIZZLE_babr 2, 3, 2, 0 // Select b, then a, then b, then r in that order.
4756#define SHDR_DETAIL_SWIZZLE_babg 2, 3, 2, 1 // Select b, then a, then b, then g in that order.
4757#define SHDR_DETAIL_SWIZZLE_babb 2, 3, 2, 2 // Select b, then a, then b, then b in that order.
4758#define SHDR_DETAIL_SWIZZLE_baba 2, 3, 2, 3 // Select b, then a, then b, then a in that order.
4759#define SHDR_DETAIL_SWIZZLE_baar 2, 3, 3, 0 // Select b, then a, then a, then r in that order.
4760#define SHDR_DETAIL_SWIZZLE_baag 2, 3, 3, 1 // Select b, then a, then a, then g in that order.
4761#define SHDR_DETAIL_SWIZZLE_baab 2, 3, 3, 2 // Select b, then a, then a, then b in that order.
4762#define SHDR_DETAIL_SWIZZLE_baaa 2, 3, 3, 3 // Select b, then a, then a, then a in that order.
4763#define SHDR_DETAIL_SWIZZLE_arrr 3, 0, 0, 0 // Select a, then r, then r, then r in that order.
4764#define SHDR_DETAIL_SWIZZLE_arrg 3, 0, 0, 1 // Select a, then r, then r, then g in that order.
4765#define SHDR_DETAIL_SWIZZLE_arrb 3, 0, 0, 2 // Select a, then r, then r, then b in that order.
4766#define SHDR_DETAIL_SWIZZLE_arra 3, 0, 0, 3 // Select a, then r, then r, then a in that order.
4767#define SHDR_DETAIL_SWIZZLE_argr 3, 0, 1, 0 // Select a, then r, then g, then r in that order.
4768#define SHDR_DETAIL_SWIZZLE_argg 3, 0, 1, 1 // Select a, then r, then g, then g in that order.
4769#define SHDR_DETAIL_SWIZZLE_argb 3, 0, 1, 2 // Select a, then r, then g, then b in that order.
4770#define SHDR_DETAIL_SWIZZLE_arga 3, 0, 1, 3 // Select a, then r, then g, then a in that order.
4771#define SHDR_DETAIL_SWIZZLE_arbr 3, 0, 2, 0 // Select a, then r, then b, then r in that order.
4772#define SHDR_DETAIL_SWIZZLE_arbg 3, 0, 2, 1 // Select a, then r, then b, then g in that order.
4773#define SHDR_DETAIL_SWIZZLE_arbb 3, 0, 2, 2 // Select a, then r, then b, then b in that order.
4774#define SHDR_DETAIL_SWIZZLE_arba 3, 0, 2, 3 // Select a, then r, then b, then a in that order.
4775#define SHDR_DETAIL_SWIZZLE_arar 3, 0, 3, 0 // Select a, then r, then a, then r in that order.
4776#define SHDR_DETAIL_SWIZZLE_arag 3, 0, 3, 1 // Select a, then r, then a, then g in that order.
4777#define SHDR_DETAIL_SWIZZLE_arab 3, 0, 3, 2 // Select a, then r, then a, then b in that order.
4778#define SHDR_DETAIL_SWIZZLE_araa 3, 0, 3, 3 // Select a, then r, then a, then a in that order.
4779#define SHDR_DETAIL_SWIZZLE_agrr 3, 1, 0, 0 // Select a, then g, then r, then r in that order.
4780#define SHDR_DETAIL_SWIZZLE_agrg 3, 1, 0, 1 // Select a, then g, then r, then g in that order.
4781#define SHDR_DETAIL_SWIZZLE_agrb 3, 1, 0, 2 // Select a, then g, then r, then b in that order.
4782#define SHDR_DETAIL_SWIZZLE_agra 3, 1, 0, 3 // Select a, then g, then r, then a in that order.
4783#define SHDR_DETAIL_SWIZZLE_aggr 3, 1, 1, 0 // Select a, then g, then g, then r in that order.
4784#define SHDR_DETAIL_SWIZZLE_aggg 3, 1, 1, 1 // Select a, then g, then g, then g in that order.
4785#define SHDR_DETAIL_SWIZZLE_aggb 3, 1, 1, 2 // Select a, then g, then g, then b in that order.
4786#define SHDR_DETAIL_SWIZZLE_agga 3, 1, 1, 3 // Select a, then g, then g, then a in that order.
4787#define SHDR_DETAIL_SWIZZLE_agbr 3, 1, 2, 0 // Select a, then g, then b, then r in that order.
4788#define SHDR_DETAIL_SWIZZLE_agbg 3, 1, 2, 1 // Select a, then g, then b, then g in that order.
4789#define SHDR_DETAIL_SWIZZLE_agbb 3, 1, 2, 2 // Select a, then g, then b, then b in that order.
4790#define SHDR_DETAIL_SWIZZLE_agba 3, 1, 2, 3 // Select a, then g, then b, then a in that order.
4791#define SHDR_DETAIL_SWIZZLE_agar 3, 1, 3, 0 // Select a, then g, then a, then r in that order.
4792#define SHDR_DETAIL_SWIZZLE_agag 3, 1, 3, 1 // Select a, then g, then a, then g in that order.
4793#define SHDR_DETAIL_SWIZZLE_agab 3, 1, 3, 2 // Select a, then g, then a, then b in that order.
4794#define SHDR_DETAIL_SWIZZLE_agaa 3, 1, 3, 3 // Select a, then g, then a, then a in that order.
4795#define SHDR_DETAIL_SWIZZLE_abrr 3, 2, 0, 0 // Select a, then b, then r, then r in that order.
4796#define SHDR_DETAIL_SWIZZLE_abrg 3, 2, 0, 1 // Select a, then b, then r, then g in that order.
4797#define SHDR_DETAIL_SWIZZLE_abrb 3, 2, 0, 2 // Select a, then b, then r, then b in that order.
4798#define SHDR_DETAIL_SWIZZLE_abra 3, 2, 0, 3 // Select a, then b, then r, then a in that order.
4799#define SHDR_DETAIL_SWIZZLE_abgr 3, 2, 1, 0 // Select a, then b, then g, then r in that order.
4800#define SHDR_DETAIL_SWIZZLE_abgg 3, 2, 1, 1 // Select a, then b, then g, then g in that order.
4801#define SHDR_DETAIL_SWIZZLE_abgb 3, 2, 1, 2 // Select a, then b, then g, then b in that order.
4802#define SHDR_DETAIL_SWIZZLE_abga 3, 2, 1, 3 // Select a, then b, then g, then a in that order.
4803#define SHDR_DETAIL_SWIZZLE_abbr 3, 2, 2, 0 // Select a, then b, then b, then r in that order.
4804#define SHDR_DETAIL_SWIZZLE_abbg 3, 2, 2, 1 // Select a, then b, then b, then g in that order.
4805#define SHDR_DETAIL_SWIZZLE_abbb 3, 2, 2, 2 // Select a, then b, then b, then b in that order.
4806#define SHDR_DETAIL_SWIZZLE_abba 3, 2, 2, 3 // Select a, then b, then b, then a in that order.
4807#define SHDR_DETAIL_SWIZZLE_abar 3, 2, 3, 0 // Select a, then b, then a, then r in that order.
4808#define SHDR_DETAIL_SWIZZLE_abag 3, 2, 3, 1 // Select a, then b, then a, then g in that order.
4809#define SHDR_DETAIL_SWIZZLE_abab 3, 2, 3, 2 // Select a, then b, then a, then b in that order.
4810#define SHDR_DETAIL_SWIZZLE_abaa 3, 2, 3, 3 // Select a, then b, then a, then a in that order.
4811#define SHDR_DETAIL_SWIZZLE_aarr 3, 3, 0, 0 // Select a, then a, then r, then r in that order.
4812#define SHDR_DETAIL_SWIZZLE_aarg 3, 3, 0, 1 // Select a, then a, then r, then g in that order.
4813#define SHDR_DETAIL_SWIZZLE_aarb 3, 3, 0, 2 // Select a, then a, then r, then b in that order.
4814#define SHDR_DETAIL_SWIZZLE_aara 3, 3, 0, 3 // Select a, then a, then r, then a in that order.
4815#define SHDR_DETAIL_SWIZZLE_aagr 3, 3, 1, 0 // Select a, then a, then g, then r in that order.
4816#define SHDR_DETAIL_SWIZZLE_aagg 3, 3, 1, 1 // Select a, then a, then g, then g in that order.
4817#define SHDR_DETAIL_SWIZZLE_aagb 3, 3, 1, 2 // Select a, then a, then g, then b in that order.
4818#define SHDR_DETAIL_SWIZZLE_aaga 3, 3, 1, 3 // Select a, then a, then g, then a in that order.
4819#define SHDR_DETAIL_SWIZZLE_aabr 3, 3, 2, 0 // Select a, then a, then b, then r in that order.
4820#define SHDR_DETAIL_SWIZZLE_aabg 3, 3, 2, 1 // Select a, then a, then b, then g in that order.
4821#define SHDR_DETAIL_SWIZZLE_aabb 3, 3, 2, 2 // Select a, then a, then b, then b in that order.
4822#define SHDR_DETAIL_SWIZZLE_aaba 3, 3, 2, 3 // Select a, then a, then b, then a in that order.
4823#define SHDR_DETAIL_SWIZZLE_aaar 3, 3, 3, 0 // Select a, then a, then a, then r in that order.
4824#define SHDR_DETAIL_SWIZZLE_aaag 3, 3, 3, 1 // Select a, then a, then a, then g in that order.
4825#define SHDR_DETAIL_SWIZZLE_aaab 3, 3, 3, 2 // Select a, then a, then a, then b in that order.
4826#define SHDR_DETAIL_SWIZZLE_aaaa 3, 3, 3, 3 // Select a, then a, then a, then a in that order.
4827#define SHDR_DETAIL_SWIZZLE_s 0 // Select the s component.
4828#define SHDR_DETAIL_SWIZZLE_t 1 // Select the t component.
4829#define SHDR_DETAIL_SWIZZLE_p 2 // Select the p component.
4830#define SHDR_DETAIL_SWIZZLE_q 3 // Select the q component.
4831#define SHDR_DETAIL_SWIZZLE_ss 0, 0 // Select s, then s in that order.
4832#define SHDR_DETAIL_SWIZZLE_st 0, 1 // Select s, then t in that order.
4833#define SHDR_DETAIL_SWIZZLE_sp 0, 2 // Select s, then p in that order.
4834#define SHDR_DETAIL_SWIZZLE_sq 0, 3 // Select s, then q in that order.
4835#define SHDR_DETAIL_SWIZZLE_ts 1, 0 // Select t, then s in that order.
4836#define SHDR_DETAIL_SWIZZLE_tt 1, 1 // Select t, then t in that order.
4837#define SHDR_DETAIL_SWIZZLE_tp 1, 2 // Select t, then p in that order.
4838#define SHDR_DETAIL_SWIZZLE_tq 1, 3 // Select t, then q in that order.
4839#define SHDR_DETAIL_SWIZZLE_ps 2, 0 // Select p, then s in that order.
4840#define SHDR_DETAIL_SWIZZLE_pt 2, 1 // Select p, then t in that order.
4841#define SHDR_DETAIL_SWIZZLE_pp 2, 2 // Select p, then p in that order.
4842#define SHDR_DETAIL_SWIZZLE_pq 2, 3 // Select p, then q in that order.
4843#define SHDR_DETAIL_SWIZZLE_qs 3, 0 // Select q, then s in that order.
4844#define SHDR_DETAIL_SWIZZLE_qt 3, 1 // Select q, then t in that order.
4845#define SHDR_DETAIL_SWIZZLE_qp 3, 2 // Select q, then p in that order.
4846#define SHDR_DETAIL_SWIZZLE_qq 3, 3 // Select q, then q in that order.
4847#define SHDR_DETAIL_SWIZZLE_sss 0, 0, 0 // Select s, then s, then s in that order.
4848#define SHDR_DETAIL_SWIZZLE_sst 0, 0, 1 // Select s, then s, then t in that order.
4849#define SHDR_DETAIL_SWIZZLE_ssp 0, 0, 2 // Select s, then s, then p in that order.
4850#define SHDR_DETAIL_SWIZZLE_ssq 0, 0, 3 // Select s, then s, then q in that order.
4851#define SHDR_DETAIL_SWIZZLE_sts 0, 1, 0 // Select s, then t, then s in that order.
4852#define SHDR_DETAIL_SWIZZLE_stt 0, 1, 1 // Select s, then t, then t in that order.
4853#define SHDR_DETAIL_SWIZZLE_stp 0, 1, 2 // Select s, then t, then p in that order.
4854#define SHDR_DETAIL_SWIZZLE_stq 0, 1, 3 // Select s, then t, then q in that order.
4855#define SHDR_DETAIL_SWIZZLE_sps 0, 2, 0 // Select s, then p, then s in that order.
4856#define SHDR_DETAIL_SWIZZLE_spt 0, 2, 1 // Select s, then p, then t in that order.
4857#define SHDR_DETAIL_SWIZZLE_spp 0, 2, 2 // Select s, then p, then p in that order.
4858#define SHDR_DETAIL_SWIZZLE_spq 0, 2, 3 // Select s, then p, then q in that order.
4859#define SHDR_DETAIL_SWIZZLE_sqs 0, 3, 0 // Select s, then q, then s in that order.
4860#define SHDR_DETAIL_SWIZZLE_sqt 0, 3, 1 // Select s, then q, then t in that order.
4861#define SHDR_DETAIL_SWIZZLE_sqp 0, 3, 2 // Select s, then q, then p in that order.
4862#define SHDR_DETAIL_SWIZZLE_sqq 0, 3, 3 // Select s, then q, then q in that order.
4863#define SHDR_DETAIL_SWIZZLE_tss 1, 0, 0 // Select t, then s, then s in that order.
4864#define SHDR_DETAIL_SWIZZLE_tst 1, 0, 1 // Select t, then s, then t in that order.
4865#define SHDR_DETAIL_SWIZZLE_tsp 1, 0, 2 // Select t, then s, then p in that order.
4866#define SHDR_DETAIL_SWIZZLE_tsq 1, 0, 3 // Select t, then s, then q in that order.
4867#define SHDR_DETAIL_SWIZZLE_tts 1, 1, 0 // Select t, then t, then s in that order.
4868#define SHDR_DETAIL_SWIZZLE_ttt 1, 1, 1 // Select t, then t, then t in that order.
4869#define SHDR_DETAIL_SWIZZLE_ttp 1, 1, 2 // Select t, then t, then p in that order.
4870#define SHDR_DETAIL_SWIZZLE_ttq 1, 1, 3 // Select t, then t, then q in that order.
4871#define SHDR_DETAIL_SWIZZLE_tps 1, 2, 0 // Select t, then p, then s in that order.
4872#define SHDR_DETAIL_SWIZZLE_tpt 1, 2, 1 // Select t, then p, then t in that order.
4873#define SHDR_DETAIL_SWIZZLE_tpp 1, 2, 2 // Select t, then p, then p in that order.
4874#define SHDR_DETAIL_SWIZZLE_tpq 1, 2, 3 // Select t, then p, then q in that order.
4875#define SHDR_DETAIL_SWIZZLE_tqs 1, 3, 0 // Select t, then q, then s in that order.
4876#define SHDR_DETAIL_SWIZZLE_tqt 1, 3, 1 // Select t, then q, then t in that order.
4877#define SHDR_DETAIL_SWIZZLE_tqp 1, 3, 2 // Select t, then q, then p in that order.
4878#define SHDR_DETAIL_SWIZZLE_tqq 1, 3, 3 // Select t, then q, then q in that order.
4879#define SHDR_DETAIL_SWIZZLE_pss 2, 0, 0 // Select p, then s, then s in that order.
4880#define SHDR_DETAIL_SWIZZLE_pst 2, 0, 1 // Select p, then s, then t in that order.
4881#define SHDR_DETAIL_SWIZZLE_psp 2, 0, 2 // Select p, then s, then p in that order.
4882#define SHDR_DETAIL_SWIZZLE_psq 2, 0, 3 // Select p, then s, then q in that order.
4883#define SHDR_DETAIL_SWIZZLE_pts 2, 1, 0 // Select p, then t, then s in that order.
4884#define SHDR_DETAIL_SWIZZLE_ptt 2, 1, 1 // Select p, then t, then t in that order.
4885#define SHDR_DETAIL_SWIZZLE_ptp 2, 1, 2 // Select p, then t, then p in that order.
4886#define SHDR_DETAIL_SWIZZLE_ptq 2, 1, 3 // Select p, then t, then q in that order.
4887#define SHDR_DETAIL_SWIZZLE_pps 2, 2, 0 // Select p, then p, then s in that order.
4888#define SHDR_DETAIL_SWIZZLE_ppt 2, 2, 1 // Select p, then p, then t in that order.
4889#define SHDR_DETAIL_SWIZZLE_ppp 2, 2, 2 // Select p, then p, then p in that order.
4890#define SHDR_DETAIL_SWIZZLE_ppq 2, 2, 3 // Select p, then p, then q in that order.
4891#define SHDR_DETAIL_SWIZZLE_pqs 2, 3, 0 // Select p, then q, then s in that order.
4892#define SHDR_DETAIL_SWIZZLE_pqt 2, 3, 1 // Select p, then q, then t in that order.
4893#define SHDR_DETAIL_SWIZZLE_pqp 2, 3, 2 // Select p, then q, then p in that order.
4894#define SHDR_DETAIL_SWIZZLE_pqq 2, 3, 3 // Select p, then q, then q in that order.
4895#define SHDR_DETAIL_SWIZZLE_qss 3, 0, 0 // Select q, then s, then s in that order.
4896#define SHDR_DETAIL_SWIZZLE_qst 3, 0, 1 // Select q, then s, then t in that order.
4897#define SHDR_DETAIL_SWIZZLE_qsp 3, 0, 2 // Select q, then s, then p in that order.
4898#define SHDR_DETAIL_SWIZZLE_qsq 3, 0, 3 // Select q, then s, then q in that order.
4899#define SHDR_DETAIL_SWIZZLE_qts 3, 1, 0 // Select q, then t, then s in that order.
4900#define SHDR_DETAIL_SWIZZLE_qtt 3, 1, 1 // Select q, then t, then t in that order.
4901#define SHDR_DETAIL_SWIZZLE_qtp 3, 1, 2 // Select q, then t, then p in that order.
4902#define SHDR_DETAIL_SWIZZLE_qtq 3, 1, 3 // Select q, then t, then q in that order.
4903#define SHDR_DETAIL_SWIZZLE_qps 3, 2, 0 // Select q, then p, then s in that order.
4904#define SHDR_DETAIL_SWIZZLE_qpt 3, 2, 1 // Select q, then p, then t in that order.
4905#define SHDR_DETAIL_SWIZZLE_qpp 3, 2, 2 // Select q, then p, then p in that order.
4906#define SHDR_DETAIL_SWIZZLE_qpq 3, 2, 3 // Select q, then p, then q in that order.
4907#define SHDR_DETAIL_SWIZZLE_qqs 3, 3, 0 // Select q, then q, then s in that order.
4908#define SHDR_DETAIL_SWIZZLE_qqt 3, 3, 1 // Select q, then q, then t in that order.
4909#define SHDR_DETAIL_SWIZZLE_qqp 3, 3, 2 // Select q, then q, then p in that order.
4910#define SHDR_DETAIL_SWIZZLE_qqq 3, 3, 3 // Select q, then q, then q in that order.
4911#define SHDR_DETAIL_SWIZZLE_ssss 0, 0, 0, 0 // Select s, then s, then s, then s in that order.
4912#define SHDR_DETAIL_SWIZZLE_ssst 0, 0, 0, 1 // Select s, then s, then s, then t in that order.
4913#define SHDR_DETAIL_SWIZZLE_sssp 0, 0, 0, 2 // Select s, then s, then s, then p in that order.
4914#define SHDR_DETAIL_SWIZZLE_sssq 0, 0, 0, 3 // Select s, then s, then s, then q in that order.
4915#define SHDR_DETAIL_SWIZZLE_ssts 0, 0, 1, 0 // Select s, then s, then t, then s in that order.
4916#define SHDR_DETAIL_SWIZZLE_sstt 0, 0, 1, 1 // Select s, then s, then t, then t in that order.
4917#define SHDR_DETAIL_SWIZZLE_sstp 0, 0, 1, 2 // Select s, then s, then t, then p in that order.
4918#define SHDR_DETAIL_SWIZZLE_sstq 0, 0, 1, 3 // Select s, then s, then t, then q in that order.
4919#define SHDR_DETAIL_SWIZZLE_ssps 0, 0, 2, 0 // Select s, then s, then p, then s in that order.
4920#define SHDR_DETAIL_SWIZZLE_sspt 0, 0, 2, 1 // Select s, then s, then p, then t in that order.
4921#define SHDR_DETAIL_SWIZZLE_sspp 0, 0, 2, 2 // Select s, then s, then p, then p in that order.
4922#define SHDR_DETAIL_SWIZZLE_sspq 0, 0, 2, 3 // Select s, then s, then p, then q in that order.
4923#define SHDR_DETAIL_SWIZZLE_ssqs 0, 0, 3, 0 // Select s, then s, then q, then s in that order.
4924#define SHDR_DETAIL_SWIZZLE_ssqt 0, 0, 3, 1 // Select s, then s, then q, then t in that order.
4925#define SHDR_DETAIL_SWIZZLE_ssqp 0, 0, 3, 2 // Select s, then s, then q, then p in that order.
4926#define SHDR_DETAIL_SWIZZLE_ssqq 0, 0, 3, 3 // Select s, then s, then q, then q in that order.
4927#define SHDR_DETAIL_SWIZZLE_stss 0, 1, 0, 0 // Select s, then t, then s, then s in that order.
4928#define SHDR_DETAIL_SWIZZLE_stst 0, 1, 0, 1 // Select s, then t, then s, then t in that order.
4929#define SHDR_DETAIL_SWIZZLE_stsp 0, 1, 0, 2 // Select s, then t, then s, then p in that order.
4930#define SHDR_DETAIL_SWIZZLE_stsq 0, 1, 0, 3 // Select s, then t, then s, then q in that order.
4931#define SHDR_DETAIL_SWIZZLE_stts 0, 1, 1, 0 // Select s, then t, then t, then s in that order.
4932#define SHDR_DETAIL_SWIZZLE_sttt 0, 1, 1, 1 // Select s, then t, then t, then t in that order.
4933#define SHDR_DETAIL_SWIZZLE_sttp 0, 1, 1, 2 // Select s, then t, then t, then p in that order.
4934#define SHDR_DETAIL_SWIZZLE_sttq 0, 1, 1, 3 // Select s, then t, then t, then q in that order.
4935#define SHDR_DETAIL_SWIZZLE_stps 0, 1, 2, 0 // Select s, then t, then p, then s in that order.
4936#define SHDR_DETAIL_SWIZZLE_stpt 0, 1, 2, 1 // Select s, then t, then p, then t in that order.
4937#define SHDR_DETAIL_SWIZZLE_stpp 0, 1, 2, 2 // Select s, then t, then p, then p in that order.
4938#define SHDR_DETAIL_SWIZZLE_stpq 0, 1, 2, 3 // Select s, then t, then p, then q in that order.
4939#define SHDR_DETAIL_SWIZZLE_stqs 0, 1, 3, 0 // Select s, then t, then q, then s in that order.
4940#define SHDR_DETAIL_SWIZZLE_stqt 0, 1, 3, 1 // Select s, then t, then q, then t in that order.
4941#define SHDR_DETAIL_SWIZZLE_stqp 0, 1, 3, 2 // Select s, then t, then q, then p in that order.
4942#define SHDR_DETAIL_SWIZZLE_stqq 0, 1, 3, 3 // Select s, then t, then q, then q in that order.
4943#define SHDR_DETAIL_SWIZZLE_spss 0, 2, 0, 0 // Select s, then p, then s, then s in that order.
4944#define SHDR_DETAIL_SWIZZLE_spst 0, 2, 0, 1 // Select s, then p, then s, then t in that order.
4945#define SHDR_DETAIL_SWIZZLE_spsp 0, 2, 0, 2 // Select s, then p, then s, then p in that order.
4946#define SHDR_DETAIL_SWIZZLE_spsq 0, 2, 0, 3 // Select s, then p, then s, then q in that order.
4947#define SHDR_DETAIL_SWIZZLE_spts 0, 2, 1, 0 // Select s, then p, then t, then s in that order.
4948#define SHDR_DETAIL_SWIZZLE_sptt 0, 2, 1, 1 // Select s, then p, then t, then t in that order.
4949#define SHDR_DETAIL_SWIZZLE_sptp 0, 2, 1, 2 // Select s, then p, then t, then p in that order.
4950#define SHDR_DETAIL_SWIZZLE_sptq 0, 2, 1, 3 // Select s, then p, then t, then q in that order.
4951#define SHDR_DETAIL_SWIZZLE_spps 0, 2, 2, 0 // Select s, then p, then p, then s in that order.
4952#define SHDR_DETAIL_SWIZZLE_sppt 0, 2, 2, 1 // Select s, then p, then p, then t in that order.
4953#define SHDR_DETAIL_SWIZZLE_sppp 0, 2, 2, 2 // Select s, then p, then p, then p in that order.
4954#define SHDR_DETAIL_SWIZZLE_sppq 0, 2, 2, 3 // Select s, then p, then p, then q in that order.
4955#define SHDR_DETAIL_SWIZZLE_spqs 0, 2, 3, 0 // Select s, then p, then q, then s in that order.
4956#define SHDR_DETAIL_SWIZZLE_spqt 0, 2, 3, 1 // Select s, then p, then q, then t in that order.
4957#define SHDR_DETAIL_SWIZZLE_spqp 0, 2, 3, 2 // Select s, then p, then q, then p in that order.
4958#define SHDR_DETAIL_SWIZZLE_spqq 0, 2, 3, 3 // Select s, then p, then q, then q in that order.
4959#define SHDR_DETAIL_SWIZZLE_sqss 0, 3, 0, 0 // Select s, then q, then s, then s in that order.
4960#define SHDR_DETAIL_SWIZZLE_sqst 0, 3, 0, 1 // Select s, then q, then s, then t in that order.
4961#define SHDR_DETAIL_SWIZZLE_sqsp 0, 3, 0, 2 // Select s, then q, then s, then p in that order.
4962#define SHDR_DETAIL_SWIZZLE_sqsq 0, 3, 0, 3 // Select s, then q, then s, then q in that order.
4963#define SHDR_DETAIL_SWIZZLE_sqts 0, 3, 1, 0 // Select s, then q, then t, then s in that order.
4964#define SHDR_DETAIL_SWIZZLE_sqtt 0, 3, 1, 1 // Select s, then q, then t, then t in that order.
4965#define SHDR_DETAIL_SWIZZLE_sqtp 0, 3, 1, 2 // Select s, then q, then t, then p in that order.
4966#define SHDR_DETAIL_SWIZZLE_sqtq 0, 3, 1, 3 // Select s, then q, then t, then q in that order.
4967#define SHDR_DETAIL_SWIZZLE_sqps 0, 3, 2, 0 // Select s, then q, then p, then s in that order.
4968#define SHDR_DETAIL_SWIZZLE_sqpt 0, 3, 2, 1 // Select s, then q, then p, then t in that order.
4969#define SHDR_DETAIL_SWIZZLE_sqpp 0, 3, 2, 2 // Select s, then q, then p, then p in that order.
4970#define SHDR_DETAIL_SWIZZLE_sqpq 0, 3, 2, 3 // Select s, then q, then p, then q in that order.
4971#define SHDR_DETAIL_SWIZZLE_sqqs 0, 3, 3, 0 // Select s, then q, then q, then s in that order.
4972#define SHDR_DETAIL_SWIZZLE_sqqt 0, 3, 3, 1 // Select s, then q, then q, then t in that order.
4973#define SHDR_DETAIL_SWIZZLE_sqqp 0, 3, 3, 2 // Select s, then q, then q, then p in that order.
4974#define SHDR_DETAIL_SWIZZLE_sqqq 0, 3, 3, 3 // Select s, then q, then q, then q in that order.
4975#define SHDR_DETAIL_SWIZZLE_tsss 1, 0, 0, 0 // Select t, then s, then s, then s in that order.
4976#define SHDR_DETAIL_SWIZZLE_tsst 1, 0, 0, 1 // Select t, then s, then s, then t in that order.
4977#define SHDR_DETAIL_SWIZZLE_tssp 1, 0, 0, 2 // Select t, then s, then s, then p in that order.
4978#define SHDR_DETAIL_SWIZZLE_tssq 1, 0, 0, 3 // Select t, then s, then s, then q in that order.
4979#define SHDR_DETAIL_SWIZZLE_tsts 1, 0, 1, 0 // Select t, then s, then t, then s in that order.
4980#define SHDR_DETAIL_SWIZZLE_tstt 1, 0, 1, 1 // Select t, then s, then t, then t in that order.
4981#define SHDR_DETAIL_SWIZZLE_tstp 1, 0, 1, 2 // Select t, then s, then t, then p in that order.
4982#define SHDR_DETAIL_SWIZZLE_tstq 1, 0, 1, 3 // Select t, then s, then t, then q in that order.
4983#define SHDR_DETAIL_SWIZZLE_tsps 1, 0, 2, 0 // Select t, then s, then p, then s in that order.
4984#define SHDR_DETAIL_SWIZZLE_tspt 1, 0, 2, 1 // Select t, then s, then p, then t in that order.
4985#define SHDR_DETAIL_SWIZZLE_tspp 1, 0, 2, 2 // Select t, then s, then p, then p in that order.
4986#define SHDR_DETAIL_SWIZZLE_tspq 1, 0, 2, 3 // Select t, then s, then p, then q in that order.
4987#define SHDR_DETAIL_SWIZZLE_tsqs 1, 0, 3, 0 // Select t, then s, then q, then s in that order.
4988#define SHDR_DETAIL_SWIZZLE_tsqt 1, 0, 3, 1 // Select t, then s, then q, then t in that order.
4989#define SHDR_DETAIL_SWIZZLE_tsqp 1, 0, 3, 2 // Select t, then s, then q, then p in that order.
4990#define SHDR_DETAIL_SWIZZLE_tsqq 1, 0, 3, 3 // Select t, then s, then q, then q in that order.
4991#define SHDR_DETAIL_SWIZZLE_ttss 1, 1, 0, 0 // Select t, then t, then s, then s in that order.
4992#define SHDR_DETAIL_SWIZZLE_ttst 1, 1, 0, 1 // Select t, then t, then s, then t in that order.
4993#define SHDR_DETAIL_SWIZZLE_ttsp 1, 1, 0, 2 // Select t, then t, then s, then p in that order.
4994#define SHDR_DETAIL_SWIZZLE_ttsq 1, 1, 0, 3 // Select t, then t, then s, then q in that order.
4995#define SHDR_DETAIL_SWIZZLE_ttts 1, 1, 1, 0 // Select t, then t, then t, then s in that order.
4996#define SHDR_DETAIL_SWIZZLE_tttt 1, 1, 1, 1 // Select t, then t, then t, then t in that order.
4997#define SHDR_DETAIL_SWIZZLE_tttp 1, 1, 1, 2 // Select t, then t, then t, then p in that order.
4998#define SHDR_DETAIL_SWIZZLE_tttq 1, 1, 1, 3 // Select t, then t, then t, then q in that order.
4999#define SHDR_DETAIL_SWIZZLE_ttps 1, 1, 2, 0 // Select t, then t, then p, then s in that order.
5000#define SHDR_DETAIL_SWIZZLE_ttpt 1, 1, 2, 1 // Select t, then t, then p, then t in that order.
5001#define SHDR_DETAIL_SWIZZLE_ttpp 1, 1, 2, 2 // Select t, then t, then p, then p in that order.
5002#define SHDR_DETAIL_SWIZZLE_ttpq 1, 1, 2, 3 // Select t, then t, then p, then q in that order.
5003#define SHDR_DETAIL_SWIZZLE_ttqs 1, 1, 3, 0 // Select t, then t, then q, then s in that order.
5004#define SHDR_DETAIL_SWIZZLE_ttqt 1, 1, 3, 1 // Select t, then t, then q, then t in that order.
5005#define SHDR_DETAIL_SWIZZLE_ttqp 1, 1, 3, 2 // Select t, then t, then q, then p in that order.
5006#define SHDR_DETAIL_SWIZZLE_ttqq 1, 1, 3, 3 // Select t, then t, then q, then q in that order.
5007#define SHDR_DETAIL_SWIZZLE_tpss 1, 2, 0, 0 // Select t, then p, then s, then s in that order.
5008#define SHDR_DETAIL_SWIZZLE_tpst 1, 2, 0, 1 // Select t, then p, then s, then t in that order.
5009#define SHDR_DETAIL_SWIZZLE_tpsp 1, 2, 0, 2 // Select t, then p, then s, then p in that order.
5010#define SHDR_DETAIL_SWIZZLE_tpsq 1, 2, 0, 3 // Select t, then p, then s, then q in that order.
5011#define SHDR_DETAIL_SWIZZLE_tpts 1, 2, 1, 0 // Select t, then p, then t, then s in that order.
5012#define SHDR_DETAIL_SWIZZLE_tptt 1, 2, 1, 1 // Select t, then p, then t, then t in that order.
5013#define SHDR_DETAIL_SWIZZLE_tptp 1, 2, 1, 2 // Select t, then p, then t, then p in that order.
5014#define SHDR_DETAIL_SWIZZLE_tptq 1, 2, 1, 3 // Select t, then p, then t, then q in that order.
5015#define SHDR_DETAIL_SWIZZLE_tpps 1, 2, 2, 0 // Select t, then p, then p, then s in that order.
5016#define SHDR_DETAIL_SWIZZLE_tppt 1, 2, 2, 1 // Select t, then p, then p, then t in that order.
5017#define SHDR_DETAIL_SWIZZLE_tppp 1, 2, 2, 2 // Select t, then p, then p, then p in that order.
5018#define SHDR_DETAIL_SWIZZLE_tppq 1, 2, 2, 3 // Select t, then p, then p, then q in that order.
5019#define SHDR_DETAIL_SWIZZLE_tpqs 1, 2, 3, 0 // Select t, then p, then q, then s in that order.
5020#define SHDR_DETAIL_SWIZZLE_tpqt 1, 2, 3, 1 // Select t, then p, then q, then t in that order.
5021#define SHDR_DETAIL_SWIZZLE_tpqp 1, 2, 3, 2 // Select t, then p, then q, then p in that order.
5022#define SHDR_DETAIL_SWIZZLE_tpqq 1, 2, 3, 3 // Select t, then p, then q, then q in that order.
5023#define SHDR_DETAIL_SWIZZLE_tqss 1, 3, 0, 0 // Select t, then q, then s, then s in that order.
5024#define SHDR_DETAIL_SWIZZLE_tqst 1, 3, 0, 1 // Select t, then q, then s, then t in that order.
5025#define SHDR_DETAIL_SWIZZLE_tqsp 1, 3, 0, 2 // Select t, then q, then s, then p in that order.
5026#define SHDR_DETAIL_SWIZZLE_tqsq 1, 3, 0, 3 // Select t, then q, then s, then q in that order.
5027#define SHDR_DETAIL_SWIZZLE_tqts 1, 3, 1, 0 // Select t, then q, then t, then s in that order.
5028#define SHDR_DETAIL_SWIZZLE_tqtt 1, 3, 1, 1 // Select t, then q, then t, then t in that order.
5029#define SHDR_DETAIL_SWIZZLE_tqtp 1, 3, 1, 2 // Select t, then q, then t, then p in that order.
5030#define SHDR_DETAIL_SWIZZLE_tqtq 1, 3, 1, 3 // Select t, then q, then t, then q in that order.
5031#define SHDR_DETAIL_SWIZZLE_tqps 1, 3, 2, 0 // Select t, then q, then p, then s in that order.
5032#define SHDR_DETAIL_SWIZZLE_tqpt 1, 3, 2, 1 // Select t, then q, then p, then t in that order.
5033#define SHDR_DETAIL_SWIZZLE_tqpp 1, 3, 2, 2 // Select t, then q, then p, then p in that order.
5034#define SHDR_DETAIL_SWIZZLE_tqpq 1, 3, 2, 3 // Select t, then q, then p, then q in that order.
5035#define SHDR_DETAIL_SWIZZLE_tqqs 1, 3, 3, 0 // Select t, then q, then q, then s in that order.
5036#define SHDR_DETAIL_SWIZZLE_tqqt 1, 3, 3, 1 // Select t, then q, then q, then t in that order.
5037#define SHDR_DETAIL_SWIZZLE_tqqp 1, 3, 3, 2 // Select t, then q, then q, then p in that order.
5038#define SHDR_DETAIL_SWIZZLE_tqqq 1, 3, 3, 3 // Select t, then q, then q, then q in that order.
5039#define SHDR_DETAIL_SWIZZLE_psss 2, 0, 0, 0 // Select p, then s, then s, then s in that order.
5040#define SHDR_DETAIL_SWIZZLE_psst 2, 0, 0, 1 // Select p, then s, then s, then t in that order.
5041#define SHDR_DETAIL_SWIZZLE_pssp 2, 0, 0, 2 // Select p, then s, then s, then p in that order.
5042#define SHDR_DETAIL_SWIZZLE_pssq 2, 0, 0, 3 // Select p, then s, then s, then q in that order.
5043#define SHDR_DETAIL_SWIZZLE_psts 2, 0, 1, 0 // Select p, then s, then t, then s in that order.
5044#define SHDR_DETAIL_SWIZZLE_pstt 2, 0, 1, 1 // Select p, then s, then t, then t in that order.
5045#define SHDR_DETAIL_SWIZZLE_pstp 2, 0, 1, 2 // Select p, then s, then t, then p in that order.
5046#define SHDR_DETAIL_SWIZZLE_pstq 2, 0, 1, 3 // Select p, then s, then t, then q in that order.
5047#define SHDR_DETAIL_SWIZZLE_psps 2, 0, 2, 0 // Select p, then s, then p, then s in that order.
5048#define SHDR_DETAIL_SWIZZLE_pspt 2, 0, 2, 1 // Select p, then s, then p, then t in that order.
5049#define SHDR_DETAIL_SWIZZLE_pspp 2, 0, 2, 2 // Select p, then s, then p, then p in that order.
5050#define SHDR_DETAIL_SWIZZLE_pspq 2, 0, 2, 3 // Select p, then s, then p, then q in that order.
5051#define SHDR_DETAIL_SWIZZLE_psqs 2, 0, 3, 0 // Select p, then s, then q, then s in that order.
5052#define SHDR_DETAIL_SWIZZLE_psqt 2, 0, 3, 1 // Select p, then s, then q, then t in that order.
5053#define SHDR_DETAIL_SWIZZLE_psqp 2, 0, 3, 2 // Select p, then s, then q, then p in that order.
5054#define SHDR_DETAIL_SWIZZLE_psqq 2, 0, 3, 3 // Select p, then s, then q, then q in that order.
5055#define SHDR_DETAIL_SWIZZLE_ptss 2, 1, 0, 0 // Select p, then t, then s, then s in that order.
5056#define SHDR_DETAIL_SWIZZLE_ptst 2, 1, 0, 1 // Select p, then t, then s, then t in that order.
5057#define SHDR_DETAIL_SWIZZLE_ptsp 2, 1, 0, 2 // Select p, then t, then s, then p in that order.
5058#define SHDR_DETAIL_SWIZZLE_ptsq 2, 1, 0, 3 // Select p, then t, then s, then q in that order.
5059#define SHDR_DETAIL_SWIZZLE_ptts 2, 1, 1, 0 // Select p, then t, then t, then s in that order.
5060#define SHDR_DETAIL_SWIZZLE_pttt 2, 1, 1, 1 // Select p, then t, then t, then t in that order.
5061#define SHDR_DETAIL_SWIZZLE_pttp 2, 1, 1, 2 // Select p, then t, then t, then p in that order.
5062#define SHDR_DETAIL_SWIZZLE_pttq 2, 1, 1, 3 // Select p, then t, then t, then q in that order.
5063#define SHDR_DETAIL_SWIZZLE_ptps 2, 1, 2, 0 // Select p, then t, then p, then s in that order.
5064#define SHDR_DETAIL_SWIZZLE_ptpt 2, 1, 2, 1 // Select p, then t, then p, then t in that order.
5065#define SHDR_DETAIL_SWIZZLE_ptpp 2, 1, 2, 2 // Select p, then t, then p, then p in that order.
5066#define SHDR_DETAIL_SWIZZLE_ptpq 2, 1, 2, 3 // Select p, then t, then p, then q in that order.
5067#define SHDR_DETAIL_SWIZZLE_ptqs 2, 1, 3, 0 // Select p, then t, then q, then s in that order.
5068#define SHDR_DETAIL_SWIZZLE_ptqt 2, 1, 3, 1 // Select p, then t, then q, then t in that order.
5069#define SHDR_DETAIL_SWIZZLE_ptqp 2, 1, 3, 2 // Select p, then t, then q, then p in that order.
5070#define SHDR_DETAIL_SWIZZLE_ptqq 2, 1, 3, 3 // Select p, then t, then q, then q in that order.
5071#define SHDR_DETAIL_SWIZZLE_ppss 2, 2, 0, 0 // Select p, then p, then s, then s in that order.
5072#define SHDR_DETAIL_SWIZZLE_ppst 2, 2, 0, 1 // Select p, then p, then s, then t in that order.
5073#define SHDR_DETAIL_SWIZZLE_ppsp 2, 2, 0, 2 // Select p, then p, then s, then p in that order.
5074#define SHDR_DETAIL_SWIZZLE_ppsq 2, 2, 0, 3 // Select p, then p, then s, then q in that order.
5075#define SHDR_DETAIL_SWIZZLE_ppts 2, 2, 1, 0 // Select p, then p, then t, then s in that order.
5076#define SHDR_DETAIL_SWIZZLE_pptt 2, 2, 1, 1 // Select p, then p, then t, then t in that order.
5077#define SHDR_DETAIL_SWIZZLE_pptp 2, 2, 1, 2 // Select p, then p, then t, then p in that order.
5078#define SHDR_DETAIL_SWIZZLE_pptq 2, 2, 1, 3 // Select p, then p, then t, then q in that order.
5079#define SHDR_DETAIL_SWIZZLE_ppps 2, 2, 2, 0 // Select p, then p, then p, then s in that order.
5080#define SHDR_DETAIL_SWIZZLE_pppt 2, 2, 2, 1 // Select p, then p, then p, then t in that order.
5081#define SHDR_DETAIL_SWIZZLE_pppp 2, 2, 2, 2 // Select p, then p, then p, then p in that order.
5082#define SHDR_DETAIL_SWIZZLE_pppq 2, 2, 2, 3 // Select p, then p, then p, then q in that order.
5083#define SHDR_DETAIL_SWIZZLE_ppqs 2, 2, 3, 0 // Select p, then p, then q, then s in that order.
5084#define SHDR_DETAIL_SWIZZLE_ppqt 2, 2, 3, 1 // Select p, then p, then q, then t in that order.
5085#define SHDR_DETAIL_SWIZZLE_ppqp 2, 2, 3, 2 // Select p, then p, then q, then p in that order.
5086#define SHDR_DETAIL_SWIZZLE_ppqq 2, 2, 3, 3 // Select p, then p, then q, then q in that order.
5087#define SHDR_DETAIL_SWIZZLE_pqss 2, 3, 0, 0 // Select p, then q, then s, then s in that order.
5088#define SHDR_DETAIL_SWIZZLE_pqst 2, 3, 0, 1 // Select p, then q, then s, then t in that order.
5089#define SHDR_DETAIL_SWIZZLE_pqsp 2, 3, 0, 2 // Select p, then q, then s, then p in that order.
5090#define SHDR_DETAIL_SWIZZLE_pqsq 2, 3, 0, 3 // Select p, then q, then s, then q in that order.
5091#define SHDR_DETAIL_SWIZZLE_pqts 2, 3, 1, 0 // Select p, then q, then t, then s in that order.
5092#define SHDR_DETAIL_SWIZZLE_pqtt 2, 3, 1, 1 // Select p, then q, then t, then t in that order.
5093#define SHDR_DETAIL_SWIZZLE_pqtp 2, 3, 1, 2 // Select p, then q, then t, then p in that order.
5094#define SHDR_DETAIL_SWIZZLE_pqtq 2, 3, 1, 3 // Select p, then q, then t, then q in that order.
5095#define SHDR_DETAIL_SWIZZLE_pqps 2, 3, 2, 0 // Select p, then q, then p, then s in that order.
5096#define SHDR_DETAIL_SWIZZLE_pqpt 2, 3, 2, 1 // Select p, then q, then p, then t in that order.
5097#define SHDR_DETAIL_SWIZZLE_pqpp 2, 3, 2, 2 // Select p, then q, then p, then p in that order.
5098#define SHDR_DETAIL_SWIZZLE_pqpq 2, 3, 2, 3 // Select p, then q, then p, then q in that order.
5099#define SHDR_DETAIL_SWIZZLE_pqqs 2, 3, 3, 0 // Select p, then q, then q, then s in that order.
5100#define SHDR_DETAIL_SWIZZLE_pqqt 2, 3, 3, 1 // Select p, then q, then q, then t in that order.
5101#define SHDR_DETAIL_SWIZZLE_pqqp 2, 3, 3, 2 // Select p, then q, then q, then p in that order.
5102#define SHDR_DETAIL_SWIZZLE_pqqq 2, 3, 3, 3 // Select p, then q, then q, then q in that order.
5103#define SHDR_DETAIL_SWIZZLE_qsss 3, 0, 0, 0 // Select q, then s, then s, then s in that order.
5104#define SHDR_DETAIL_SWIZZLE_qsst 3, 0, 0, 1 // Select q, then s, then s, then t in that order.
5105#define SHDR_DETAIL_SWIZZLE_qssp 3, 0, 0, 2 // Select q, then s, then s, then p in that order.
5106#define SHDR_DETAIL_SWIZZLE_qssq 3, 0, 0, 3 // Select q, then s, then s, then q in that order.
5107#define SHDR_DETAIL_SWIZZLE_qsts 3, 0, 1, 0 // Select q, then s, then t, then s in that order.
5108#define SHDR_DETAIL_SWIZZLE_qstt 3, 0, 1, 1 // Select q, then s, then t, then t in that order.
5109#define SHDR_DETAIL_SWIZZLE_qstp 3, 0, 1, 2 // Select q, then s, then t, then p in that order.
5110#define SHDR_DETAIL_SWIZZLE_qstq 3, 0, 1, 3 // Select q, then s, then t, then q in that order.
5111#define SHDR_DETAIL_SWIZZLE_qsps 3, 0, 2, 0 // Select q, then s, then p, then s in that order.
5112#define SHDR_DETAIL_SWIZZLE_qspt 3, 0, 2, 1 // Select q, then s, then p, then t in that order.
5113#define SHDR_DETAIL_SWIZZLE_qspp 3, 0, 2, 2 // Select q, then s, then p, then p in that order.
5114#define SHDR_DETAIL_SWIZZLE_qspq 3, 0, 2, 3 // Select q, then s, then p, then q in that order.
5115#define SHDR_DETAIL_SWIZZLE_qsqs 3, 0, 3, 0 // Select q, then s, then q, then s in that order.
5116#define SHDR_DETAIL_SWIZZLE_qsqt 3, 0, 3, 1 // Select q, then s, then q, then t in that order.
5117#define SHDR_DETAIL_SWIZZLE_qsqp 3, 0, 3, 2 // Select q, then s, then q, then p in that order.
5118#define SHDR_DETAIL_SWIZZLE_qsqq 3, 0, 3, 3 // Select q, then s, then q, then q in that order.
5119#define SHDR_DETAIL_SWIZZLE_qtss 3, 1, 0, 0 // Select q, then t, then s, then s in that order.
5120#define SHDR_DETAIL_SWIZZLE_qtst 3, 1, 0, 1 // Select q, then t, then s, then t in that order.
5121#define SHDR_DETAIL_SWIZZLE_qtsp 3, 1, 0, 2 // Select q, then t, then s, then p in that order.
5122#define SHDR_DETAIL_SWIZZLE_qtsq 3, 1, 0, 3 // Select q, then t, then s, then q in that order.
5123#define SHDR_DETAIL_SWIZZLE_qtts 3, 1, 1, 0 // Select q, then t, then t, then s in that order.
5124#define SHDR_DETAIL_SWIZZLE_qttt 3, 1, 1, 1 // Select q, then t, then t, then t in that order.
5125#define SHDR_DETAIL_SWIZZLE_qttp 3, 1, 1, 2 // Select q, then t, then t, then p in that order.
5126#define SHDR_DETAIL_SWIZZLE_qttq 3, 1, 1, 3 // Select q, then t, then t, then q in that order.
5127#define SHDR_DETAIL_SWIZZLE_qtps 3, 1, 2, 0 // Select q, then t, then p, then s in that order.
5128#define SHDR_DETAIL_SWIZZLE_qtpt 3, 1, 2, 1 // Select q, then t, then p, then t in that order.
5129#define SHDR_DETAIL_SWIZZLE_qtpp 3, 1, 2, 2 // Select q, then t, then p, then p in that order.
5130#define SHDR_DETAIL_SWIZZLE_qtpq 3, 1, 2, 3 // Select q, then t, then p, then q in that order.
5131#define SHDR_DETAIL_SWIZZLE_qtqs 3, 1, 3, 0 // Select q, then t, then q, then s in that order.
5132#define SHDR_DETAIL_SWIZZLE_qtqt 3, 1, 3, 1 // Select q, then t, then q, then t in that order.
5133#define SHDR_DETAIL_SWIZZLE_qtqp 3, 1, 3, 2 // Select q, then t, then q, then p in that order.
5134#define SHDR_DETAIL_SWIZZLE_qtqq 3, 1, 3, 3 // Select q, then t, then q, then q in that order.
5135#define SHDR_DETAIL_SWIZZLE_qpss 3, 2, 0, 0 // Select q, then p, then s, then s in that order.
5136#define SHDR_DETAIL_SWIZZLE_qpst 3, 2, 0, 1 // Select q, then p, then s, then t in that order.
5137#define SHDR_DETAIL_SWIZZLE_qpsp 3, 2, 0, 2 // Select q, then p, then s, then p in that order.
5138#define SHDR_DETAIL_SWIZZLE_qpsq 3, 2, 0, 3 // Select q, then p, then s, then q in that order.
5139#define SHDR_DETAIL_SWIZZLE_qpts 3, 2, 1, 0 // Select q, then p, then t, then s in that order.
5140#define SHDR_DETAIL_SWIZZLE_qptt 3, 2, 1, 1 // Select q, then p, then t, then t in that order.
5141#define SHDR_DETAIL_SWIZZLE_qptp 3, 2, 1, 2 // Select q, then p, then t, then p in that order.
5142#define SHDR_DETAIL_SWIZZLE_qptq 3, 2, 1, 3 // Select q, then p, then t, then q in that order.
5143#define SHDR_DETAIL_SWIZZLE_qpps 3, 2, 2, 0 // Select q, then p, then p, then s in that order.
5144#define SHDR_DETAIL_SWIZZLE_qppt 3, 2, 2, 1 // Select q, then p, then p, then t in that order.
5145#define SHDR_DETAIL_SWIZZLE_qppp 3, 2, 2, 2 // Select q, then p, then p, then p in that order.
5146#define SHDR_DETAIL_SWIZZLE_qppq 3, 2, 2, 3 // Select q, then p, then p, then q in that order.
5147#define SHDR_DETAIL_SWIZZLE_qpqs 3, 2, 3, 0 // Select q, then p, then q, then s in that order.
5148#define SHDR_DETAIL_SWIZZLE_qpqt 3, 2, 3, 1 // Select q, then p, then q, then t in that order.
5149#define SHDR_DETAIL_SWIZZLE_qpqp 3, 2, 3, 2 // Select q, then p, then q, then p in that order.
5150#define SHDR_DETAIL_SWIZZLE_qpqq 3, 2, 3, 3 // Select q, then p, then q, then q in that order.
5151#define SHDR_DETAIL_SWIZZLE_qqss 3, 3, 0, 0 // Select q, then q, then s, then s in that order.
5152#define SHDR_DETAIL_SWIZZLE_qqst 3, 3, 0, 1 // Select q, then q, then s, then t in that order.
5153#define SHDR_DETAIL_SWIZZLE_qqsp 3, 3, 0, 2 // Select q, then q, then s, then p in that order.
5154#define SHDR_DETAIL_SWIZZLE_qqsq 3, 3, 0, 3 // Select q, then q, then s, then q in that order.
5155#define SHDR_DETAIL_SWIZZLE_qqts 3, 3, 1, 0 // Select q, then q, then t, then s in that order.
5156#define SHDR_DETAIL_SWIZZLE_qqtt 3, 3, 1, 1 // Select q, then q, then t, then t in that order.
5157#define SHDR_DETAIL_SWIZZLE_qqtp 3, 3, 1, 2 // Select q, then q, then t, then p in that order.
5158#define SHDR_DETAIL_SWIZZLE_qqtq 3, 3, 1, 3 // Select q, then q, then t, then q in that order.
5159#define SHDR_DETAIL_SWIZZLE_qqps 3, 3, 2, 0 // Select q, then q, then p, then s in that order.
5160#define SHDR_DETAIL_SWIZZLE_qqpt 3, 3, 2, 1 // Select q, then q, then p, then t in that order.
5161#define SHDR_DETAIL_SWIZZLE_qqpp 3, 3, 2, 2 // Select q, then q, then p, then p in that order.
5162#define SHDR_DETAIL_SWIZZLE_qqpq 3, 3, 2, 3 // Select q, then q, then p, then q in that order.
5163#define SHDR_DETAIL_SWIZZLE_qqqs 3, 3, 3, 0 // Select q, then q, then q, then s in that order.
5164#define SHDR_DETAIL_SWIZZLE_qqqt 3, 3, 3, 1 // Select q, then q, then q, then t in that order.
5165#define SHDR_DETAIL_SWIZZLE_qqqp 3, 3, 3, 2 // Select q, then q, then q, then p in that order.
5166#define SHDR_DETAIL_SWIZZLE_qqqq 3, 3, 3, 3 // Select q, then q, then q, then q in that order.
5167
5168#endif // SHDR_MACROS_HPP
5169
5170#endif // SHDR_SINGLE_HEADER_INCLUDED