GlProgramPipeline.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "anki/gl/GlProgramPipeline.h"
  6. #include "anki/gl/GlProgram.h"
  7. namespace anki {
  8. //==============================================================================
  9. GlProgramPipeline::GlProgramPipeline(
  10. const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
  11. {
  12. ANKI_ASSERT(progsBegin != nullptr && progsEnd != nullptr);
  13. ANKI_ASSERT(progsBegin != progsEnd);
  14. attachProgramsInternal(progsBegin, progsEnd - progsBegin);
  15. // Create and attach programs
  16. glGenProgramPipelines(1, &m_glName);
  17. ANKI_ASSERT(m_glName != 0);
  18. glBindProgramPipeline(m_glName);
  19. for(U i = 0; i < m_progs.size(); i++)
  20. {
  21. GlProgramHandle& prog = m_progs[i];
  22. if(prog.isCreated())
  23. {
  24. GLbitfield bit;
  25. GLenum gltype = computeGlShaderType(i, &bit);
  26. ANKI_ASSERT(prog.getType() == gltype && "Attached wrong shader");
  27. (void)gltype;
  28. glUseProgramStages(m_glName, bit, prog._get().getGlName());
  29. }
  30. }
  31. // Validate and check error
  32. glValidateProgramPipeline(m_glName);
  33. GLint status = 0;
  34. glGetProgramPipelineiv(m_glName, GL_VALIDATE_STATUS, &status);
  35. if(!status)
  36. {
  37. GLint infoLen = 0;
  38. GLint charsWritten = 0;
  39. String infoLogTxt;
  40. glGetProgramPipelineiv(m_glName, GL_INFO_LOG_LENGTH, &infoLen);
  41. infoLogTxt.resize(infoLen + 1);
  42. glGetProgramPipelineInfoLog(
  43. m_glName, infoLen, &charsWritten, &infoLogTxt[0]);
  44. infoLogTxt = "Ppline error log follows:\n" + infoLogTxt;
  45. throw ANKI_EXCEPTION("%s", &infoLogTxt[0]);
  46. }
  47. glBindProgramPipeline(0);
  48. }
  49. //==============================================================================
  50. GlProgramPipeline& GlProgramPipeline::operator=(GlProgramPipeline&& b)
  51. {
  52. destroy();
  53. Base::operator=(std::forward<Base>(b));
  54. for(U i = 0; i < m_progs.size(); i++)
  55. {
  56. m_progs[i] = b.m_progs[i];
  57. b.m_progs[i] = GlProgramHandle();
  58. }
  59. return *this;
  60. }
  61. //==============================================================================
  62. void GlProgramPipeline::destroy()
  63. {
  64. if(m_glName)
  65. {
  66. glDeleteProgramPipelines(1, &m_glName);
  67. m_glName = 0;
  68. }
  69. }
  70. //==============================================================================
  71. void GlProgramPipeline::attachProgramsInternal(
  72. const GlProgramHandle* progs, PtrSize count)
  73. {
  74. U mask = 0;
  75. while(count-- != 0)
  76. {
  77. const GlProgramHandle& prog = progs[count];
  78. U idx = computeShaderTypeIndex(prog._get().getType());
  79. ANKI_ASSERT(!m_progs[idx].isCreated() && "Attaching the same");
  80. m_progs[idx] = prog;
  81. mask |= 1 << idx;
  82. }
  83. // Check what we attached
  84. //
  85. if(mask & (1 << 5))
  86. {
  87. // Is compute
  88. ANKI_ASSERT((mask & (1 << 5)) == (1 << 5)
  89. && "Compute should be alone in the pipeline");
  90. }
  91. else
  92. {
  93. const U fragVert = (1 << 0) | (1 << 4);
  94. ANKI_ASSERT((mask & fragVert) && "Should contain vert and frag");
  95. (void)fragVert;
  96. const U tess = (1 << 1) | (1 << 2);
  97. if((mask & tess) != 0)
  98. {
  99. ANKI_ASSERT(((mask & tess) == 0x6)
  100. && "Should set both the tessellation shaders");
  101. }
  102. }
  103. }
  104. //==============================================================================
  105. void GlProgramPipeline::bind()
  106. {
  107. ANKI_ASSERT(isCreated());
  108. glBindProgramPipeline(m_glName);
  109. }
  110. //==============================================================================
  111. GlProgramHandle GlProgramPipeline::getAttachedProgram(GLenum type) const
  112. {
  113. ANKI_ASSERT(isCreated());
  114. U idx = computeShaderTypeIndex(type);
  115. GlProgramHandle prog = m_progs[idx];
  116. ANKI_ASSERT(prog.isCreated() && "Asking for non-created program");
  117. return prog;
  118. }
  119. } // end namespace anki