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