2
0

ShaderProgram.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #ifndef ANKI_GL_SHADER_PROGRAM_H
  2. #define ANKI_GL_SHADER_PROGRAM_H
  3. #include "anki/gl/GlObject.h"
  4. #include "anki/util/Dictionary.h"
  5. #include "anki/Math.h"
  6. #include "anki/util/Vector.h"
  7. #include <string>
  8. #include <memory>
  9. namespace anki {
  10. class ShaderProgram;
  11. class ShaderProgramUniformBlock;
  12. class Texture;
  13. /// @addtogroup OpenGL
  14. /// @{
  15. /// Shader program variable. The type is attribute or uniform
  16. class ShaderProgramVariable
  17. {
  18. friend class ShaderProgram;
  19. public:
  20. /// Shader var types
  21. enum ShaderProgramVariableType
  22. {
  23. SPVT_ATTRIBUTE,
  24. SPVT_UNIFORM
  25. };
  26. ShaderProgramVariable(ShaderProgramVariableType type_)
  27. : type(type_)
  28. {}
  29. virtual ~ShaderProgramVariable()
  30. {}
  31. ShaderProgramVariable& operator=(const ShaderProgramVariable& b);
  32. /// @name Accessors
  33. /// @{
  34. const ShaderProgram& getFatherShaderProgram() const
  35. {
  36. return *fatherSProg;
  37. }
  38. GLint getLocation() const
  39. {
  40. return loc;
  41. }
  42. const std::string& getName() const
  43. {
  44. return name;
  45. }
  46. GLenum getGlDataType() const
  47. {
  48. return glDataType;
  49. }
  50. ShaderProgramVariableType getType() const
  51. {
  52. return type;
  53. }
  54. PtrSize getSize() const
  55. {
  56. return size;
  57. }
  58. /// @}
  59. private:
  60. GLint loc; ///< GL location
  61. std::string name; ///< The name inside the shader program
  62. /// GL_FLOAT, GL_FLOAT_VEC2 etc. See
  63. /// http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml
  64. GLenum glDataType;
  65. PtrSize size; ///< Its 1 if it is a single or >1 if it is an array
  66. ShaderProgramVariableType type;
  67. /// We need the ShaderProg of this variable mainly for sanity checks
  68. const ShaderProgram* fatherSProg;
  69. };
  70. /// Uniform shader variable
  71. class ShaderProgramUniformVariable: public ShaderProgramVariable
  72. {
  73. friend class ShaderProgramUniformBlock;
  74. friend class ShaderProgram;
  75. public:
  76. ShaderProgramUniformVariable()
  77. : ShaderProgramVariable(SPVT_UNIFORM)
  78. {}
  79. ShaderProgramUniformVariable& operator=(
  80. const ShaderProgramUniformVariable& b);
  81. const ShaderProgramUniformBlock* getUniformBlock() const
  82. {
  83. return block;
  84. }
  85. /// @name Set the var
  86. /// @{
  87. void set(const F32 x) const;
  88. void set(const Vec2& x) const;
  89. void set(const Vec3& x) const
  90. {
  91. set(&x, 1);
  92. }
  93. void set(const Vec4& x) const
  94. {
  95. set(&x, 1);
  96. }
  97. void set(const Mat3& x) const
  98. {
  99. set(&x, 1);
  100. }
  101. void set(const Mat4& x) const
  102. {
  103. set(&x, 1);
  104. }
  105. void set(const Texture& tex) const;
  106. void set(const Texture* const texes[], const U32 count) const;
  107. void set(const F32 x[], U32 size) const;
  108. void set(const Vec2 x[], U32 size) const;
  109. void set(const Vec3 x[], U32 size) const;
  110. void set(const Vec4 x[], U32 size) const;
  111. void set(const Mat3 x[], U32 size) const;
  112. void set(const Mat4 x[], U32 size) const;
  113. /// @tparam Container It could be something like array<F32, X> or
  114. /// vector<Vec2> etc
  115. template<typename Container>
  116. void setContainer(const Container& c) const
  117. {
  118. set(&c[0], c.size());
  119. }
  120. /// @}
  121. /// @name Uniform block setters
  122. /// Write a client memory that represents the uniform block
  123. /// @{
  124. void setClientMemory(void* buff, U32 buffSize,
  125. const F32 arr[], U32 size) const;
  126. void setClientMemory(void* buff, U32 buffSize,
  127. const Vec2 arr[], U32 size) const;
  128. void setClientMemory(void* buff, U32 buffSize,
  129. const Vec3 arr[], U32 size) const;
  130. void setClientMemory(void* buff, U32 buffSize,
  131. const Vec4 arr[], U32 size) const;
  132. void setClientMemory(void* buff, U32 buffSize,
  133. const Mat3 arr[], U32 size) const;
  134. void setClientMemory(void* buff, U32 buffSize,
  135. const Mat4 arr[], U32 size) const;
  136. /// @}
  137. private:
  138. GLuint index;
  139. ShaderProgramUniformBlock* block = nullptr;
  140. /// Offset inside the uniform block. -1 if it's inside the default uniform
  141. /// block
  142. GLint offset = -1;
  143. /// "An array identifying the stride between elements, in basic machine
  144. /// units, of each of the uniforms specified by the corresponding array of
  145. /// uniformIndices is returned. The stride of a uniform associated with
  146. /// the default uniform block is -1. Note that this information only makes
  147. /// sense for uniforms that are arrays. For uniforms that are not arrays,
  148. /// but are declared in a named uniform block, an array stride of zero is
  149. /// returned"
  150. GLint arrayStride = -1;
  151. /// Identifying the stride between columns of a column-major matrix or rows
  152. /// of a row-major matrix
  153. GLint matrixStride = -1;
  154. /// Standard set uniform checks
  155. /// - Check if initialized
  156. /// - if the current shader program is the var's shader program
  157. /// - if the GL driver gives the same location as the one the var has
  158. void doCommonSetCode() const;
  159. /// Do common checks
  160. template<typename T>
  161. void setClientMemorySanityChecks(U32 buffSize, U32 size) const;
  162. /// Do the actual job of setClientMemory
  163. template<typename T>
  164. void setClientMemoryInternal(void* buff_, U32 buffSize,
  165. const T arr[], U32 size) const;
  166. /// Do the actual job of setClientMemory for matrices
  167. template<typename Mat, typename Vec>
  168. void setClientMemoryInternalMatrix(void* buff_, U32 buffSize,
  169. const Mat arr[], U32 size) const;
  170. };
  171. /// Attribute shader program variable
  172. class ShaderProgramAttributeVariable: public ShaderProgramVariable
  173. {
  174. friend class ShaderProgram;
  175. public:
  176. ShaderProgramAttributeVariable()
  177. : ShaderProgramVariable(SPVT_ATTRIBUTE)
  178. {}
  179. };
  180. /// Uniform shader block
  181. class ShaderProgramUniformBlock
  182. {
  183. friend class ShaderProgram;
  184. public:
  185. ShaderProgramUniformBlock()
  186. {}
  187. ShaderProgramUniformBlock(const ShaderProgramUniformBlock& b)
  188. {
  189. operator=(b);
  190. }
  191. ~ShaderProgramUniformBlock()
  192. {}
  193. /// @name Accessors
  194. /// @{
  195. GLuint getIndex() const
  196. {
  197. return index;
  198. }
  199. U32 getSize() const
  200. {
  201. return size;
  202. }
  203. const std::string& getName() const
  204. {
  205. return name;
  206. }
  207. GLuint getBinding() const
  208. {
  209. return bindingPoint;
  210. }
  211. void setBinding(GLuint bp) const
  212. {
  213. // Don't try any opts with existing binding point. Binding points
  214. // should break
  215. glUniformBlockBinding(progId, index, bp);
  216. bindingPoint = bp;
  217. }
  218. /// @}
  219. ShaderProgramUniformBlock& operator=(const ShaderProgramUniformBlock& b);
  220. private:
  221. Vector<ShaderProgramUniformVariable*> uniforms;
  222. GLuint index = GL_INVALID_INDEX;
  223. U32 size = 0; ///< In bytes
  224. std::string name;
  225. /// Ask the program to get you the binding point
  226. mutable GLuint bindingPoint;
  227. GLuint progId; ///< Needed for binding
  228. };
  229. /// Shader program object
  230. class ShaderProgram: public GlObject
  231. {
  232. public:
  233. typedef GlObject Base;
  234. typedef Vector<ShaderProgramUniformVariable>
  235. UniformVariablesContainer;
  236. typedef Vector<ShaderProgramAttributeVariable>
  237. AttributeVariablesContainer;
  238. typedef Vector<ShaderProgramUniformBlock>
  239. UniformBlocksContainer;
  240. /// @name Constructors/Destructor
  241. /// @{
  242. ShaderProgram()
  243. {}
  244. /// Move. It's not movable untill we need it
  245. ShaderProgram(ShaderProgram&& b) = delete;
  246. ShaderProgram(const char* vertSource, const char* tcSource,
  247. const char* teSource, const char* geomSource, const char* fragSource,
  248. const char* compSource,
  249. const char* transformFeedbackVaryings[],
  250. const GLenum xfbBufferMode = GL_SEPARATE_ATTRIBS)
  251. {
  252. create(vertSource, tcSource, teSource, geomSource, fragSource,
  253. compSource, transformFeedbackVaryings, xfbBufferMode);
  254. }
  255. ~ShaderProgram()
  256. {
  257. destroy();
  258. }
  259. /// @}
  260. /// Move deleted. It's not movable untill we need it
  261. ShaderProgram& operator=(ShaderProgram&& b) = delete;
  262. /// @name Accessors
  263. /// @{
  264. const UniformVariablesContainer& getUniformVariables() const
  265. {
  266. ANKI_ASSERT(isCreated());
  267. return unis;
  268. }
  269. const AttributeVariablesContainer& getAttributeVariables() const
  270. {
  271. ANKI_ASSERT(isCreated());
  272. return attribs;
  273. }
  274. /// @}
  275. /// Create the program
  276. /// @param vertSource Vertex shader source
  277. /// @param tcSource Tessellation control shader source. Can be nullptr
  278. /// @param teSource Tessellation evaluation shader source. Can be nullptr
  279. /// @param geomSource Geometry shader source. Can be nullptr
  280. /// @param fragSource Fragment shader source. Can be nullptr
  281. /// @param compSource Compute shader source. Can be nullptr
  282. /// @param xfbVaryings An array of varyings names. Eg
  283. /// {"var0", "var1", nullptr}. Can be nullptr
  284. /// @param xfbBufferMode GL_SEPARATE_ATTRIBS or GL_INTERLEAVED_ATTRIBS
  285. void create(
  286. const char* vertSource, const char* tcSource, const char* teSource,
  287. const char* geomSource, const char* fragSource, const char* compSource,
  288. const char* xfbVaryings[],
  289. const GLenum xfbBufferMode = GL_SEPARATE_ATTRIBS);
  290. /// Bind the shader program
  291. void bind() const
  292. {
  293. ANKI_ASSERT(isCreated());
  294. if(current != this)
  295. {
  296. glUseProgram(glId);
  297. current = this;
  298. }
  299. }
  300. // Unbinds only @a this if its binded
  301. void unbind() const
  302. {
  303. ANKI_ASSERT(isCreated());
  304. if(current == this)
  305. {
  306. glUseProgram(0);
  307. current = nullptr;
  308. }
  309. }
  310. /// @name Variable finders
  311. /// Used to find and return the variable. They return nullptr if the
  312. /// variable is not found
  313. /// @{
  314. const ShaderProgramUniformVariable* tryFindUniformVariable(
  315. const char* varName) const;
  316. const ShaderProgramUniformVariable& findUniformVariable(
  317. const char* varName) const;
  318. const ShaderProgramAttributeVariable* tryFindAttributeVariable(
  319. const char* varName) const;
  320. const ShaderProgramAttributeVariable& findAttributeVariable(
  321. const char* varName) const;
  322. const ShaderProgramUniformBlock* tryFindUniformBlock(
  323. const char* name) const;
  324. const ShaderProgramUniformBlock& findUniformBlock(const char* name) const;
  325. /// @}
  326. static GLuint getCurrentProgramGlId()
  327. {
  328. GLint i;
  329. glGetIntegerv(GL_CURRENT_PROGRAM, &i);
  330. return i;
  331. }
  332. /// For debugging
  333. friend std::ostream& operator<<(std::ostream& s,
  334. const ShaderProgram& x);
  335. private:
  336. typedef Dictionary<ShaderProgramUniformVariable*>
  337. NameToUniVarHashMap;
  338. typedef Dictionary<ShaderProgramAttributeVariable*>
  339. NameToAttribVarHashMap;
  340. typedef Dictionary<ShaderProgramUniformBlock*>
  341. NameToUniformBlockHashMap;
  342. static thread_local const ShaderProgram* current;
  343. GLuint vertShaderGlId = 0; ///< Vertex shader OpenGL id
  344. GLuint tcShaderGlId = 0; ///< Tessellation control shader OpenGL id
  345. GLuint teShaderGlId = 0; ///< Tessellation eval shader OpenGL id
  346. GLuint geomShaderGlId = 0; ///< Geometry shader OpenGL id
  347. GLuint fragShaderGlId = 0; ///< Fragment shader OpenGL id
  348. GLuint compShaderGlId = 0; ///< Compute shader OpenGL id
  349. /// @name Containers
  350. /// @{
  351. UniformVariablesContainer unis;
  352. AttributeVariablesContainer attribs;
  353. NameToUniVarHashMap nameToUniVar; ///< Uniform searching
  354. NameToAttribVarHashMap nameToAttribVar; ///< Attribute searching
  355. UniformBlocksContainer blocks;
  356. NameToUniformBlockHashMap nameToBlock;
  357. /// @}
  358. /// Query the driver to get the vars. After the linking of the shader
  359. /// prog is done gather all the vars in custom containers
  360. void initUniAndAttribVars();
  361. /// Get info about the uniform blocks
  362. void initUniformBlocks();
  363. /// Create and compile shader
  364. /// @return The shader's OpenGL id
  365. /// @exception Exception
  366. static GLuint createAndCompileShader(const char* sourceCode,
  367. const char* preproc, GLenum type);
  368. /// Link the shader program
  369. /// @exception Exception
  370. void link() const;
  371. void destroy();
  372. };
  373. /// @}
  374. } // end namespace anki
  375. #endif