BsGLSLGpuProgram.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. const char *source = mSource.c_str();
  95. mGLHandle = glCreateShaderProgramv(shaderType, 1, &source);
  96. mCompileError = "";
  97. mIsCompiled = !checkForGLSLError(mGLHandle, mCompileError);
  98. }
  99. if (mIsCompiled)
  100. {
  101. GLSLParamParser paramParser;
  102. paramParser.buildUniformDescriptions(mGLHandle, *mParametersDesc);
  103. if (mType == GPT_VERTEX_PROGRAM)
  104. {
  105. VertexDeclaration::VertexElementList elementList = paramParser.buildVertexDeclaration(mGLHandle);
  106. mVertexDeclaration = HardwareBufferManager::instance().createVertexDeclaration(elementList);
  107. }
  108. }
  109. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
  110. GpuProgram::initialize_internal();
  111. }
  112. void GLSLGpuProgram::destroy_internal()
  113. {
  114. if (mIsCompiled && mGLHandle != 0)
  115. {
  116. glDeleteProgram(mGLHandle);
  117. mGLHandle = 0;
  118. }
  119. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuProgram);
  120. GpuProgram::destroy_internal();
  121. }
  122. bool GLSLGpuProgram::isSupported() const
  123. {
  124. if (!isRequiredCapabilitiesSupported())
  125. return false;
  126. RenderSystem* rs = BansheeEngine::RenderSystem::instancePtr();
  127. return rs->getCapabilities()->isShaderProfileSupported("glsl");
  128. }
  129. const String& GLSLGpuProgram::getLanguage() const
  130. {
  131. static const String language = "glsl";
  132. return language;
  133. }
  134. /************************************************************************/
  135. /* SERIALIZATION */
  136. /************************************************************************/
  137. RTTITypeBase* GLSLGpuProgram::getRTTIStatic()
  138. {
  139. return GLSLGpuProgramRTTI::instance();
  140. }
  141. RTTITypeBase* GLSLGpuProgram::getRTTI() const
  142. {
  143. return GLSLGpuProgram::getRTTIStatic();
  144. }
  145. }