BsGLSLGpuProgram.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #pragma once
  2. #include "BsGLSLGpuProgram.h"
  3. #include "BsRenderSystem.h"
  4. #include "BsException.h"
  5. #include "BsGLSLParamParser.h"
  6. #include "BsHardwareBufferManager.h"
  7. #include "BsGLSLGpuProgramRTTI.h"
  8. #include "BsRenderStats.h"
  9. namespace BansheeEngine
  10. {
  11. UINT32 GLSLGpuProgram::mVertexShaderCount = 0;
  12. UINT32 GLSLGpuProgram::mFragmentShaderCount = 0;
  13. UINT32 GLSLGpuProgram::mGeometryShaderCount = 0;
  14. UINT32 GLSLGpuProgram::mDomainShaderCount = 0;
  15. UINT32 GLSLGpuProgram::mHullShaderCount = 0;
  16. bool checkForGLSLError(const GLuint programObj, String& outErrorMsg)
  17. {
  18. StringStream stream;
  19. GLenum glErr;
  20. bool errorsFound = false;
  21. glErr = glGetError();
  22. while (glErr != GL_NO_ERROR)
  23. {
  24. const char* glerrStr = (const char*)gluErrorString(glErr);
  25. if (glerrStr)
  26. {
  27. if (errorsFound)
  28. stream << "\nPrevious errors: \n";
  29. stream << String(glerrStr) << std::endl;;
  30. }
  31. glErr = glGetError();
  32. errorsFound = true;
  33. }
  34. if (errorsFound && programObj > 0)
  35. {
  36. GLint infologLength = 0;
  37. glGetProgramiv(programObj, GL_INFO_LOG_LENGTH, &infologLength);
  38. if (infologLength > 0)
  39. {
  40. GLint charsWritten = 0;
  41. GLchar* infoLog = (GLchar*)bs_alloc<ScratchAlloc>(sizeof(GLchar)* infologLength);
  42. glGetProgramInfoLog(programObj, infologLength, &charsWritten, infoLog);
  43. stream << "Compile and linker info log: \n";
  44. stream << String(infoLog);
  45. bs_free<ScratchAlloc>(infoLog);
  46. }
  47. }
  48. outErrorMsg = stream.str();
  49. return errorsFound;
  50. }
  51. GLSLGpuProgram::GLSLGpuProgram(const String& source, const String& entryPoint, GpuProgramType gptype,
  52. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes, bool isAdjacencyInfoRequired)
  53. :GpuProgram(source, entryPoint, gptype, profile, includes, isAdjacencyInfoRequired),
  54. mProgramID(0), mGLHandle(0)
  55. { }
  56. GLSLGpuProgram::~GLSLGpuProgram()
  57. { }
  58. void GLSLGpuProgram::initialize_internal()
  59. {
  60. if (!isSupported())
  61. {
  62. mIsCompiled = false;
  63. mCompileError = "Specified program is not supported by the current render system.";
  64. GpuProgram::initialize_internal();
  65. return;
  66. }
  67. GLenum shaderType = 0x0000;
  68. switch (mType)
  69. {
  70. case GPT_VERTEX_PROGRAM:
  71. shaderType = GL_VERTEX_SHADER;
  72. mProgramID = ++mVertexShaderCount;
  73. break;
  74. case GPT_FRAGMENT_PROGRAM:
  75. shaderType = GL_FRAGMENT_SHADER;
  76. mProgramID = ++mFragmentShaderCount;
  77. break;
  78. case GPT_GEOMETRY_PROGRAM:
  79. shaderType = GL_GEOMETRY_SHADER;
  80. mProgramID = ++mGeometryShaderCount;
  81. break;
  82. case GPT_HULL_PROGRAM:
  83. shaderType = GL_TESS_CONTROL_SHADER;
  84. mProgramID = ++mDomainShaderCount;
  85. break;
  86. case GPT_DOMAIN_PROGRAM:
  87. shaderType = GL_TESS_EVALUATION_SHADER;
  88. mProgramID = ++mHullShaderCount;
  89. break;
  90. }
  91. // Add preprocessor extras and main source
  92. if (!mSource.empty())
  93. {
  94. Vector<GLchar*> lines;
  95. UINT32 lineLength = 0;
  96. for (UINT32 i = 0; i < mSource.size(); i++)
  97. {
  98. if (mSource[i] == '\n' || mSource[i] == '\r')
  99. {
  100. if (lineLength > 0)
  101. {
  102. assert(sizeof(mSource[i]) == sizeof(GLchar));
  103. bool isDefine = mSource[i - lineLength] == '#';
  104. GLchar* lineData = (GLchar*)stackAlloc(sizeof(GLchar) * (lineLength + 1 + (isDefine ? 1 : 0)));
  105. memcpy(lineData, &mSource[i - lineLength], sizeof(GLchar) * lineLength);
  106. if (isDefine) // Defines require a newline as well as a null terminator, otherwise it doesn't compile properly
  107. {
  108. lineData[lineLength] = '\n';
  109. lineData[lineLength + 1] = '\0';
  110. }
  111. else
  112. lineData[lineLength] = '\0';
  113. lines.push_back(lineData);
  114. lineLength = 0;
  115. }
  116. }
  117. else
  118. {
  119. lineLength++;
  120. }
  121. }
  122. if (lineLength > 0)
  123. {
  124. UINT32 end = (UINT32)mSource.size() - 1;
  125. assert(sizeof(mSource[end]) == sizeof(GLchar));
  126. GLchar* lineData = (GLchar*)stackAlloc(sizeof(GLchar) * (lineLength + 1));
  127. memcpy(lineData, &mSource[mSource.size() - lineLength], sizeof(GLchar) * lineLength);
  128. lineData[lineLength] = '\0';
  129. lines.push_back(lineData);
  130. lineLength = 0;
  131. }
  132. mGLHandle = glCreateShaderProgramv(shaderType, (GLsizei)lines.size(), (const GLchar**)lines.data());
  133. for (auto iter = lines.rbegin(); iter != lines.rend(); ++iter)
  134. {
  135. stackDeallocLast(*iter);
  136. }
  137. mCompileError = "";
  138. mIsCompiled = !checkForGLSLError(mGLHandle, mCompileError);
  139. }
  140. if (mIsCompiled)
  141. {
  142. GLSLParamParser paramParser;
  143. paramParser.buildUniformDescriptions(mGLHandle, *mParametersDesc);
  144. if (mType == GPT_VERTEX_PROGRAM)
  145. {
  146. VertexDeclaration::VertexElementList elementList = paramParser.buildVertexDeclaration(mGLHandle);
  147. mVertexDeclaration = HardwareBufferManager::instance().createVertexDeclaration(elementList);
  148. }
  149. }
  150. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
  151. GpuProgram::initialize_internal();
  152. }
  153. void GLSLGpuProgram::destroy_internal()
  154. {
  155. if (mIsCompiled && mGLHandle != 0)
  156. {
  157. glDeleteProgram(mGLHandle);
  158. mGLHandle = 0;
  159. }
  160. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuProgram);
  161. GpuProgram::destroy_internal();
  162. }
  163. bool GLSLGpuProgram::isSupported() const
  164. {
  165. if (!isRequiredCapabilitiesSupported())
  166. return false;
  167. RenderSystem* rs = BansheeEngine::RenderSystem::instancePtr();
  168. return rs->getCapabilities()->isShaderProfileSupported("glsl");
  169. }
  170. const String& GLSLGpuProgram::getLanguage() const
  171. {
  172. static const String language = "glsl";
  173. return language;
  174. }
  175. /************************************************************************/
  176. /* SERIALIZATION */
  177. /************************************************************************/
  178. RTTITypeBase* GLSLGpuProgram::getRTTIStatic()
  179. {
  180. return GLSLGpuProgramRTTI::instance();
  181. }
  182. RTTITypeBase* GLSLGpuProgram::getRTTI() const
  183. {
  184. return GLSLGpuProgram::getRTTIStatic();
  185. }
  186. }