ShaderProgramImpl.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/gl/ShaderProgramImpl.h>
  6. #include <AnKi/Gr/Shader.h>
  7. #include <AnKi/Gr/gl/ShaderImpl.h>
  8. namespace anki {
  9. static void deletePrograms(GLsizei n, const GLuint* progs)
  10. {
  11. ANKI_ASSERT(n == 1);
  12. ANKI_ASSERT(progs);
  13. glDeleteProgram(*progs);
  14. }
  15. ShaderProgramImpl::~ShaderProgramImpl()
  16. {
  17. destroyDeferred(getManager(), deletePrograms);
  18. m_refl.m_uniforms.destroy(getAllocator());
  19. }
  20. Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
  21. {
  22. m_glName = glCreateProgram();
  23. ANKI_ASSERT(m_glName != 0);
  24. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*vert).getGlName());
  25. m_shaders[ShaderType::kVertex] = vert;
  26. if(tessc)
  27. {
  28. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tessc).getGlName());
  29. m_shaders[ShaderType::kTessellationControl] = tessc;
  30. }
  31. if(tesse)
  32. {
  33. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tesse).getGlName());
  34. m_shaders[ShaderType::kTessellationEvaluation] = tesse;
  35. }
  36. if(geom)
  37. {
  38. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*geom).getGlName());
  39. m_shaders[ShaderType::kGeometry] = geom;
  40. }
  41. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*frag).getGlName());
  42. m_shaders[ShaderType::kFragment] = frag;
  43. return link(static_cast<const ShaderImpl&>(*vert).getGlName(), static_cast<const ShaderImpl&>(*frag).getGlName());
  44. }
  45. Error ShaderProgramImpl::initCompute(ShaderPtr comp)
  46. {
  47. m_glName = glCreateProgram();
  48. ANKI_ASSERT(m_glName != 0);
  49. glAttachShader(m_glName, static_cast<const ShaderImpl&>(*comp).getGlName());
  50. m_shaders[ShaderType::kCompute] = comp;
  51. return link(0, 0);
  52. }
  53. Error ShaderProgramImpl::link(GLuint vert, GLuint frag)
  54. {
  55. Error err = Error::NONE;
  56. glLinkProgram(m_glName);
  57. GLint status = 0;
  58. glGetProgramiv(m_glName, GL_LINK_STATUS, &status);
  59. if(!status)
  60. {
  61. GLint infoLen = 0;
  62. GLint charsWritten = 0;
  63. DynamicArrayAuto<char> infoLogTxt(getAllocator());
  64. glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &infoLen);
  65. infoLogTxt.create(infoLen + 1);
  66. glGetProgramInfoLog(m_glName, infoLen, &charsWritten, &infoLogTxt[0]);
  67. ANKI_GL_LOGE("Link error log follows (vs:%u, fs:%u):\n%s", vert, frag, &infoLogTxt[0]);
  68. err = Error::USER_DATA;
  69. }
  70. return err;
  71. }
  72. const ShaderProgramImplReflection& ShaderProgramImpl::getReflection()
  73. {
  74. if(m_reflInitialized)
  75. {
  76. return m_refl;
  77. }
  78. GLint uniformCount = 0;
  79. glGetProgramiv(getGlName(), GL_ACTIVE_UNIFORMS, &uniformCount);
  80. if(uniformCount)
  81. {
  82. for(U i = 0; i < U(uniformCount); ++i)
  83. {
  84. // Get uniform info
  85. GLsizei len;
  86. GLenum type;
  87. GLint size;
  88. Array<char, 128> name;
  89. glGetActiveUniform(getGlName(), i, sizeof(name), &len, &size, &type, &name[0]);
  90. name[len] = '\0';
  91. if(CString(&name[0]).find("gl_") == 0)
  92. {
  93. // Builtin, skip
  94. continue;
  95. }
  96. // Set type
  97. ShaderVariableDataType akType = ShaderVariableDataType::NONE;
  98. switch(type)
  99. {
  100. case GL_FLOAT_VEC4:
  101. akType = ShaderVariableDataType::VEC4;
  102. break;
  103. case GL_INT_VEC4:
  104. akType = ShaderVariableDataType::IVEC4;
  105. break;
  106. case GL_UNSIGNED_INT_VEC4:
  107. akType = ShaderVariableDataType::UVEC4;
  108. break;
  109. case GL_FLOAT_MAT4:
  110. akType = ShaderVariableDataType::MAT4;
  111. break;
  112. case GL_FLOAT_MAT3:
  113. akType = ShaderVariableDataType::MAT3;
  114. break;
  115. default:
  116. // Unsupported type, skip as well
  117. continue;
  118. }
  119. const GLint location = glGetUniformLocation(getGlName(), &name[0]);
  120. if(location < 0)
  121. {
  122. // Uniform block maybe, skip
  123. continue;
  124. }
  125. // Store
  126. ShaderProgramImplReflection::Uniform uni;
  127. uni.m_location = location;
  128. uni.m_type = akType;
  129. uni.m_arrSize = size;
  130. m_refl.m_uniforms.emplaceBack(getAllocator(), uni);
  131. }
  132. // Sort the uniforms
  133. std::sort(m_refl.m_uniforms.getBegin(), m_refl.m_uniforms.getEnd(),
  134. [](const ShaderProgramImplReflection::Uniform& a, const ShaderProgramImplReflection::Uniform& b) {
  135. return a.m_location < b.m_location;
  136. });
  137. // Now calculate the offset inside the push constant buffer
  138. m_refl.m_uniformDataSize = 0;
  139. for(ShaderProgramImplReflection::Uniform& uni : m_refl.m_uniforms)
  140. {
  141. U32 dataSize = 0;
  142. switch(uni.m_type)
  143. {
  144. case ShaderVariableDataType::VEC4:
  145. case ShaderVariableDataType::IVEC4:
  146. case ShaderVariableDataType::UVEC4:
  147. dataSize = sizeof(F32) * 4;
  148. break;
  149. case ShaderVariableDataType::MAT4:
  150. dataSize = sizeof(F32) * 16;
  151. break;
  152. case ShaderVariableDataType::MAT3:
  153. dataSize = sizeof(F32) * 12;
  154. break;
  155. default:
  156. ANKI_ASSERT(!"Unsupported type");
  157. }
  158. uni.m_pushConstantOffset = m_refl.m_uniformDataSize;
  159. m_refl.m_uniformDataSize += dataSize * uni.m_arrSize;
  160. }
  161. }
  162. m_reflInitialized = true;
  163. return m_refl;
  164. }
  165. } // end namespace anki