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