1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #include "Rendering/Shaders/Shader.h"
4 #include "Rendering/Shaders/GLSLCopyState.h"
5 #include "Rendering/GL/myGL.h"
6 #include "Rendering/GlobalRendering.h"
7 #include "System/Util.h"
8 #include "System/FileSystem/FileHandler.h"
9 #include "System/Log/ILog.h"
10 #include <algorithm>
11 #ifdef DEBUG
12 	#include <string.h> // strncmp
13 #endif
14 #ifdef HEADLESS
15 	#define GL_INVALID_INDEX -1
16 #endif
17 
18 
19 #define LOG_SECTION_SHADER "Shader"
20 LOG_REGISTER_SECTION_GLOBAL(LOG_SECTION_SHADER)
21 
22 // use the specific section for all LOG*() calls in this source file
23 #ifdef LOG_SECTION_CURRENT
24 	#undef LOG_SECTION_CURRENT
25 #endif
26 #define LOG_SECTION_CURRENT LOG_SECTION_SHADER
27 
28 
29 static std::unordered_map<size_t, GLuint> glslShadersCache;
30 
31 
32 
glslIsValid(GLuint obj)33 static bool glslIsValid(GLuint obj)
34 {
35 	const bool isShader = glIsShader(obj);
36 	assert(glIsShader(obj) || glIsProgram(obj));
37 
38 	GLint compiled;
39 	if (isShader)
40 		glGetShaderiv(obj, GL_COMPILE_STATUS, &compiled);
41 	else
42 		glGetProgramiv(obj, GL_LINK_STATUS, &compiled);
43 
44 	return compiled;
45 }
46 
47 
glslGetLog(GLuint obj)48 static std::string glslGetLog(GLuint obj)
49 {
50 	const bool isShader = glIsShader(obj);
51 	assert(glIsShader(obj) || glIsProgram(obj));
52 
53 	int infologLength = 0;
54 	int maxLength;
55 
56 	if (isShader)
57 		glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &maxLength);
58 	else
59 		glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &maxLength);
60 
61 	std::string infoLog;
62 	infoLog.resize(maxLength);
63 
64 	if (isShader)
65 		glGetShaderInfoLog(obj, maxLength, &infologLength, &infoLog[0]);
66 	else
67 		glGetProgramInfoLog(obj, maxLength, &infologLength, &infoLog[0]);
68 
69 	infoLog.resize(infologLength);
70 	return infoLog;
71 }
72 
73 
GetShaderSource(const std::string & fileName)74 static std::string GetShaderSource(const std::string& fileName)
75 {
76 	std::string soPath = "shaders/" + fileName;
77 	std::string soSource = "";
78 
79 	CFileHandler soFile(soPath);
80 
81 	if (soFile.FileExists()) {
82 		soSource.resize(soFile.FileSize());
83 		soFile.Read(&soSource[0], soFile.FileSize());
84 	} else {
85 		LOG_L(L_ERROR, "[%s] file not found \"%s\"", __FUNCTION__, soPath.c_str());
86 	}
87 
88 	return soSource;
89 }
90 
ExtractGlslVersion(std::string * src,std::string * version)91 static bool ExtractGlslVersion(std::string* src, std::string* version)
92 {
93 	const auto pos = src->find("#version ");
94 
95 	if (pos != std::string::npos) {
96 		const auto eol = src->find('\n', pos) + 1;
97 		*version = src->substr(pos, eol - pos);
98 		src->erase(pos, eol - pos);
99 		return true;
100 	}
101 	return false;
102 }
103 
104 
105 
106 
107 namespace Shader {
108 	static NullShaderObject nullShaderObject_(0, "");
109 	static NullProgramObject nullProgramObject_("NullProgram");
110 
111 	NullShaderObject* nullShaderObject = &nullShaderObject_;
112 	NullProgramObject* nullProgramObject = &nullProgramObject_;
113 
114 
ARBShaderObject(unsigned int shType,const std::string & shSrc,const std::string & shSrcDefs)115 	ARBShaderObject::ARBShaderObject(
116 		unsigned int shType,
117 		const std::string& shSrc,
118 		const std::string& shSrcDefs
119 	): IShaderObject(shType, shSrc)
120 	{
121 		assert(globalRendering->haveARB); // non-debug check is done in ShaderHandler
122 		glGenProgramsARB(1, &objID);
123 	}
124 
Compile(bool reloadFromDisk)125 	void ARBShaderObject::Compile(bool reloadFromDisk) {
126 		glEnable(type);
127 
128 		if (reloadFromDisk)
129 			curShaderSrc = GetShaderSource(srcFile);
130 
131 		glBindProgramARB(type, objID);
132 		glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, curShaderSrc.size(), curShaderSrc.c_str());
133 
134 		int errorPos = -1;
135 		int isNative =  0;
136 
137 		glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
138 		glGetProgramivARB(type, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative);
139 
140 		const char* err = (const char*) glGetString(GL_PROGRAM_ERROR_STRING_ARB);
141 
142 		log = std::string((err != NULL)? err: "[NULL]");
143 		valid = (errorPos == -1 && isNative != 0);
144 
145 		glBindProgramARB(type, 0);
146 		glDisable(type);
147 	}
148 
Release()149 	void ARBShaderObject::Release() {
150 		glDeleteProgramsARB(1, &objID);
151 	}
152 
153 
154 
GLSLShaderObject(unsigned int shType,const std::string & shSrcFile,const std::string & shSrcDefs)155 	GLSLShaderObject::GLSLShaderObject(
156 		unsigned int shType,
157 		const std::string& shSrcFile,
158 		const std::string& shSrcDefs
159 	): IShaderObject(shType, shSrcFile, shSrcDefs)
160 	{
161 		assert(globalRendering->haveGLSL); // non-debug check is done in ShaderHandler
162 	}
163 
Compile(bool reloadFromDisk)164 	void GLSLShaderObject::Compile(bool reloadFromDisk) {
165 		if (reloadFromDisk)
166 			curShaderSrc = GetShaderSource(srcFile);
167 
168 		std::string sourceStr = curShaderSrc;
169 		std::string defFlags  = rawDefStrs + "\n" + modDefStrs;
170 		std::string versionStr;
171 
172 		// extract #version pragma and put it on the first line (only allowed there)
173 		// version pragma in definitions overrides version pragma in source (if any)
174 		ExtractGlslVersion(&sourceStr, &versionStr);
175 		ExtractGlslVersion(&defFlags,  &versionStr);
176 		if (!versionStr.empty()) EnsureEndsWith(&versionStr, "\n");
177 		if (!defFlags.empty())   EnsureEndsWith(&defFlags,   "\n");
178 
179 		// NOTE: many definition flags are not set until after shader is compiled
180 		std::vector<const GLchar*> sources = {
181 			"// SHADER VERSION\n",
182 			versionStr.c_str(),
183 			"// SHADER FLAGS\n",
184 			defFlags.c_str(),
185 			"// SHADER SOURCE\n",
186 			"#line 1\n",
187 			sourceStr.c_str()
188 		};
189 
190 		if (objID == 0)
191 			objID = glCreateShader(type);
192 
193 		glShaderSource(objID, sources.size(), &sources[0], NULL);
194 		glCompileShader(objID);
195 
196 		valid = glslIsValid(objID);
197 		log   = glslGetLog(objID);
198 
199 		if (!IsValid()) {
200 			LOG_L(L_WARNING, "[GLSL-SO::%s] shader-object name: %s, compile-log:\n%s\n", __FUNCTION__, srcFile.c_str(), log.c_str());
201 			LOG_L(L_WARNING, "\n%s%s%s%s%s%s%s", sources[0], sources[1], sources[2], sources[3], sources[4], sources[5], sources[6]);
202 		}
203 	}
204 
Release()205 	void GLSLShaderObject::Release() {
206 		glDeleteShader(objID);
207 		objID = 0;
208 	}
209 
210 
211 
IProgramObject(const std::string & poName)212 	IProgramObject::IProgramObject(const std::string& poName): name(poName), objID(0), curHash(0), valid(false), bound(false) {
213 	}
214 
Enable()215 	void IProgramObject::Enable() {
216 		bound = true;
217 	}
218 
Disable()219 	void IProgramObject::Disable() {
220 		bound = false;
221 	}
222 
IsBound() const223 	bool IProgramObject::IsBound() const {
224 		return bound;
225 	}
226 
Release()227 	void IProgramObject::Release() {
228 		for (IShaderObject*& so: shaderObjs) {
229 			so->Release();
230 			delete so;
231 		}
232 
233 		shaderObjs.clear();
234 	}
235 
IsShaderAttached(const IShaderObject * so) const236 	bool IProgramObject::IsShaderAttached(const IShaderObject* so) const {
237 		return (std::find(shaderObjs.begin(), shaderObjs.end(), so) != shaderObjs.end());
238 	}
239 
RecompileIfNeeded()240 	void IProgramObject::RecompileIfNeeded()
241 	{
242 		const unsigned int hash = GetHash();
243 
244 		if (hash == curHash)
245 			return;
246 
247 		// NOTE: this does not preserve the #version pragma
248 		const std::string definitionFlags = GetString();
249 
250 		for (IShaderObject*& so: shaderObjs) {
251 			so->SetDefinitions(definitionFlags);
252 		}
253 
254 		Reload(false);
255 		PrintInfo();
256 	}
257 
PrintInfo()258 	void IProgramObject::PrintInfo()
259 	{
260 		LOG_L(L_DEBUG, "Uniform States for program-object \"%s\":", name.c_str());
261 		LOG_L(L_DEBUG, "Defs:\n %s", GetString().c_str());
262 		LOG_L(L_DEBUG, "Uniforms:");
263 		for (const auto& p : uniformStates) {
264 			const bool curUsed = GetUniformLocation(p.second.GetName()) >= 0;
265 			if (p.second.IsUninit()) {
266 				LOG_L(L_DEBUG, "\t%s: uninitialized used=%i", (p.second.GetName()).c_str(), int(curUsed));
267 			} else {
268 				LOG_L(L_DEBUG, "\t%s: x=float:%f;int:%i y=%f z=%f used=%i", (p.second.GetName()).c_str(), p.second.GetFltValues()[0], p.second.GetIntValues()[0], p.second.GetFltValues()[1], p.second.GetFltValues()[2], int(curUsed));
269 			}
270 		}
271 	}
272 
GetNewUniformState(const std::string name)273 	UniformState* IProgramObject::GetNewUniformState(const std::string name)
274 	{
275 		UniformState* us = &uniformStates.emplace(hashString(name.c_str()), name).first->second;
276 		us->SetLocation(GetUniformLoc(name));
277 	#if DEBUG
278 		if (us->IsLocationValid())
279 			us->SetType(GetUniformType(us->GetLocation()));
280 	#endif
281 		return us;
282 	}
283 
284 
ARBProgramObject(const std::string & poName)285 	ARBProgramObject::ARBProgramObject(const std::string& poName): IProgramObject(poName) {
286 		objID = -1; // not used for ARBProgramObject instances
287 		uniformTarget = -1;
288 	}
289 
SetUniformTarget(int target)290 	void ARBProgramObject::SetUniformTarget(int target) {
291 		uniformTarget = target;
292 	}
GetUnitformTarget()293 	int ARBProgramObject::GetUnitformTarget() {
294 		return uniformTarget;
295 	}
296 
Enable()297 	void ARBProgramObject::Enable() {
298 		RecompileIfNeeded();
299 		for (const IShaderObject* so: shaderObjs) {
300 			glEnable(so->GetType());
301 			glBindProgramARB(so->GetType(), so->GetObjID());
302 		}
303 		IProgramObject::Enable();
304 	}
Disable()305 	void ARBProgramObject::Disable() {
306 		for (const IShaderObject* so: shaderObjs) {
307 			glBindProgramARB(so->GetType(), 0);
308 			glDisable(so->GetType());
309 		}
310 		IProgramObject::Disable();
311 	}
312 
Link()313 	void ARBProgramObject::Link() {
314 		bool shaderObjectsValid = true;
315 
316 		for (const IShaderObject* so: shaderObjs) {
317 			shaderObjectsValid = (shaderObjectsValid && so->IsValid());
318 		}
319 
320 		valid = shaderObjectsValid;
321 	}
Release()322 	void ARBProgramObject::Release() {
323 		IProgramObject::Release();
324 	}
Reload(bool reloadFromDisk)325 	void ARBProgramObject::Reload(bool reloadFromDisk) {
326 
327 	}
328 
GetUniformLoc(const std::string & name)329 	int ARBProgramObject::GetUniformLoc(const std::string& name) {
330 		return -1; //FIXME
331 	}
332 
333 	#define glPEP4f  glProgramEnvParameter4fARB
334 	#define glPEP4fv glProgramEnvParameter4fvARB
SetUniform1i(int idx,int v0)335 	void ARBProgramObject::SetUniform1i(int idx, int   v0                              ) { glPEP4f(uniformTarget, idx, float(v0), float( 0), float( 0), float( 0)); }
SetUniform2i(int idx,int v0,int v1)336 	void ARBProgramObject::SetUniform2i(int idx, int   v0, int   v1                    ) { glPEP4f(uniformTarget, idx, float(v0), float(v1), float( 0), float( 0)); }
SetUniform3i(int idx,int v0,int v1,int v2)337 	void ARBProgramObject::SetUniform3i(int idx, int   v0, int   v1, int   v2          ) { glPEP4f(uniformTarget, idx, float(v0), float(v1), float(v2), float( 0)); }
SetUniform4i(int idx,int v0,int v1,int v2,int v3)338 	void ARBProgramObject::SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3) { glPEP4f(uniformTarget, idx, float(v0), float(v1), float(v2), float(v3)); }
SetUniform1f(int idx,float v0)339 	void ARBProgramObject::SetUniform1f(int idx, float v0                              ) { glPEP4f(uniformTarget, idx, v0, 0.0f, 0.0f, 0.0f); }
SetUniform2f(int idx,float v0,float v1)340 	void ARBProgramObject::SetUniform2f(int idx, float v0, float v1                    ) { glPEP4f(uniformTarget, idx, v0,   v1, 0.0f, 0.0f); }
SetUniform3f(int idx,float v0,float v1,float v2)341 	void ARBProgramObject::SetUniform3f(int idx, float v0, float v1, float v2          ) { glPEP4f(uniformTarget, idx, v0,   v1,   v2, 0.0f); }
SetUniform4f(int idx,float v0,float v1,float v2,float v3)342 	void ARBProgramObject::SetUniform4f(int idx, float v0, float v1, float v2, float v3) { glPEP4f(uniformTarget, idx, v0,   v1,   v2,   v3); }
343 
SetUniform2iv(int idx,const int * v)344 	void ARBProgramObject::SetUniform2iv(int idx, const int*   v) { int   vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] =    0; vv[3] =    0; glPEP4fv(uniformTarget, idx, (float*) vv); }
SetUniform3iv(int idx,const int * v)345 	void ARBProgramObject::SetUniform3iv(int idx, const int*   v) { int   vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] = v[2]; vv[3] =    0; glPEP4fv(uniformTarget, idx, (float*) vv); }
SetUniform4iv(int idx,const int * v)346 	void ARBProgramObject::SetUniform4iv(int idx, const int*   v) { int   vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] = v[2]; vv[3] = v[3]; glPEP4fv(uniformTarget, idx, (float*) vv); }
SetUniform2fv(int idx,const float * v)347 	void ARBProgramObject::SetUniform2fv(int idx, const float* v) { float vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] = 0.0f; vv[3] = 0.0f; glPEP4fv(uniformTarget, idx,          vv); }
SetUniform3fv(int idx,const float * v)348 	void ARBProgramObject::SetUniform3fv(int idx, const float* v) { float vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] = v[2]; vv[3] = 0.0f; glPEP4fv(uniformTarget, idx,          vv); }
SetUniform4fv(int idx,const float * v)349 	void ARBProgramObject::SetUniform4fv(int idx, const float* v) { float vv[4]; vv[0] = v[0]; vv[1] = v[1]; vv[2] = v[2]; vv[3] = v[3]; glPEP4fv(uniformTarget, idx,          vv); }
350 	#undef glPEP4f
351 	#undef glPEP4fv
352 
AttachShaderObject(IShaderObject * so)353 	void ARBProgramObject::AttachShaderObject(IShaderObject* so) {
354 		if (so != NULL) {
355 			IProgramObject::AttachShaderObject(so);
356 		}
357 	}
358 
359 
360 
GLSLProgramObject(const std::string & poName)361 	GLSLProgramObject::GLSLProgramObject(const std::string& poName): IProgramObject(poName) {
362 		objID = 0;
363 		objID = glCreateProgram();
364 	}
365 
Enable()366 	void GLSLProgramObject::Enable() { RecompileIfNeeded(); glUseProgram(objID); IProgramObject::Enable(); }
Disable()367 	void GLSLProgramObject::Disable() { glUseProgram(0); IProgramObject::Disable(); }
368 
Link()369 	void GLSLProgramObject::Link() {
370 		RecompileIfNeeded();
371 		assert(glIsProgram(objID));
372 
373 		if (!glIsProgram(objID))
374 			return;
375 
376 		glLinkProgram(objID);
377 
378 		valid = glslIsValid(objID);
379 		log += glslGetLog(objID);
380 
381 		if (!IsValid()) {
382 			LOG_L(L_WARNING, "[GLSL-PO::%s] program-object name: %s, link-log:\n%s\n", __FUNCTION__, name.c_str(), log.c_str());
383 		}
384 	}
385 
Validate()386 	void GLSLProgramObject::Validate() {
387 		GLint validated = 0;
388 
389 		glValidateProgram(objID);
390 		glGetProgramiv(objID, GL_VALIDATE_STATUS, &validated);
391 
392 		// append the validation-log
393 		log += glslGetLog(objID);
394 
395 		valid = valid && bool(validated);
396 
397 	#ifdef DEBUG
398 		GLsizei numUniforms, maxUniformNameLength;
399 		glGetProgramiv(objID, GL_ACTIVE_UNIFORMS, &numUniforms);
400 		glGetProgramiv(objID, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
401 
402 		if (maxUniformNameLength <= 0)
403 			return;
404 
405 		std::string bufname(maxUniformNameLength, 0);
406 		for (int i = 0; i < numUniforms; ++i) {
407 			GLsizei nameLength = 0;
408 			GLint size = 0;
409 			GLenum type = 0;
410 			glGetActiveUniform(objID, i, maxUniformNameLength, &nameLength, &size, &type, &bufname[0]);
411 			bufname[nameLength] = 0;
412 
413 			if (nameLength == 0)
414 				continue;
415 
416 			if (strncmp(&bufname[0], "gl_", 3) == 0)
417 				continue;
418 
419 			const auto hash = hashString(&bufname[0]);
420 			auto it = uniformStates.find(hash);
421 			if (it != uniformStates.end())
422 				continue;
423 
424 			LOG_L(L_WARNING, "[GLSL-PO::%s] program-object name: %s, unset uniform: %s", __FUNCTION__, name.c_str(), &bufname[0]);
425 			//assert(false);
426 		}
427 	#endif
428 	}
429 
Release()430 	void GLSLProgramObject::Release() {
431 		IProgramObject::Release();
432 
433 		glDeleteProgram(objID);
434 		objID = 0;
435 	}
436 
Reload(bool reloadFromDisk)437 	void GLSLProgramObject::Reload(bool reloadFromDisk) {
438 		const unsigned int oldHash = curHash;
439 		curHash = GetHash();
440 
441 		log = "";
442 		valid = false;
443 
444 		if (GetAttachedShaderObjs().empty()) {
445 			return;
446 		}
447 
448 		GLuint oldProgID = objID;
449 
450 		for (auto& us_pair: uniformStates) {
451 			us_pair.second.SetLocation(GL_INVALID_INDEX);
452 		}
453 
454 		bool deleteOldShader = false;
455 		if (glslShadersCache.find(oldHash) == glslShadersCache.end()) {
456 			glslShadersCache[oldHash] = oldProgID;
457 		} else {
458 			for (IShaderObject*& so: GetAttachedShaderObjs()) {
459 				glDetachShader(oldProgID, so->GetObjID());
460 				so->Release();
461 			}
462 			deleteOldShader = true;
463 		}
464 
465 		auto it = glslShadersCache.find(curHash);
466 		if (it != glslShadersCache.end()) {
467 			objID = it->second;
468 			glslShadersCache.erase(it);
469 		} else {
470 			objID = glCreateProgram();
471 			for (IShaderObject*& so: GetAttachedShaderObjs()) {
472 				so->Compile(reloadFromDisk); //FIXME check if changed or not (when it did, we can't use shader cache!)
473 			}
474 			for (IShaderObject*& so: GetAttachedShaderObjs()) {
475 				if (so->IsValid()) {
476 					glAttachShader(objID, so->GetObjID());
477 				}
478 			}
479 			Link();
480 		}
481 
482 		GLSLCopyState(objID, oldProgID, &((IProgramObject*)(this))->uniformStates);
483 
484 		if (deleteOldShader)
485 			glDeleteProgram(oldProgID);
486 	}
487 
AttachShaderObject(IShaderObject * so)488 	void GLSLProgramObject::AttachShaderObject(IShaderObject* so) {
489 		if (so != NULL) {
490 			assert(!IsShaderAttached(so));
491 			IProgramObject::AttachShaderObject(so);
492 
493 			if (so->IsValid()) {
494 				glAttachShader(objID, so->GetObjID());
495 			}
496 		}
497 	}
498 
GetUniformType(const int loc)499 	int GLSLProgramObject::GetUniformType(const int loc) {
500 		GLint size = 0;
501 		GLenum type = 0;
502 		glGetActiveUniform(objID, loc, 0, nullptr, &size, &type, nullptr);
503 		assert(size == 1); // arrays aren't handled yet
504 		return type;
505 	}
506 
GetUniformLoc(const std::string & name)507 	int GLSLProgramObject::GetUniformLoc(const std::string& name) {
508 		return glGetUniformLocation(objID, name.c_str());
509 	}
510 
SetUniformLocation(const std::string & name)511 	void GLSLProgramObject::SetUniformLocation(const std::string& name) {
512 		uniformLocs.push_back(hashString(name.c_str()));
513 		GetUniformLocation(name);
514 	}
515 
SetUniform(UniformState * uState,int v0)516 	void GLSLProgramObject::SetUniform(UniformState* uState, int   v0)                               { assert(IsBound()); if (uState->Set(v0            )) glUniform1i(uState->GetLocation(), v0             ); }
SetUniform(UniformState * uState,float v0)517 	void GLSLProgramObject::SetUniform(UniformState* uState, float v0)                               { assert(IsBound()); if (uState->Set(v0            )) glUniform1f(uState->GetLocation(), v0             ); }
SetUniform(UniformState * uState,int v0,int v1)518 	void GLSLProgramObject::SetUniform(UniformState* uState, int   v0, int   v1)                     { assert(IsBound()); if (uState->Set(v0, v1        )) glUniform2i(uState->GetLocation(), v0, v1         ); }
SetUniform(UniformState * uState,float v0,float v1)519 	void GLSLProgramObject::SetUniform(UniformState* uState, float v0, float v1)                     { assert(IsBound()); if (uState->Set(v0, v1        )) glUniform2f(uState->GetLocation(), v0, v1         ); }
SetUniform(UniformState * uState,int v0,int v1,int v2)520 	void GLSLProgramObject::SetUniform(UniformState* uState, int   v0, int   v1, int   v2)           { assert(IsBound()); if (uState->Set(v0, v1, v2    )) glUniform3i(uState->GetLocation(), v0, v1, v2     ); }
SetUniform(UniformState * uState,float v0,float v1,float v2)521 	void GLSLProgramObject::SetUniform(UniformState* uState, float v0, float v1, float v2)           { assert(IsBound()); if (uState->Set(v0, v1, v2    )) glUniform3f(uState->GetLocation(), v0, v1, v2     ); }
SetUniform(UniformState * uState,int v0,int v1,int v2,int v3)522 	void GLSLProgramObject::SetUniform(UniformState* uState, int   v0, int   v1, int   v2, int   v3) { assert(IsBound()); if (uState->Set(v0, v1, v2, v3)) glUniform4i(uState->GetLocation(), v0, v1, v2, v3 ); }
SetUniform(UniformState * uState,float v0,float v1,float v2,float v3)523 	void GLSLProgramObject::SetUniform(UniformState* uState, float v0, float v1, float v2, float v3) { assert(IsBound()); if (uState->Set(v0, v1, v2, v3)) glUniform4f(uState->GetLocation(), v0, v1, v2, v3 ); }
524 
SetUniform2v(UniformState * uState,const int * v)525 	void GLSLProgramObject::SetUniform2v(UniformState* uState, const int*   v) { assert(IsBound()); if (uState->Set2v(v)) glUniform2iv(uState->GetLocation(), 1, v); }
SetUniform2v(UniformState * uState,const float * v)526 	void GLSLProgramObject::SetUniform2v(UniformState* uState, const float* v) { assert(IsBound()); if (uState->Set2v(v)) glUniform2fv(uState->GetLocation(), 1, v); }
SetUniform3v(UniformState * uState,const int * v)527 	void GLSLProgramObject::SetUniform3v(UniformState* uState, const int*   v) { assert(IsBound()); if (uState->Set3v(v)) glUniform3iv(uState->GetLocation(), 1, v); }
SetUniform3v(UniformState * uState,const float * v)528 	void GLSLProgramObject::SetUniform3v(UniformState* uState, const float* v) { assert(IsBound()); if (uState->Set3v(v)) glUniform3fv(uState->GetLocation(), 1, v); }
SetUniform4v(UniformState * uState,const int * v)529 	void GLSLProgramObject::SetUniform4v(UniformState* uState, const int*   v) { assert(IsBound()); if (uState->Set4v(v)) glUniform4iv(uState->GetLocation(), 1, v); }
SetUniform4v(UniformState * uState,const float * v)530 	void GLSLProgramObject::SetUniform4v(UniformState* uState, const float* v) { assert(IsBound()); if (uState->Set4v(v)) glUniform4fv(uState->GetLocation(), 1, v); }
531 
SetUniformMatrix2x2(UniformState * uState,bool transp,const float * v)532 	void GLSLProgramObject::SetUniformMatrix2x2(UniformState* uState, bool transp, const float* v) { assert(IsBound()); if (uState->Set2x2(v, transp)) glUniformMatrix2fv(uState->GetLocation(), 1, transp, v); }
SetUniformMatrix3x3(UniformState * uState,bool transp,const float * v)533 	void GLSLProgramObject::SetUniformMatrix3x3(UniformState* uState, bool transp, const float* v) { assert(IsBound()); if (uState->Set3x3(v, transp)) glUniformMatrix3fv(uState->GetLocation(), 1, transp, v); }
SetUniformMatrix4x4(UniformState * uState,bool transp,const float * v)534 	void GLSLProgramObject::SetUniformMatrix4x4(UniformState* uState, bool transp, const float* v) { assert(IsBound()); if (uState->Set4x4(v, transp)) glUniformMatrix4fv(uState->GetLocation(), 1, transp, v); }
535 
SetUniform1i(int idx,int v0)536 	void GLSLProgramObject::SetUniform1i(int idx, int   v0                              ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0            )) glUniform1i(it->second.GetLocation(), v0            ); }
SetUniform2i(int idx,int v0,int v1)537 	void GLSLProgramObject::SetUniform2i(int idx, int   v0, int   v1                    ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1        )) glUniform2i(it->second.GetLocation(), v0, v1        ); }
SetUniform3i(int idx,int v0,int v1,int v2)538 	void GLSLProgramObject::SetUniform3i(int idx, int   v0, int   v1, int   v2          ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1, v2    )) glUniform3i(it->second.GetLocation(), v0, v1, v2    ); }
SetUniform4i(int idx,int v0,int v1,int v2,int v3)539 	void GLSLProgramObject::SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1, v2, v3)) glUniform4i(it->second.GetLocation(), v0, v1, v2, v3); }
SetUniform1f(int idx,float v0)540 	void GLSLProgramObject::SetUniform1f(int idx, float v0                              ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0            )) glUniform1f(it->second.GetLocation(), v0            ); }
SetUniform2f(int idx,float v0,float v1)541 	void GLSLProgramObject::SetUniform2f(int idx, float v0, float v1                    ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1        )) glUniform2f(it->second.GetLocation(), v0, v1        ); }
SetUniform3f(int idx,float v0,float v1,float v2)542 	void GLSLProgramObject::SetUniform3f(int idx, float v0, float v1, float v2          ) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1, v2    )) glUniform3f(it->second.GetLocation(), v0, v1, v2    ); }
SetUniform4f(int idx,float v0,float v1,float v2,float v3)543 	void GLSLProgramObject::SetUniform4f(int idx, float v0, float v1, float v2, float v3) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set(v0, v1, v2, v3)) glUniform4f(it->second.GetLocation(), v0, v1, v2, v3); }
544 
SetUniform2iv(int idx,const int * v)545 	void GLSLProgramObject::SetUniform2iv(int idx, const int*   v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set2v(v)) glUniform2iv(it->second.GetLocation(), 1, v); }
SetUniform3iv(int idx,const int * v)546 	void GLSLProgramObject::SetUniform3iv(int idx, const int*   v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set3v(v)) glUniform3iv(it->second.GetLocation(), 1, v); }
SetUniform4iv(int idx,const int * v)547 	void GLSLProgramObject::SetUniform4iv(int idx, const int*   v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set4v(v)) glUniform4iv(it->second.GetLocation(), 1, v); }
SetUniform2fv(int idx,const float * v)548 	void GLSLProgramObject::SetUniform2fv(int idx, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set2v(v)) glUniform2fv(it->second.GetLocation(), 1, v); }
SetUniform3fv(int idx,const float * v)549 	void GLSLProgramObject::SetUniform3fv(int idx, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set3v(v)) glUniform3fv(it->second.GetLocation(), 1, v); }
SetUniform4fv(int idx,const float * v)550 	void GLSLProgramObject::SetUniform4fv(int idx, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set4v(v)) glUniform4fv(it->second.GetLocation(), 1, v); }
551 
SetUniformMatrix2fv(int idx,bool transp,const float * v)552 	void GLSLProgramObject::SetUniformMatrix2fv(int idx, bool transp, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set2x2(v, transp)) glUniformMatrix2fv(it->second.GetLocation(), 1, transp, v); }
SetUniformMatrix3fv(int idx,bool transp,const float * v)553 	void GLSLProgramObject::SetUniformMatrix3fv(int idx, bool transp, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set3x3(v, transp)) glUniformMatrix3fv(it->second.GetLocation(), 1, transp, v); }
SetUniformMatrix4fv(int idx,bool transp,const float * v)554 	void GLSLProgramObject::SetUniformMatrix4fv(int idx, bool transp, const float* v) { assert(IsBound()); auto it = uniformStates.find(uniformLocs[idx]); if (it != uniformStates.end() && it->second.Set4x4(v, transp)) glUniformMatrix4fv(it->second.GetLocation(), 1, transp, v); }
SetUniformMatrixArray4fv(int idx,int count,bool transp,const float * v)555 	void GLSLProgramObject::SetUniformMatrixArray4fv(int idx, int count, bool transp, const float* v) { assert(IsBound()); /*glUniformMatrix4fv(it->second.GetLocation(), count, transp, v);*/ }
556 
557 	#ifdef glUniformMatrix2dv
SetUniformMatrix2dv(int idx,bool transp,const double * v)558 	void GLSLProgramObject::SetUniformMatrix2dv(int idx, bool transp, const double* v) { /*glUniformMatrix2dv(it->second.GetLocation(), 1, transp, v);*/ }
559 	#else
SetUniformMatrix2dv(int idx,bool transp,const double * v)560 	void GLSLProgramObject::SetUniformMatrix2dv(int idx, bool transp, const double* v) {}
561 	#endif
562 	#ifdef glUniformMatrix3dv
SetUniformMatrix3dv(int idx,bool transp,const double * v)563 	void GLSLProgramObject::SetUniformMatrix3dv(int idx, bool transp, const double* v) { /*glUniformMatrix3dv(it->second.GetLocation(), 1, transp, v);*/ }
564 	#else
SetUniformMatrix3dv(int idx,bool transp,const double * v)565 	void GLSLProgramObject::SetUniformMatrix3dv(int idx, bool transp, const double* v) {}
566 	#endif
567 	#ifdef glUniformMatrix4dv
SetUniformMatrix4dv(int idx,bool transp,const double * v)568 	void GLSLProgramObject::SetUniformMatrix4dv(int idx, bool transp, const double* v) { /*glUniformMatrix4dv(it->second.GetLocation(), 1, transp, v);*/ }
569 	#else
SetUniformMatrix4dv(int idx,bool transp,const double * v)570 	void GLSLProgramObject::SetUniformMatrix4dv(int idx, bool transp, const double* v) {}
571 	#endif
572 
573 	#ifdef glUniformMatrix4dv
SetUniformMatrixArray4dv(int idx,int count,bool transp,const double * v)574 	void GLSLProgramObject::SetUniformMatrixArray4dv(int idx, int count, bool transp, const double* v) { /*glUniformMatrix4dv(it->second.GetLocation(), count, transp, v);*/ }
575 	#else
SetUniformMatrixArray4dv(int idx,int count,bool transp,const double * v)576 	void GLSLProgramObject::SetUniformMatrixArray4dv(int idx, int count, bool transp, const double* v) {}
577 	#endif
578 }
579