1 module gfm.opengl.uniform;
2 
3 import std.conv, 
4        std..string,
5        core.stdc..string;
6 
7 import derelict.opengl3.gl3;
8 
9 import gfm.core.log,
10        gfm.math.vector, 
11        gfm.math.matrix,
12        gfm.opengl.opengl;
13 
14 
15 /// Represents an OpenGL program uniform. Owned by a GLProgram.
16 /// Both uniform locations and values are cached, to minimize OpenGL calls.
17 final class GLUniform
18 {
19     public
20     {
21         /// Creates a GLUniform.
22         /// This is done automatically after linking a GLProgram.
23         /// See_also: GLProgram.
24         /// Throws: $(D OpenGLException) on error.
25         this(OpenGL gl, GLuint program, GLenum type, string name, GLsizei size)
26         {
27             _gl = gl;
28             _type = type;
29             _size = size;
30             _name = name;
31 
32             _location = glGetUniformLocation(program, toStringz(name));
33             if (_location == -1)
34             {
35                 // probably rare: the driver said explicitely this variable was active, and there it's not.
36                 throw new OpenGLException(format("can't get uniform %s location", name));
37             }
38 
39             size_t cacheSize = sizeOfUniformType(type) * size;
40             if (cacheSize > 0)
41             {
42                 _value = new ubyte[cacheSize]; // relying on zero initialization here
43                 _valueChanged = false;
44 
45                 _firstSet = true;
46                 _disabled = false;
47             }
48             else
49             {
50                 _gl._logger.warningf("uniform %s is unrecognized or has size 0, disabled", _name);
51                 _disabled = true;
52             }
53         }
54 
55         /// Creates a fake disabled uniform variable, designed to cope with variables 
56         /// that have been optimized out by the OpenGL driver, or those which do not exist.
57         this(OpenGL gl, string name)
58         {
59             _gl = gl;
60             _disabled = true;
61             _gl._logger.warningf("creating fake uniform '%s' which either does not exist in the shader program, or was discarded by the driver as unused", name);
62         }
63 
64         /// Sets a uniform variable value.
65         /// T should be the exact type needed, checked at runtime.
66         /// Throws: $(D OpenGLException) on error.
67         void set(T)(T newValue)
68         {
69             set!T(&newValue, 1u);
70         }
71 
72         /// Sets multiple uniform variables.
73         /// Throws: $(D OpenGLException) on error.
74         void set(T)(T[] newValues)
75         {
76             set!T(newValues.ptr, newValues.length);
77         }
78 
79         /// Sets multiple uniform variables.
80         /// Throws: $(D OpenGLException) on error.
81         void set(T)(T* newValues, size_t count)
82         {
83             if (_disabled)
84                 return;
85 
86             if (!typeIsCompliant!T(_type))
87                 throw new OpenGLException(format("using type %s for setting uniform '%s' which has GLSL type '%s'", 
88                                                  T.stringof, _name, GLSLTypeNameArray(_type, _size)));
89 
90             if (count != _size)
91                 throw new OpenGLException(format("cannot set uniform '%s' of size %s with a value of size %s", 
92                                                  _name, _size, count));
93 
94             // if first time or different value incoming
95             if (_firstSet || (0 != memcmp(newValues, _value.ptr, _value.length)))
96             {
97                 memcpy(_value.ptr, newValues, _value.length);
98                 _valueChanged = true;
99 
100                 if (_shouldUpdateImmediately)
101                     update();
102             }
103 
104             _firstSet = false;
105         }
106     
107         /// Updates the uniform value.
108         void use()
109         {
110             _shouldUpdateImmediately = true;
111             update();
112         }       
113 
114         /// Unuses this uniform..
115         void unuse()
116         {
117             _shouldUpdateImmediately = false;
118         }
119     }
120 
121     private
122     {
123         OpenGL _gl;
124         GLint _location;
125         GLenum _type;
126         GLsizei _size;
127         ubyte[] _value;
128         bool _valueChanged;
129         bool _firstSet; // force update to ensure we do not relie on the driver initializing uniform to zero
130         bool _disabled; // allow transparent usage while not doing anything
131         bool _shouldUpdateImmediately;
132         string _name;
133 
134         void update()
135         {
136             if (_disabled)
137                 return;
138 
139             // safety check to prevent defaults values in uniforms
140             if (_firstSet)
141             {
142                 _gl._logger.warningf("uniform '%s' left to default value, driver will probably zero it", _name);
143                 _firstSet = false;
144             }
145 
146             // has value changed?
147             // if so, set OpenGL value
148             if (_valueChanged)
149             {
150                 setUniform();
151                 _valueChanged = false;
152             }
153         }
154 
155         void setUniform()
156         {
157             switch(_type)
158             {
159                 case GL_FLOAT:      glUniform1fv(_location, _size, cast(GLfloat*)_value); break;
160                 case GL_FLOAT_VEC2: glUniform2fv(_location, _size, cast(GLfloat*)_value); break;
161                 case GL_FLOAT_VEC3: glUniform3fv(_location, _size, cast(GLfloat*)_value); break;
162                 case GL_FLOAT_VEC4: glUniform4fv(_location, _size, cast(GLfloat*)_value); break;
163                 case GL_DOUBLE:      glUniform1dv(_location, _size, cast(GLdouble*)_value); break;
164                 case GL_DOUBLE_VEC2: glUniform2dv(_location, _size, cast(GLdouble*)_value); break;
165                 case GL_DOUBLE_VEC3: glUniform3dv(_location, _size, cast(GLdouble*)_value); break;
166                 case GL_DOUBLE_VEC4: glUniform4dv(_location, _size, cast(GLdouble*)_value); break;
167                 case GL_INT:      glUniform1iv(_location, _size, cast(GLint*)_value); break;
168                 case GL_INT_VEC2: glUniform2iv(_location, _size, cast(GLint*)_value); break;
169                 case GL_INT_VEC3: glUniform3iv(_location, _size, cast(GLint*)_value); break;
170                 case GL_INT_VEC4: glUniform4iv(_location, _size, cast(GLint*)_value); break;
171                 case GL_UNSIGNED_INT:      glUniform1uiv(_location, _size, cast(GLuint*)_value); break;
172                 case GL_UNSIGNED_INT_VEC2: glUniform2uiv(_location, _size, cast(GLuint*)_value); break;
173                 case GL_UNSIGNED_INT_VEC3: glUniform3uiv(_location, _size, cast(GLuint*)_value); break;
174                 case GL_UNSIGNED_INT_VEC4: glUniform4uiv(_location, _size, cast(GLuint*)_value); break;
175                 case GL_BOOL:      glUniform1iv(_location, _size, cast(GLint*)_value); break;
176                 case GL_BOOL_VEC2: glUniform2iv(_location, _size, cast(GLint*)_value); break;
177                 case GL_BOOL_VEC3: glUniform3iv(_location, _size, cast(GLint*)_value); break;
178                 case GL_BOOL_VEC4: glUniform4iv(_location, _size, cast(GLint*)_value); break;
179                 case GL_FLOAT_MAT2:   glUniformMatrix2fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
180                 case GL_FLOAT_MAT3:   glUniformMatrix3fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
181                 case GL_FLOAT_MAT4:   glUniformMatrix4fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
182                 case GL_FLOAT_MAT2x3: glUniformMatrix2x3fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
183                 case GL_FLOAT_MAT2x4: glUniformMatrix3x2fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
184                 case GL_FLOAT_MAT3x2: glUniformMatrix2x4fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
185                 case GL_FLOAT_MAT3x4: glUniformMatrix4x2fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
186                 case GL_FLOAT_MAT4x2: glUniformMatrix3x4fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
187                 case GL_FLOAT_MAT4x3: glUniformMatrix4x3fv(_location, _size, GL_TRUE, cast(GLfloat*)_value); break;
188                 case GL_DOUBLE_MAT2:   glUniformMatrix2dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
189                 case GL_DOUBLE_MAT3:   glUniformMatrix3dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
190                 case GL_DOUBLE_MAT4:   glUniformMatrix4dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
191                 case GL_DOUBLE_MAT2x3: glUniformMatrix2x3dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
192                 case GL_DOUBLE_MAT2x4: glUniformMatrix3x2dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
193                 case GL_DOUBLE_MAT3x2: glUniformMatrix2x4dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
194                 case GL_DOUBLE_MAT3x4: glUniformMatrix4x2dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
195                 case GL_DOUBLE_MAT4x2: glUniformMatrix3x4dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
196                 case GL_DOUBLE_MAT4x3: glUniformMatrix4x3dv(_location, _size, GL_TRUE, cast(GLdouble*)_value); break;
197 
198                 // image samplers
199                 case GL_IMAGE_1D: .. case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
200                     glUniform1iv(_location, _size, cast(GLint*)_value);
201                     break;
202 
203                 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
204                     glUniform1uiv(_location, _size, cast(GLuint*)_value);
205                     break;
206 
207                 case GL_SAMPLER_1D:
208                 case GL_SAMPLER_2D:
209                 case GL_SAMPLER_3D:
210                 case GL_SAMPLER_CUBE:
211                 case GL_SAMPLER_1D_SHADOW:
212                 case GL_SAMPLER_2D_SHADOW:
213                 case GL_SAMPLER_1D_ARRAY:
214                 case GL_SAMPLER_2D_ARRAY:
215                 case GL_SAMPLER_1D_ARRAY_SHADOW:
216                 case GL_SAMPLER_2D_ARRAY_SHADOW:
217                 case GL_SAMPLER_2D_MULTISAMPLE:
218                 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
219                 case GL_SAMPLER_CUBE_SHADOW:
220                 case GL_SAMPLER_BUFFER:
221                 case GL_SAMPLER_2D_RECT:
222                 case GL_SAMPLER_2D_RECT_SHADOW:
223                 case GL_INT_SAMPLER_1D:
224                 case GL_INT_SAMPLER_2D:
225                 case GL_INT_SAMPLER_3D:
226                 case GL_INT_SAMPLER_CUBE:
227                 case GL_INT_SAMPLER_1D_ARRAY:
228                 case GL_INT_SAMPLER_2D_ARRAY:
229                 case GL_INT_SAMPLER_2D_MULTISAMPLE:
230                 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
231                 case GL_INT_SAMPLER_BUFFER:
232                 case GL_INT_SAMPLER_2D_RECT:
233                 case GL_UNSIGNED_INT_SAMPLER_1D:
234                 case GL_UNSIGNED_INT_SAMPLER_2D:
235                 case GL_UNSIGNED_INT_SAMPLER_3D:
236                 case GL_UNSIGNED_INT_SAMPLER_CUBE:
237                 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
238                 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
239                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
240                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
241                 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
242                 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
243                     glUniform1iv(_location, _size, cast(GLint*)_value);
244                     break;
245 
246                 default: 
247                     break;
248             }
249             _gl.runtimeCheck();
250         }
251 
252         public static bool typeIsCompliant(T)(GLenum type)
253         {
254             switch (type)
255             {
256                 case GL_FLOAT:      return is(T == float);
257                 case GL_FLOAT_VEC2: return is(T == vec2f);
258                 case GL_FLOAT_VEC3: return is(T == vec3f);
259                 case GL_FLOAT_VEC4: return is(T == vec4f);
260                 case GL_DOUBLE:      return is(T == double);
261                 case GL_DOUBLE_VEC2: return is(T == vec2d);
262                 case GL_DOUBLE_VEC3: return is(T == vec3d);
263                 case GL_DOUBLE_VEC4: return is(T == vec4d);
264                 case GL_INT:      return is(T == int);
265                 case GL_INT_VEC2: return is(T == vec2i);
266                 case GL_INT_VEC3: return is(T == vec3i);
267                 case GL_INT_VEC4: return is(T == vec4i);
268                 case GL_UNSIGNED_INT:      return is(T == uint);
269                 case GL_UNSIGNED_INT_VEC2: return is(T == vec2ui);
270                 case GL_UNSIGNED_INT_VEC3: return is(T == vec3ui);
271                 case GL_UNSIGNED_INT_VEC4: return is(T == vec4ui);
272                 case GL_BOOL:      return is(T == int); // int because bool type is 1 byte
273                 case GL_BOOL_VEC2: return is(T == vec2i);
274                 case GL_BOOL_VEC3: return is(T == vec3i);
275                 case GL_BOOL_VEC4: return is(T == vec4i);
276                 case GL_FLOAT_MAT2: return is(T == mat2f);
277                 case GL_FLOAT_MAT3: return is(T == mat3f);
278                 case GL_FLOAT_MAT4: return is(T == mat4f);
279                 case GL_FLOAT_MAT2x3: return is(T == mat3x2f);
280                 case GL_FLOAT_MAT2x4: return is(T == mat4x2f);
281                 case GL_FLOAT_MAT3x2: return is(T == mat2x3f);
282                 case GL_FLOAT_MAT3x4: return is(T == mat4x3f);
283                 case GL_FLOAT_MAT4x2: return is(T == mat2x4f);
284                 case GL_FLOAT_MAT4x3: return is(T == mat3x4f);
285                 case GL_DOUBLE_MAT2: return is(T == mat2d);
286                 case GL_DOUBLE_MAT3: return is(T == mat3d);
287                 case GL_DOUBLE_MAT4: return is(T == mat4d);
288                 case GL_DOUBLE_MAT2x3: return is(T == mat3x2d);
289                 case GL_DOUBLE_MAT2x4: return is(T == mat4x2d);
290                 case GL_DOUBLE_MAT3x2: return is(T == mat2x3d);
291                 case GL_DOUBLE_MAT3x4: return is(T == mat4x3d);
292                 case GL_DOUBLE_MAT4x2: return is(T == mat2x4d);
293                 case GL_DOUBLE_MAT4x3: return is(T == mat3x4d);
294 
295                     // image samplers
296                 case GL_IMAGE_1D: .. case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
297                     return is(T == int);
298 
299                 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
300                     return is(T == uint);
301 
302                 case GL_SAMPLER_1D:
303                 case GL_SAMPLER_2D:
304                 case GL_SAMPLER_3D:
305                 case GL_SAMPLER_CUBE:
306                 case GL_SAMPLER_1D_SHADOW:
307                 case GL_SAMPLER_2D_SHADOW:
308                 case GL_SAMPLER_1D_ARRAY:
309                 case GL_SAMPLER_2D_ARRAY:
310                 case GL_SAMPLER_1D_ARRAY_SHADOW:
311                 case GL_SAMPLER_2D_ARRAY_SHADOW:
312                 case GL_SAMPLER_2D_MULTISAMPLE:
313                 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
314                 case GL_SAMPLER_CUBE_SHADOW:
315                 case GL_SAMPLER_BUFFER:
316                 case GL_SAMPLER_2D_RECT:
317                 case GL_SAMPLER_2D_RECT_SHADOW:
318                 case GL_INT_SAMPLER_1D:
319                 case GL_INT_SAMPLER_2D:
320                 case GL_INT_SAMPLER_3D:
321                 case GL_INT_SAMPLER_CUBE:
322                 case GL_INT_SAMPLER_1D_ARRAY:
323                 case GL_INT_SAMPLER_2D_ARRAY:
324                 case GL_INT_SAMPLER_2D_MULTISAMPLE:
325                 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
326                 case GL_INT_SAMPLER_BUFFER:
327                 case GL_INT_SAMPLER_2D_RECT:
328                 case GL_UNSIGNED_INT_SAMPLER_1D:
329                 case GL_UNSIGNED_INT_SAMPLER_2D:
330                 case GL_UNSIGNED_INT_SAMPLER_3D:
331                 case GL_UNSIGNED_INT_SAMPLER_CUBE:
332                 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
333                 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
334                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
335                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
336                 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
337                 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
338                     return is(T == int);
339 
340                 default:
341                     // unrecognized type, in release mode return true
342                     debug
343                     {
344                         assert(false);
345                     }
346                     else
347                     {
348                         return true;
349                     }
350             }
351         }
352 
353         public static size_t sizeOfUniformType(GLenum type)
354         {
355             switch (type)
356             {
357                 case GL_FLOAT:      return float.sizeof;
358                 case GL_FLOAT_VEC2: return vec2f.sizeof;
359                 case GL_FLOAT_VEC3: return vec3f.sizeof;
360                 case GL_FLOAT_VEC4: return vec4f.sizeof;
361                 case GL_DOUBLE:      return double.sizeof;
362                 case GL_DOUBLE_VEC2: return vec2d.sizeof;
363                 case GL_DOUBLE_VEC3: return vec3d.sizeof;
364                 case GL_DOUBLE_VEC4: return vec4d.sizeof;
365                 case GL_INT:      return int.sizeof;
366                 case GL_INT_VEC2: return vec2i.sizeof;
367                 case GL_INT_VEC3: return vec3i.sizeof;
368                 case GL_INT_VEC4: return vec4i.sizeof;
369                 case GL_UNSIGNED_INT:      return uint.sizeof;
370                 case GL_UNSIGNED_INT_VEC2: return vec2ui.sizeof;
371                 case GL_UNSIGNED_INT_VEC3: return vec3ui.sizeof;
372                 case GL_UNSIGNED_INT_VEC4: return vec4ui.sizeof;
373                 case GL_BOOL:      return int.sizeof; // int because D bool type is 1 byte
374                 case GL_BOOL_VEC2: return vec2i.sizeof;
375                 case GL_BOOL_VEC3: return vec3i.sizeof;
376                 case GL_BOOL_VEC4: return vec4i.sizeof;
377                 case GL_FLOAT_MAT2: return mat2f.sizeof;
378                 case GL_FLOAT_MAT3: return mat3f.sizeof;
379                 case GL_FLOAT_MAT4: return mat4f.sizeof;
380                 case GL_FLOAT_MAT2x3: return mat3x2f.sizeof;
381                 case GL_FLOAT_MAT2x4: return mat4x2f.sizeof;
382                 case GL_FLOAT_MAT3x2: return mat2x3f.sizeof;
383                 case GL_FLOAT_MAT3x4: return mat4x3f.sizeof;
384                 case GL_FLOAT_MAT4x2: return mat2x4f.sizeof;
385                 case GL_FLOAT_MAT4x3: return mat3x4f.sizeof;
386                 case GL_DOUBLE_MAT2: return mat2d.sizeof;
387                 case GL_DOUBLE_MAT3: return mat3d.sizeof;
388                 case GL_DOUBLE_MAT4: return mat4d.sizeof;
389                 case GL_DOUBLE_MAT2x3: return mat3x2d.sizeof;
390                 case GL_DOUBLE_MAT2x4: return mat4x2d.sizeof;
391                 case GL_DOUBLE_MAT3x2: return mat2x3d.sizeof;
392                 case GL_DOUBLE_MAT3x4: return mat4x3d.sizeof;
393                 case GL_DOUBLE_MAT4x2: return mat2x4d.sizeof;
394                 case GL_DOUBLE_MAT4x3: return mat3x4d.sizeof;
395 
396                     // image samplers
397                 case GL_IMAGE_1D: .. case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
398                     return int.sizeof;
399 
400                 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
401                     return uint.sizeof;
402 
403                 case GL_SAMPLER_1D:
404                 case GL_SAMPLER_2D:
405                 case GL_SAMPLER_3D:
406                 case GL_SAMPLER_CUBE:
407                 case GL_SAMPLER_1D_SHADOW:
408                 case GL_SAMPLER_2D_SHADOW:
409                 case GL_SAMPLER_1D_ARRAY:
410                 case GL_SAMPLER_2D_ARRAY:
411                 case GL_SAMPLER_1D_ARRAY_SHADOW:
412                 case GL_SAMPLER_2D_ARRAY_SHADOW:
413                 case GL_SAMPLER_2D_MULTISAMPLE:
414                 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
415                 case GL_SAMPLER_CUBE_SHADOW:
416                 case GL_SAMPLER_BUFFER:
417                 case GL_SAMPLER_2D_RECT:
418                 case GL_SAMPLER_2D_RECT_SHADOW:
419                 case GL_INT_SAMPLER_1D:
420                 case GL_INT_SAMPLER_2D:
421                 case GL_INT_SAMPLER_3D:
422                 case GL_INT_SAMPLER_CUBE:
423                 case GL_INT_SAMPLER_1D_ARRAY:
424                 case GL_INT_SAMPLER_2D_ARRAY:
425                 case GL_INT_SAMPLER_2D_MULTISAMPLE:
426                 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
427                 case GL_INT_SAMPLER_BUFFER:
428                 case GL_INT_SAMPLER_2D_RECT:
429                 case GL_UNSIGNED_INT_SAMPLER_1D:
430                 case GL_UNSIGNED_INT_SAMPLER_2D:
431                 case GL_UNSIGNED_INT_SAMPLER_3D:
432                 case GL_UNSIGNED_INT_SAMPLER_CUBE:
433                 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
434                 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
435                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
436                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
437                 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
438                 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
439                     return int.sizeof;
440 
441                 default:
442                     // unrecognized type
443                     // in debug mode assert, in release mode return 0 to disable this uniform
444                     debug
445                     {
446                         assert(false);
447                     }
448                     else
449                     {
450                         return 0;
451                     }
452             }
453         }
454 
455         static string GLSLTypeName(GLenum type)
456         {
457             switch (type)
458             {
459                 case GL_FLOAT: return "float";
460                 case GL_FLOAT_VEC2: return "vec2";
461                 case GL_FLOAT_VEC3: return "vec3";
462                 case GL_FLOAT_VEC4: return "vec4";
463                 case GL_DOUBLE: return "double";
464                 case GL_DOUBLE_VEC2: return "dvec2";
465                 case GL_DOUBLE_VEC3: return "dvec3";
466                 case GL_DOUBLE_VEC4: return "dvec4";
467                 case GL_INT: return "int";
468                 case GL_INT_VEC2: return "ivec2";
469                 case GL_INT_VEC3: return "ivec3";
470                 case GL_INT_VEC4: return "ivec4";
471                 case GL_UNSIGNED_INT: return "uint";
472                 case GL_UNSIGNED_INT_VEC2: return "uvec2";
473                 case GL_UNSIGNED_INT_VEC3: return "uvec3";
474                 case GL_UNSIGNED_INT_VEC4: return "uvec4";
475                 case GL_BOOL: return "bool";
476                 case GL_BOOL_VEC2: return "bvec2";
477                 case GL_BOOL_VEC3: return "bvec3";
478                 case GL_BOOL_VEC4: return "bvec4";
479                 case GL_FLOAT_MAT2: return "mat2";
480                 case GL_FLOAT_MAT3: return "mat3";
481                 case GL_FLOAT_MAT4: return "mat4";
482                 case GL_FLOAT_MAT2x3: return "mat2x3";
483                 case GL_FLOAT_MAT2x4: return "mat2x4";
484                 case GL_FLOAT_MAT3x2: return "mat3x2";
485                 case GL_FLOAT_MAT3x4: return "mat3x4";
486                 case GL_FLOAT_MAT4x2: return "mat4x2";
487                 case GL_FLOAT_MAT4x3: return "mat4x3";
488                 case GL_DOUBLE_MAT2: return "dmat2";
489                 case GL_DOUBLE_MAT3: return "dmat3";
490                 case GL_DOUBLE_MAT4: return "dmat4";
491                 case GL_DOUBLE_MAT2x3: return "dmat2x3";
492                 case GL_DOUBLE_MAT2x4: return "dmat2x4";
493                 case GL_DOUBLE_MAT3x2: return "dmat3x2";
494                 case GL_DOUBLE_MAT3x4: return "dmat3x4";
495                 case GL_DOUBLE_MAT4x2: return "dmat4x2";
496                 case GL_DOUBLE_MAT4x3: return "dmat4x3";
497                 case GL_SAMPLER_1D: return "sampler1D";
498                 case GL_SAMPLER_2D: return "sampler2D";
499                 case GL_SAMPLER_3D: return "sampler3D";
500                 case GL_SAMPLER_CUBE: return "samplerCube";
501                 case GL_SAMPLER_1D_SHADOW: return "sampler1DShadow";
502                 case GL_SAMPLER_2D_SHADOW: return "sampler2DShadow";
503                 case GL_SAMPLER_1D_ARRAY: return "sampler1DArray";
504                 case GL_SAMPLER_2D_ARRAY: return "sampler2DArray";
505                 case GL_SAMPLER_1D_ARRAY_SHADOW: return "sampler1DArrayShadow";
506                 case GL_SAMPLER_2D_ARRAY_SHADOW: return "sampler2DArrayShadow";
507                 case GL_SAMPLER_2D_MULTISAMPLE: return "sampler2DMS";
508                 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return "sampler2DMSArray";
509                 case GL_SAMPLER_CUBE_SHADOW: return "samplerCubeShadow";
510                 case GL_SAMPLER_BUFFER: return "samplerBuffer";
511                 case GL_SAMPLER_2D_RECT: return "sampler2DRect";
512                 case GL_SAMPLER_2D_RECT_SHADOW: return "sampler2DRectShadow";
513                 case GL_INT_SAMPLER_1D: return "isampler1D";
514                 case GL_INT_SAMPLER_2D: return "isampler2D";
515                 case GL_INT_SAMPLER_3D: return "isampler3D";
516                 case GL_INT_SAMPLER_CUBE: return "isamplerCube";
517                 case GL_INT_SAMPLER_1D_ARRAY: return "isampler1DArray";
518                 case GL_INT_SAMPLER_2D_ARRAY: return "isampler2DArray";
519                 case GL_INT_SAMPLER_2D_MULTISAMPLE: return "isampler2DMS";
520                 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return "isampler2DMSArray";
521                 case GL_INT_SAMPLER_BUFFER: return "isamplerBuffer";
522                 case GL_INT_SAMPLER_2D_RECT: return "isampler2DRect";
523                 case GL_UNSIGNED_INT_SAMPLER_1D: return "usampler1D";
524                 case GL_UNSIGNED_INT_SAMPLER_2D: return "usampler2D";
525                 case GL_UNSIGNED_INT_SAMPLER_3D: return "usampler3D";
526                 case GL_UNSIGNED_INT_SAMPLER_CUBE: return "usamplerCube";
527                 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return "usampler2DArray";
528                 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return "usampler2DArray";
529                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return "usampler2DMS";
530                 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return "usampler2DMSArray";
531                 case GL_UNSIGNED_INT_SAMPLER_BUFFER: return "usamplerBuffer";
532                 case GL_UNSIGNED_INT_SAMPLER_2D_RECT: return "usampler2DRect";
533                 case GL_IMAGE_1D: return "image1D";
534                 case GL_IMAGE_2D: return "image2D";
535                 case GL_IMAGE_3D: return "image3D";
536                 case GL_IMAGE_2D_RECT: return "image2DRect";
537                 case GL_IMAGE_CUBE: return "imageCube";
538                 case GL_IMAGE_BUFFER: return "imageBuffer";
539                 case GL_IMAGE_1D_ARRAY: return "image1DArray";
540                 case GL_IMAGE_2D_ARRAY: return "image2DArray";
541                 case GL_IMAGE_2D_MULTISAMPLE: return "image2DMS";
542                 case GL_IMAGE_2D_MULTISAMPLE_ARRAY: return "image2DMSArray";
543                 case GL_INT_IMAGE_1D: return "iimage1D";
544                 case GL_INT_IMAGE_2D: return "iimage2D";
545                 case GL_INT_IMAGE_3D: return "iimage3D";
546                 case GL_INT_IMAGE_2D_RECT: return "iimage2DRect";
547                 case GL_INT_IMAGE_CUBE: return "iimageCube";
548                 case GL_INT_IMAGE_BUFFER: return "iimageBuffer";
549                 case GL_INT_IMAGE_1D_ARRAY: return "iimage1DArray";
550                 case GL_INT_IMAGE_2D_ARRAY: return "iimage2DArray";
551                 case GL_INT_IMAGE_2D_MULTISAMPLE: return "iimage2DMS";
552                 case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: return "iimage2DMSArray";
553                 case GL_UNSIGNED_INT_IMAGE_1D: return "uimage1D";
554                 case GL_UNSIGNED_INT_IMAGE_2D: return "uimage2D";
555                 case GL_UNSIGNED_INT_IMAGE_3D: return "uimage3D";
556                 case GL_UNSIGNED_INT_IMAGE_2D_RECT: return "uimage2DRect";
557                 case GL_UNSIGNED_INT_IMAGE_CUBE: return "uimageCube";
558                 case GL_UNSIGNED_INT_IMAGE_BUFFER: return "uimageBuffer";
559                 case GL_UNSIGNED_INT_IMAGE_1D_ARRAY: return "uimage1DArray";
560                 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: return "uimage2DArray";
561                 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: return "uimage2DMS";
562                 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: return "uimage2DMSArray";
563                 case GL_UNSIGNED_INT_ATOMIC_COUNTER: return "atomic_uint";
564                 default:
565                     return "unknown";
566             }
567         }
568 
569         static string GLSLTypeNameArray(GLenum type, size_t multiplicity)
570         {
571             assert(multiplicity > 0);
572             if (multiplicity == 1)
573                 return GLSLTypeName(type);
574             else
575                 return format("%s[%s]", GLSLTypeName(type), multiplicity);
576         }
577     }
578 }
579 
580 static assert(is(GLint == int));
581 static assert(is(GLuint == uint));
582 static assert(is(GLfloat == float));
583 static assert(is(GLdouble == double));