1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef SPRING_SHADER_HDR
4 #define SPRING_SHADER_HDR
5 
6 #include <string>
7 #include <vector>
8 #include <map>
9 #include <unordered_map>
10 #include "ShaderStates.h"
11 
12 
13 
14 constexpr size_t hashString(const char* str, size_t hash = 5381)
15 {
16 	return (*str) ? hashString(str + 1, hash + (hash << 5) + *str) : hash;
17 }
18 
19 struct fast_hash : public std::unary_function<int, size_t>
20 {
operatorfast_hash21         size_t operator()(const int a) const
22         {
23                 return a;
24         }
25 };
26 
27 namespace Shader {
28 	struct IShaderObject {
29 	public:
30 		IShaderObject(unsigned int shType, const std::string& shSrcFile, const std::string& shSrcDefs = ""):
31 			objID(0), type(shType), valid(false), srcFile(shSrcFile), rawDefStrs(shSrcDefs) {
32 		}
33 
~IShaderObjectIShaderObject34 		virtual ~IShaderObject() {}
35 
CompileIShaderObject36 		virtual void Compile(bool reloadFromDisk) {}
ReleaseIShaderObject37 		virtual void Release() {}
GetObjIDIShaderObject38 		unsigned int GetObjID() const { return objID; }
GetTypeIShaderObject39 		unsigned int GetType() const { return type; }
IsValidIShaderObject40 		bool IsValid() const { return valid; }
GetLogIShaderObject41 		const std::string& GetLog() const { return log; }
42 
SetDefinitionsIShaderObject43 		void SetDefinitions(const std::string& defs) { modDefStrs = defs; }
44 
45 	protected:
46 		unsigned int objID;
47 		unsigned int type;
48 
49 		bool valid;
50 
51 		std::string srcFile;
52 		std::string curShaderSrc;
53 		std::string modDefStrs;
54 		std::string rawDefStrs;
55 		std::string log;
56 	};
57 
58 	struct NullShaderObject: public Shader::IShaderObject {
59 	public:
NullShaderObjectNullShaderObject60 		NullShaderObject(unsigned int shType, const std::string& shSrcFile) : IShaderObject(shType, shSrcFile) {}
61 	};
62 
63 	struct ARBShaderObject: public Shader::IShaderObject {
64 	public:
65 		ARBShaderObject(unsigned int, const std::string&, const std::string& shSrcDefs = "");
66 		void Compile(bool reloadFromDisk);
67 		void Release();
68 	};
69 
70 	struct GLSLShaderObject: public Shader::IShaderObject {
71 	public:
72 		GLSLShaderObject(unsigned int, const std::string&, const std::string& shSrcDefs = "");
73 		void Compile(bool reloadFromDisk);
74 		void Release();
75 	};
76 
77 
78 
79 
80 	struct IProgramObject : public SShaderFlagState {
81 	public:
82 		IProgramObject(const std::string& poName);
~IProgramObjectIProgramObject83 		virtual ~IProgramObject() {}
84 
85 		virtual void Enable();
86 		virtual void Disable();
LinkIProgramObject87 		virtual void Link() {}
ValidateIProgramObject88 		virtual void Validate() {}
89 		virtual void Release() = 0;
90 		virtual void Reload(bool reloadFromDisk) = 0;
91 
92 		void PrintInfo();
93 
94 	private:
95 		virtual int GetUniformLoc(const std::string& name) = 0;
96 		virtual int GetUniformType(const int loc) = 0;
97 
98 	private:
99 		UniformState* GetNewUniformState(const std::string name);
100 
101 	public:
GetUniformLocationIProgramObject102 		int GetUniformLocation(const std::string& name) {
103 			return GetUniformState(name)->GetLocation();
104 		}
105 
GetUniformStateIProgramObject106 		UniformState* GetUniformState(const std::string& name) {
107 			const auto hash = hashString(name.c_str()); // never compiletime const (std::string is never a literal)
108 			auto it = uniformStates.find(hash);
109 			if (it != uniformStates.end())
110 				return &it->second;
111 			return GetNewUniformState(name);
112 		}
GetUniformStateIProgramObject113 		UniformState* GetUniformState(const char* name) {
114 			// (when inlined) hash might be compiletime const cause of constexpr of hashString
115 			// WARNING: Cause of a bug in gcc, you _must_ assign the constexpr to a var before
116 			//          passing it to a function. I.e. foo.find(hashString(name)) would always
117 			//          be runtime evaluated (even when `name` is a literal)!
118 			const auto hash = hashString(name);
119 			auto it = uniformStates.find(hash);
120 			if (it != uniformStates.end())
121 				return &it->second;
122 			return GetNewUniformState(name);
123 		}
124 
125 	public:
SetUniformIProgramObject126 		template<typename TK, typename TV> inline void SetUniform(const TK& name, TV v0) { SetUniform(GetUniformState(name), v0); }
SetUniformIProgramObject127 		template<typename TK, typename TV> inline void SetUniform(const TK& name, TV v0, TV v1)  { SetUniform(GetUniformState(name), v0, v1); }
SetUniformIProgramObject128 		template<typename TK, typename TV> inline void SetUniform(const TK& name, TV v0, TV v1, TV v2)  { SetUniform(GetUniformState(name), v0, v1, v2); }
SetUniformIProgramObject129 		template<typename TK, typename TV> inline void SetUniform(const TK& name, TV v0, TV v1, TV v2, TV v3)  { SetUniform(GetUniformState(name), v0, v1, v2, v3); }
130 
SetUniform2vIProgramObject131 		template<typename TK, typename TV> inline void SetUniform2v(const TK& name, const TV* v) { SetUniform2v(GetUniformState(name), v); }
SetUniform3vIProgramObject132 		template<typename TK, typename TV> inline void SetUniform3v(const TK& name, const TV* v) { SetUniform3v(GetUniformState(name), v); }
SetUniform4vIProgramObject133 		template<typename TK, typename TV> inline void SetUniform4v(const TK& name, const TV* v) { SetUniform4v(GetUniformState(name), v); }
134 
SetUniformMatrix2x2IProgramObject135 		template<typename TK, typename TV> inline void SetUniformMatrix2x2(const TK& name, bool transp, const TV* v) { SetUniformMatrix2x2(GetUniformState(name), transp, v); }
SetUniformMatrix3x3IProgramObject136 		template<typename TK, typename TV> inline void SetUniformMatrix3x3(const TK& name, bool transp, const TV* v) { SetUniformMatrix3x3(GetUniformState(name), transp, v); }
SetUniformMatrix4x4IProgramObject137 		template<typename TK, typename TV> inline void SetUniformMatrix4x4(const TK& name, bool transp, const TV* v) { SetUniformMatrix4x4(GetUniformState(name), transp, v); }
138 
139 
SetUniformIProgramObject140 		virtual void SetUniform(UniformState* uState, int   v0) { SetUniform1i(uState->GetLocation(), v0); }
SetUniformIProgramObject141 		virtual void SetUniform(UniformState* uState, float v0) { SetUniform1f(uState->GetLocation(), v0); }
SetUniformIProgramObject142 		virtual void SetUniform(UniformState* uState, int   v0, int   v1) { SetUniform2i(uState->GetLocation(), v0, v1); }
SetUniformIProgramObject143 		virtual void SetUniform(UniformState* uState, float v0, float v1) { SetUniform2f(uState->GetLocation(), v0, v1); }
SetUniformIProgramObject144 		virtual void SetUniform(UniformState* uState, int   v0, int   v1, int   v2) { SetUniform3i(uState->GetLocation(), v0, v1, v2); }
SetUniformIProgramObject145 		virtual void SetUniform(UniformState* uState, float v0, float v1, float v2) { SetUniform3f(uState->GetLocation(), v0, v1, v2); }
SetUniformIProgramObject146 		virtual void SetUniform(UniformState* uState, int   v0, int   v1, int   v2, int   v3) { SetUniform4i(uState->GetLocation(), v0, v1, v2, v3); }
SetUniformIProgramObject147 		virtual void SetUniform(UniformState* uState, float v0, float v1, float v2, float v3) { SetUniform4f(uState->GetLocation(), v0, v1, v2, v3); }
148 
SetUniform2vIProgramObject149 		virtual void SetUniform2v(UniformState* uState, const int*   v) { SetUniform2iv(uState->GetLocation(), v); }
SetUniform2vIProgramObject150 		virtual void SetUniform2v(UniformState* uState, const float* v) { SetUniform2fv(uState->GetLocation(), v); }
SetUniform3vIProgramObject151 		virtual void SetUniform3v(UniformState* uState, const int*   v) { SetUniform3iv(uState->GetLocation(), v); }
SetUniform3vIProgramObject152 		virtual void SetUniform3v(UniformState* uState, const float* v) { SetUniform3fv(uState->GetLocation(), v); }
SetUniform4vIProgramObject153 		virtual void SetUniform4v(UniformState* uState, const int*   v) { SetUniform4iv(uState->GetLocation(), v); }
SetUniform4vIProgramObject154 		virtual void SetUniform4v(UniformState* uState, const float* v) { SetUniform4fv(uState->GetLocation(), v); }
155 
SetUniformMatrix2x2IProgramObject156 		virtual void SetUniformMatrix2x2(UniformState* uState, bool transp, const float* m) { SetUniformMatrix2fv(uState->GetLocation(), transp, m); }
SetUniformMatrix3x3IProgramObject157 		virtual void SetUniformMatrix3x3(UniformState* uState, bool transp, const float* m) { SetUniformMatrix3fv(uState->GetLocation(), transp, m); }
SetUniformMatrix4x4IProgramObject158 		virtual void SetUniformMatrix4x4(UniformState* uState, bool transp, const float* m) { SetUniformMatrix4fv(uState->GetLocation(), transp, m); }
159 
160 
SetUniformTargetIProgramObject161 		virtual void SetUniformTarget(int) {}
SetUniformLocationIProgramObject162 		virtual void SetUniformLocation(const std::string&) {}
163 
164 		virtual void SetUniform1i(int idx, int   v0) = 0;
165 		virtual void SetUniform2i(int idx, int   v0, int   v1) = 0;
166 		virtual void SetUniform3i(int idx, int   v0, int   v1, int   v2) = 0;
167 		virtual void SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3) = 0;
168 		virtual void SetUniform1f(int idx, float v0) = 0;
169 		virtual void SetUniform2f(int idx, float v0, float v1) = 0;
170 		virtual void SetUniform3f(int idx, float v0, float v1, float v2) = 0;
171 		virtual void SetUniform4f(int idx, float v0, float v1, float v2, float v3) = 0;
172 
173 		virtual void SetUniform2iv(int idx, const int*   v) = 0;
174 		virtual void SetUniform3iv(int idx, const int*   v) = 0;
175 		virtual void SetUniform4iv(int idx, const int*   v) = 0;
176 		virtual void SetUniform2fv(int idx, const float* v) = 0;
177 		virtual void SetUniform3fv(int idx, const float* v) = 0;
178 		virtual void SetUniform4fv(int idx, const float* v) = 0;
179 
SetUniformMatrix2fvIProgramObject180 		virtual void SetUniformMatrix2fv(int idx, bool transp, const float* v) {}
SetUniformMatrix3fvIProgramObject181 		virtual void SetUniformMatrix3fv(int idx, bool transp, const float* v) {}
SetUniformMatrix4fvIProgramObject182 		virtual void SetUniformMatrix4fv(int idx, bool transp, const float* v) {}
183 		//virtual void SetUniformMatrixArray4fv(int idx, int count, bool transp, const float* v) {}
184 
185 		//virtual void SetUniformMatrix2dv(int idx, bool transp, const double* v) {}
186 		//virtual void SetUniformMatrix3dv(int idx, bool transp, const double* v) {}
187 		//virtual void SetUniformMatrix4dv(int idx, bool transp, const double* v) {}
188 		//virtual void SetUniformMatrixArray4dv(int idx, int count, bool transp, const double* v) {}
189 
190 		typedef std::vector<IShaderObject*> SOVec;
191 		typedef SOVec::iterator SOVecIt;
192 		typedef SOVec::const_iterator SOVecConstIt;
193 
AttachShaderObjectIProgramObject194 		virtual void AttachShaderObject(IShaderObject* so) { shaderObjs.push_back(so); }
GetAttachedShaderObjsIProgramObject195 		SOVec& GetAttachedShaderObjs() { return shaderObjs; }
196 
197 		void RecompileIfNeeded();
198 
199 		bool IsBound() const;
200 		bool IsShaderAttached(const IShaderObject* so) const;
IsValidIProgramObject201 		bool IsValid() const { return valid; }
202 
GetObjIDIProgramObject203 		unsigned int GetObjID() const { return objID; }
204 
GetLogIProgramObject205 		const std::string& GetLog() const { return log; }
206 
207 	protected:
208 		std::string name;
209 		std::string log;
210 
211 		unsigned int objID;
212 		unsigned int curHash;
213 
214 		bool valid;
215 		bool bound;
216 		SOVec shaderObjs;
217 	public:
218 		std::unordered_map<std::size_t, UniformState, fast_hash> uniformStates;
219 	};
220 
221 	struct NullProgramObject: public Shader::IProgramObject {
222 	public:
NullProgramObjectNullProgramObject223 		NullProgramObject(const std::string& poName): IProgramObject(poName) {}
EnableNullProgramObject224 		void Enable() {}
DisableNullProgramObject225 		void Disable() {}
ReleaseNullProgramObject226 		void Release() {}
ReloadNullProgramObject227 		void Reload(bool reloadFromDisk) {}
228 
GetUniformLocNullProgramObject229 		int GetUniformLoc(const std::string& name) { return -1; }
GetUniformTypeNullProgramObject230 		int GetUniformType(const int loc) { return -1; }
231 
SetUniform1iNullProgramObject232 		void SetUniform1i(int idx, int   v0) {}
SetUniform2iNullProgramObject233 		void SetUniform2i(int idx, int   v0, int   v1) {}
SetUniform3iNullProgramObject234 		void SetUniform3i(int idx, int   v0, int   v1, int   v2) {}
SetUniform4iNullProgramObject235 		void SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3) {}
SetUniform1fNullProgramObject236 		void SetUniform1f(int idx, float v0) {}
SetUniform2fNullProgramObject237 		void SetUniform2f(int idx, float v0, float v1) {}
SetUniform3fNullProgramObject238 		void SetUniform3f(int idx, float v0, float v1, float v2) {}
SetUniform4fNullProgramObject239 		void SetUniform4f(int idx, float v0, float v1, float v2, float v3) {}
240 
SetUniform2ivNullProgramObject241 		void SetUniform2iv(int idx, const int*   v) {}
SetUniform3ivNullProgramObject242 		void SetUniform3iv(int idx, const int*   v) {}
SetUniform4ivNullProgramObject243 		void SetUniform4iv(int idx, const int*   v) {}
SetUniform2fvNullProgramObject244 		void SetUniform2fv(int idx, const float* v) {}
SetUniform3fvNullProgramObject245 		void SetUniform3fv(int idx, const float* v) {}
SetUniform4fvNullProgramObject246 		void SetUniform4fv(int idx, const float* v) {}
247 	};
248 
249 	struct ARBProgramObject: public Shader::IProgramObject {
250 	public:
251 		ARBProgramObject(const std::string& poName);
252 		void Enable();
253 		void Disable();
254 		void Link();
255 		void Release();
256 		void Reload(bool reloadFromDisk);
257 
258 		int GetUniformLoc(const std::string& name);
GetUniformTypeARBProgramObject259 		int GetUniformType(const int loc) { return -1; }
260 		void SetUniformTarget(int target);
261 		int GetUnitformTarget();
262 
263 		void SetUniform1i(int idx, int   v0);
264 		void SetUniform2i(int idx, int   v0, int   v1);
265 		void SetUniform3i(int idx, int   v0, int   v1, int   v2);
266 		void SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3);
267 		void SetUniform1f(int idx, float v0);
268 		void SetUniform2f(int idx, float v0, float v1);
269 		void SetUniform3f(int idx, float v0, float v1, float v2);
270 		void SetUniform4f(int idx, float v0, float v1, float v2, float v3);
271 
272 		void SetUniform2iv(int idx, const int*   v);
273 		void SetUniform3iv(int idx, const int*   v);
274 		void SetUniform4iv(int idx, const int*   v);
275 		void SetUniform2fv(int idx, const float* v);
276 		void SetUniform3fv(int idx, const float* v);
277 		void SetUniform4fv(int idx, const float* v);
278 
279 		void AttachShaderObject(IShaderObject*);
280 
281 	private:
282 		int uniformTarget;
283 	};
284 
285 	struct GLSLProgramObject: public Shader::IProgramObject {
286 	public:
287 		GLSLProgramObject(const std::string& poName);
288 		void Enable();
289 		void Disable();
290 		void Link();
291 		void Validate();
292 		void Release();
293 		void Reload(bool reloadFromDisk);
294 
295 		int GetUniformType(const int loc);
296 		int GetUniformLoc(const std::string& name);
297 		void SetUniformLocation(const std::string&);
298 
299 		void SetUniform(UniformState* uState, int   v0);
300 		void SetUniform(UniformState* uState, float v0);
301 		void SetUniform(UniformState* uState, int   v0, int   v1);
302 		void SetUniform(UniformState* uState, float v0, float v1);
303 		void SetUniform(UniformState* uState, int   v0, int   v1, int   v2);
304 		void SetUniform(UniformState* uState, float v0, float v1, float v2);
305 		void SetUniform(UniformState* uState, int   v0, int   v1, int   v2, int   v3);
306 		void SetUniform(UniformState* uState, float v0, float v1, float v2, float v3);
307 
308 		void SetUniform2v(UniformState* uState, const int*   v);
309 		void SetUniform2v(UniformState* uState, const float* v);
310 		void SetUniform3v(UniformState* uState, const int*   v);
311 		void SetUniform3v(UniformState* uState, const float* v);
312 		void SetUniform4v(UniformState* uState, const int*   v);
313 		void SetUniform4v(UniformState* uState, const float* v);
314 
315 		void SetUniformMatrix2x2(UniformState* uState, bool transp, const float*  v);
316 		//void SetUniformMatrix2x2(UniformState* uState, bool transp, const double* v);
317 		void SetUniformMatrix3x3(UniformState* uState, bool transp, const float*  v);
318 		//void SetUniformMatrix3x3(UniformState* uState, bool transp, const double* v);
319 		void SetUniformMatrix4x4(UniformState* uState, bool transp, const float*  v);
320 		//void SetUniformMatrix4x4(UniformState* uState, bool transp, const double* v);
321 
322 		void SetUniform1i(int idx, int   v0);
323 		void SetUniform2i(int idx, int   v0, int   v1);
324 		void SetUniform3i(int idx, int   v0, int   v1, int   v2);
325 		void SetUniform4i(int idx, int   v0, int   v1, int   v2, int   v3);
326 		void SetUniform1f(int idx, float v0);
327 		void SetUniform2f(int idx, float v0, float v1);
328 		void SetUniform3f(int idx, float v0, float v1, float v2);
329 		void SetUniform4f(int idx, float v0, float v1, float v2, float v3);
330 
331 		void SetUniform2iv(int idx, const int*   v);
332 		void SetUniform3iv(int idx, const int*   v);
333 		void SetUniform4iv(int idx, const int*   v);
334 		void SetUniform2fv(int idx, const float* v);
335 		void SetUniform3fv(int idx, const float* v);
336 		void SetUniform4fv(int idx, const float* v);
337 
338 		void SetUniformMatrix2fv(int idx, bool transp, const float* v);
339 		void SetUniformMatrix3fv(int idx, bool transp, const float* v);
340 		void SetUniformMatrix4fv(int idx, bool transp, const float* v);
341 		void SetUniformMatrixArray4fv(int idx, int count, bool transp, const float* v);
342 
343 		void SetUniformMatrix2dv(int idx, bool transp, const double* v);
344 		void SetUniformMatrix3dv(int idx, bool transp, const double* v);
345 		void SetUniformMatrix4dv(int idx, bool transp, const double* v);
346 		void SetUniformMatrixArray4dv(int idx, int count, bool transp, const double* v);
347 
348 		void AttachShaderObject(IShaderObject*);
349 
350 	private:
351 		std::vector<size_t> uniformLocs;
352 	};
353 
354 	/*
355 	struct GLSLARBProgramObject: public Shader::IProgramObject {
356 		glCreateProgramObjectARB <==> glCreateProgram
357 		glCreateShaderObjectARB  <==> glCreateShader
358 		glDeleteObjectARB        <==> glDelete{Shader,Program}
359 		glCompileShaderARB       <==> glCompileShader
360 		glShaderSourceARB        <==> glShaderSource
361 		glAttachObjectARB        <==> glAttachShader
362 		glDetachObjectARB        <==> glDetachShader
363 		glLinkProgramARB         <==> glLinkProgram
364 		glUseProgramObjectARB    <==> glUseProgram
365 		glUniform*ARB            <==> glUniform*
366 		glGetUniformLocationARB  <==> glGetUniformLocation
367 	};
368 	*/
369 
370 	extern NullShaderObject* nullShaderObject;
371 	extern NullProgramObject* nullProgramObject;
372 }
373 
374 #endif
375