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