BsGLVertexArrayObjectManager.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsGLVertexArrayObjectManager.h"
  4. #include "BsGLVertexBuffer.h"
  5. #include "RenderAPI/BsVertexDeclaration.h"
  6. #include "GLSL/BsGLSLGpuProgram.h"
  7. #include "BsGLHardwareBufferManager.h"
  8. #include "Profiling/BsRenderStats.h"
  9. #define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i))
  10. namespace bs { namespace ct
  11. {
  12. GLVertexArrayObject::GLVertexArrayObject()
  13. :mHandle(0), mVertProgId(0), mAttachedBuffers(nullptr), mNumBuffers(0)
  14. { }
  15. GLVertexArrayObject::GLVertexArrayObject(GLuint handle, UINT64 vertexProgramId,
  16. GLVertexBuffer** attachedBuffers, UINT32 numBuffers)
  17. :mHandle(handle), mVertProgId(vertexProgramId), mAttachedBuffers(attachedBuffers), mNumBuffers(numBuffers)
  18. { }
  19. ::std::size_t GLVertexArrayObject::Hash::operator()(const GLVertexArrayObject &vao) const
  20. {
  21. std::size_t seed = 0;
  22. hash_combine(seed, vao.mVertProgId);
  23. for (UINT32 i = 0; i < vao.mNumBuffers; i++)
  24. hash_combine(seed, vao.mAttachedBuffers[i]->getGLBufferId());
  25. return seed;
  26. }
  27. bool GLVertexArrayObject::Equal::operator()(const GLVertexArrayObject &a, const GLVertexArrayObject &b) const
  28. {
  29. if (a.mVertProgId != b.mVertProgId)
  30. return false;
  31. if (a.mNumBuffers != b.mNumBuffers)
  32. return false;
  33. for (UINT32 i = 0; i < a.mNumBuffers; i++)
  34. {
  35. if (a.mAttachedBuffers[i]->getGLBufferId() != b.mAttachedBuffers[i]->getGLBufferId())
  36. return false;
  37. }
  38. return true;
  39. }
  40. bool GLVertexArrayObject::operator== (const GLVertexArrayObject& obj)
  41. {
  42. if (mVertProgId != obj.mVertProgId)
  43. return false;
  44. if (mNumBuffers != obj.mNumBuffers)
  45. return false;
  46. for (UINT32 i = 0; i < mNumBuffers; i++)
  47. {
  48. if (mAttachedBuffers[i]->getGLBufferId() != obj.mAttachedBuffers[i]->getGLBufferId())
  49. return false;
  50. }
  51. return true;
  52. }
  53. bool GLVertexArrayObject::operator!= (const GLVertexArrayObject& obj)
  54. {
  55. return !operator==(obj);
  56. }
  57. GLVertexArrayObjectManager::~GLVertexArrayObjectManager()
  58. {
  59. assert(mVAObjects.size() == 0 && "VertexArrayObjectManager getting shut down but not all VA objects were released.");
  60. }
  61. const GLVertexArrayObject& GLVertexArrayObjectManager::getVAO(const SPtr<GLSLGpuProgram>& vertexProgram,
  62. const SPtr<VertexDeclaration>& vertexDecl, const std::array<SPtr<VertexBuffer>, 32>& boundBuffers)
  63. {
  64. UINT16 maxStreamIdx = 0;
  65. const List<VertexElement>& decl = vertexDecl->getProperties().getElements();
  66. for (auto& elem : decl)
  67. maxStreamIdx = std::max(maxStreamIdx, elem.getStreamIdx());
  68. UINT32 numStreams = maxStreamIdx + 1;
  69. UINT32 numUsedBuffers = 0;
  70. INT32* streamToSeqIdx = bs_stack_alloc<INT32>(numStreams);
  71. GLVertexBuffer** usedBuffers = bs_stack_alloc<GLVertexBuffer*>((UINT32)boundBuffers.size());
  72. memset(usedBuffers, 0, (UINT32)boundBuffers.size() * sizeof(GLVertexBuffer*));
  73. for (UINT32 i = 0; i < numStreams; i++)
  74. streamToSeqIdx[i] = -1;
  75. for (auto& elem : decl)
  76. {
  77. UINT16 streamIdx = elem.getStreamIdx();
  78. if (streamIdx >= (UINT32)boundBuffers.size())
  79. continue;
  80. if (streamToSeqIdx[streamIdx] != -1) // Already visited
  81. continue;
  82. SPtr<VertexBuffer> vertexBuffer = boundBuffers[streamIdx];
  83. streamToSeqIdx[streamIdx] = (INT32)numUsedBuffers;
  84. if (vertexBuffer != nullptr)
  85. usedBuffers[numUsedBuffers] = static_cast<GLVertexBuffer*>(vertexBuffer.get());
  86. else
  87. usedBuffers[numUsedBuffers] = nullptr;
  88. numUsedBuffers++;
  89. }
  90. GLVertexArrayObject wantedVAO(0, vertexProgram->getGLHandle(), usedBuffers, numUsedBuffers);
  91. auto findIter = mVAObjects.find(wantedVAO);
  92. if (findIter != mVAObjects.end())
  93. {
  94. bs_stack_free(usedBuffers);
  95. bs_stack_free(streamToSeqIdx);
  96. return *findIter; // Found existing, return that
  97. }
  98. // Need to create new VAO
  99. const List<VertexElement>& inputAttributes = vertexProgram->getInputDeclaration()->getProperties().getElements();
  100. glGenVertexArrays(1, &wantedVAO.mHandle);
  101. BS_CHECK_GL_ERROR();
  102. glBindVertexArray(wantedVAO.mHandle);
  103. BS_CHECK_GL_ERROR();
  104. for (auto& elem : decl)
  105. {
  106. UINT16 streamIdx = elem.getStreamIdx();
  107. INT32 seqIdx = streamToSeqIdx[streamIdx];
  108. if (seqIdx == -1)
  109. continue;
  110. bool foundSemantic = false;
  111. GLint attribLocation = 0;
  112. for (auto iter = inputAttributes.begin(); iter != inputAttributes.end(); ++iter)
  113. {
  114. if (iter->getSemantic() == elem.getSemantic() && iter->getSemanticIdx() == elem.getSemanticIdx())
  115. {
  116. foundSemantic = true;
  117. attribLocation = iter->getOffset();
  118. break;
  119. }
  120. }
  121. if (!foundSemantic) // Shader needs to have a matching input attribute, otherwise we skip it
  122. continue;
  123. // TODO - We might also want to check the size of input and buffer, and make sure they match? Or does OpenGL handle that internally?
  124. GLVertexBuffer* vertexBuffer = usedBuffers[seqIdx];
  125. const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
  126. glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->getGLBufferId());
  127. BS_CHECK_GL_ERROR();
  128. void* bufferData = VBO_BUFFER_OFFSET(elem.getOffset());
  129. UINT16 typeCount = VertexElement::getTypeCount(elem.getType());
  130. GLenum glType = GLHardwareBufferManager::getGLType(elem.getType());
  131. bool isInteger = glType == GL_SHORT || glType == GL_UNSIGNED_SHORT || glType == GL_INT
  132. || glType == GL_UNSIGNED_INT || glType == GL_UNSIGNED_BYTE;
  133. GLboolean normalized = GL_FALSE;
  134. switch (elem.getType())
  135. {
  136. case VET_COLOR:
  137. case VET_COLOR_ABGR:
  138. case VET_COLOR_ARGB:
  139. case VET_UBYTE4_NORM:
  140. normalized = GL_TRUE;
  141. isInteger = false;
  142. break;
  143. default:
  144. break;
  145. }
  146. GLsizei vertexSize = static_cast<GLsizei>(vbProps.getVertexSize());
  147. if(isInteger)
  148. {
  149. glVertexAttribIPointer(attribLocation, typeCount, glType, vertexSize, bufferData);
  150. BS_CHECK_GL_ERROR();
  151. }
  152. else
  153. {
  154. glVertexAttribPointer(attribLocation, typeCount, glType, normalized, vertexSize, bufferData);
  155. BS_CHECK_GL_ERROR();
  156. }
  157. glVertexAttribDivisor(attribLocation, elem.getInstanceStepRate());
  158. BS_CHECK_GL_ERROR();
  159. glEnableVertexAttribArray(attribLocation);
  160. BS_CHECK_GL_ERROR();
  161. }
  162. wantedVAO.mAttachedBuffers = (GLVertexBuffer**)bs_alloc(numUsedBuffers * sizeof(GLVertexBuffer*));
  163. for (UINT32 i = 0; i < numUsedBuffers; i++)
  164. {
  165. wantedVAO.mAttachedBuffers[i] = usedBuffers[i];
  166. usedBuffers[i]->registerVAO(wantedVAO);
  167. }
  168. bs_stack_free(usedBuffers);
  169. bs_stack_free(streamToSeqIdx);
  170. auto iter = mVAObjects.insert(wantedVAO);
  171. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_VertexArrayObject);
  172. return *iter.first;
  173. }
  174. // Note: This must receieve a copy and not a ref because original will be destroyed
  175. void GLVertexArrayObjectManager::notifyBufferDestroyed(GLVertexArrayObject vao)
  176. {
  177. mVAObjects.erase(vao);
  178. for (UINT32 i = 0; i < vao.mNumBuffers; i++)
  179. {
  180. vao.mAttachedBuffers[i]->unregisterVAO(vao);
  181. }
  182. glDeleteVertexArrays(1, &vao.mHandle);
  183. BS_CHECK_GL_ERROR();
  184. bs_free(vao.mAttachedBuffers);
  185. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_VertexArrayObject);
  186. }
  187. }}