diff --git a/irr/include/IVideoDriver.h b/irr/include/IVideoDriver.h index 6d2182e8a..b3312160c 100644 --- a/irr/include/IVideoDriver.h +++ b/irr/include/IVideoDriver.h @@ -31,6 +31,8 @@ class IWriteFile; namespace scene { class IMeshBuffer; +class IVertexBuffer; +class IIndexBuffer; class IMesh; class IMeshManipulator; class ISceneNode; @@ -299,7 +301,10 @@ public: virtual void removeAllTextures() = 0; //! Remove hardware buffer - virtual void removeHardwareBuffer(const scene::IMeshBuffer *mb) = 0; + virtual void removeHardwareBuffer(const scene::IVertexBuffer *vb) = 0; + + //! Remove hardware buffer + virtual void removeHardwareBuffer(const scene::IIndexBuffer *ib) = 0; //! Remove all hardware buffers virtual void removeAllHardwareBuffers() = 0; @@ -738,6 +743,17 @@ public: /** \param mb Buffer to draw */ virtual void drawMeshBuffer(const scene::IMeshBuffer *mb) = 0; + /** + * Draws a mesh from individual vertex and index buffers. + * @param vb vertices to use + * @param ib indices to use + * @param primCount amount of primitives + * @param pType primitive type + */ + virtual void drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 primCount, + scene::E_PRIMITIVE_TYPE pType = scene::EPT_TRIANGLES) = 0; + //! Draws normals of a mesh buffer /** \param mb Buffer to draw the normals of \param length length scale factor of the normals diff --git a/irr/src/CNullDriver.cpp b/irr/src/CNullDriver.cpp index 054267711..6f261cef1 100644 --- a/irr/src/CNullDriver.cpp +++ b/irr/src/CNullDriver.cpp @@ -1109,19 +1109,20 @@ void CNullDriver::getFog(SColor &color, E_FOG_TYPE &fogType, f32 &start, f32 &en rangeFog = RangeFog; } -//! Draws a mesh buffer -void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer *mb) +void CNullDriver::drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 primCount, + scene::E_PRIMITIVE_TYPE pType) { - if (!mb) + if (!vb || !ib) return; - // IVertexBuffer and IIndexBuffer later - SHWBufferLink *HWBuffer = getBufferLink(mb); + if (vb->getHWBuffer() || ib->getHWBuffer()) { + // subclass is supposed to override this if it supports hw buffers + _IRR_DEBUG_BREAK_IF(1); + } - if (HWBuffer) - drawHardwareBuffer(HWBuffer); - else - drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType()); + drawVertexPrimitiveList(vb->getData(), vb->getCount(), ib->getData(), + primCount, vb->getType(), pType, ib->getType()); } //! Draws the normals of a mesh buffer @@ -1140,17 +1141,30 @@ void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer *mb, f32 length } } -CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer *mb) +CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IVertexBuffer *vb) { - if (!mb || !isHardwareBufferRecommend(mb)) + if (!vb || !isHardwareBufferRecommend(vb)) return 0; // search for hardware links - SHWBufferLink *HWBuffer = reinterpret_cast(mb->getHWBuffer()); + SHWBufferLink *HWBuffer = reinterpret_cast(vb->getHWBuffer()); if (HWBuffer) return HWBuffer; - return createHardwareBuffer(mb); // no hardware links, and mesh wants one, create it + return createHardwareBuffer(vb); // no hardware links, and mesh wants one, create it +} + +CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IIndexBuffer *ib) +{ + if (!ib || !isHardwareBufferRecommend(ib)) + return 0; + + // search for hardware links + SHWBufferLink *HWBuffer = reinterpret_cast(ib->getHWBuffer()); + if (HWBuffer) + return HWBuffer; + + return createHardwareBuffer(ib); // no hardware links, and mesh wants one, create it } //! Update all hardware buffers, remove unused ones @@ -1161,8 +1175,13 @@ void CNullDriver::updateAllHardwareBuffers() SHWBufferLink *Link = *it; ++it; - if (!Link->MeshBuffer || Link->MeshBuffer->getReferenceCount() == 1) - deleteHardwareBuffer(Link); + if (Link->IsVertex) { + if (!Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1) + deleteHardwareBuffer(Link); + } else { + if (!Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1) + deleteHardwareBuffer(Link); + } } } @@ -1174,12 +1193,20 @@ void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer) delete HWBuffer; } -//! Remove hardware buffer -void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer *mb) +void CNullDriver::removeHardwareBuffer(const scene::IVertexBuffer *vb) { - if (!mb) + if (!vb) return; - SHWBufferLink *HWBuffer = reinterpret_cast(mb->getHWBuffer()); + SHWBufferLink *HWBuffer = reinterpret_cast(vb->getHWBuffer()); + if (HWBuffer) + deleteHardwareBuffer(HWBuffer); +} + +void CNullDriver::removeHardwareBuffer(const scene::IIndexBuffer *ib) +{ + if (!ib) + return; + SHWBufferLink *HWBuffer = reinterpret_cast(ib->getHWBuffer()); if (HWBuffer) deleteHardwareBuffer(HWBuffer); } @@ -1191,12 +1218,24 @@ void CNullDriver::removeAllHardwareBuffers() deleteHardwareBuffer(HWBufferList.front()); } -bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer *mb) +bool CNullDriver::isHardwareBufferRecommend(const scene::IVertexBuffer *vb) { - if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)) + if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER) return false; - if (mb->getVertexCount() < MinVertexCountForVBO) + if (vb->getCount() < MinVertexCountForVBO) + return false; + + return true; +} + +bool CNullDriver::isHardwareBufferRecommend(const scene::IIndexBuffer *ib) +{ + if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER) + return false; + + // This is a bit stupid + if (ib->getCount() < MinVertexCountForVBO * 3) return false; return true; diff --git a/irr/src/CNullDriver.h b/irr/src/CNullDriver.h index 302108a1b..b8d45118f 100644 --- a/irr/src/CNullDriver.h +++ b/irr/src/CNullDriver.h @@ -269,8 +269,18 @@ public: const core::position2d &pos, const core::dimension2d &size) override; - //! Draws a mesh buffer - void drawMeshBuffer(const scene::IMeshBuffer *mb) override; + void drawMeshBuffer(const scene::IMeshBuffer *mb) override + { + if (!mb) + return; + drawBuffers(mb->getVertexBuffer(), mb->getIndexBuffer(), + mb->getPrimitiveCount(), mb->getPrimitiveType()); + } + + // Note: this should handle hw buffers + virtual void drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 primCount, + scene::E_PRIMITIVE_TYPE pType = scene::EPT_TRIANGLES) override; //! Draws the normals of a mesh buffer virtual void drawMeshBufferNormals(const scene::IMeshBuffer *mb, f32 length = 10.f, @@ -283,53 +293,70 @@ public: } protected: + /// Links a hardware buffer to either a vertex or index buffer struct SHWBufferLink { - SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer) : - MeshBuffer(_MeshBuffer), - ChangedID_Vertex(0), ChangedID_Index(0), - Mapped_Vertex(scene::EHM_NEVER), Mapped_Index(scene::EHM_NEVER) + SHWBufferLink(const scene::IVertexBuffer *vb) : + VertexBuffer(vb), ChangedID(0), IsVertex(true) { - if (MeshBuffer) { - MeshBuffer->grab(); - MeshBuffer->setHWBuffer(reinterpret_cast(this)); + if (VertexBuffer) { + VertexBuffer->grab(); + VertexBuffer->setHWBuffer(this); + } + } + SHWBufferLink(const scene::IIndexBuffer *ib) : + IndexBuffer(ib), ChangedID(0), IsVertex(false) + { + if (IndexBuffer) { + IndexBuffer->grab(); + IndexBuffer->setHWBuffer(this); } } virtual ~SHWBufferLink() { - if (MeshBuffer) { - MeshBuffer->setHWBuffer(NULL); - MeshBuffer->drop(); + if (IsVertex && VertexBuffer) { + VertexBuffer->setHWBuffer(nullptr); + VertexBuffer->drop(); + } else if (!IsVertex && IndexBuffer) { + IndexBuffer->setHWBuffer(nullptr); + IndexBuffer->drop(); } } - const scene::IMeshBuffer *MeshBuffer; - u32 ChangedID_Vertex; - u32 ChangedID_Index; - scene::E_HARDWARE_MAPPING Mapped_Vertex; - scene::E_HARDWARE_MAPPING Mapped_Index; - std::list::iterator listPosition; + union { + const scene::IVertexBuffer *VertexBuffer; + const scene::IIndexBuffer *IndexBuffer; + }; + u32 ChangedID; + bool IsVertex; + std::list::iterator listPosition; }; - //! Gets hardware buffer link from a meshbuffer (may create or update buffer) - virtual SHWBufferLink *getBufferLink(const scene::IMeshBuffer *mb); + //! Gets hardware buffer link from a vertex buffer (may create or update buffer) + virtual SHWBufferLink *getBufferLink(const scene::IVertexBuffer *mb); + + //! Gets hardware buffer link from a index buffer (may create or update buffer) + virtual SHWBufferLink *getBufferLink(const scene::IIndexBuffer *mb); //! updates hardware buffer if needed (only some drivers can) virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer) { return false; } - //! Draw hardware buffer (only some drivers can) - virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer) {} - //! Delete hardware buffer virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer); - //! Create hardware buffer from mesh (only some drivers can) - virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer *mb) { return 0; } + //! Create hardware buffer from vertex buffer + virtual SHWBufferLink *createHardwareBuffer(const scene::IVertexBuffer *vb) { return 0; } + + //! Create hardware buffer from index buffer + virtual SHWBufferLink *createHardwareBuffer(const scene::IIndexBuffer *ib) { return 0; } public: //! Remove hardware buffer - void removeHardwareBuffer(const scene::IMeshBuffer *mb) override; + void removeHardwareBuffer(const scene::IVertexBuffer *vb) override; + + //! Remove hardware buffer + void removeHardwareBuffer(const scene::IIndexBuffer *ib) override; //! Remove all hardware buffers void removeAllHardwareBuffers() override; @@ -337,8 +364,11 @@ public: //! Update all hardware buffers, remove unused ones virtual void updateAllHardwareBuffers(); - //! is vbo recommended on this mesh? - virtual bool isHardwareBufferRecommend(const scene::IMeshBuffer *mb); + //! is vbo recommended? + virtual bool isHardwareBufferRecommend(const scene::IVertexBuffer *mb); + + //! is vbo recommended? + virtual bool isHardwareBufferRecommend(const scene::IIndexBuffer *mb); //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp index 875534a4e..837dc05d3 100644 --- a/irr/src/COpenGLDriver.cpp +++ b/irr/src/COpenGLDriver.cpp @@ -260,10 +260,10 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) return false; #if defined(GL_ARB_vertex_buffer_object) - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; - const void *vertices = mb->getVertices(); - const u32 vertexCount = mb->getVertexCount(); - const E_VERTEX_TYPE vType = mb->getVertexType(); + const auto *vb = HWBuffer->VertexBuffer; + const void *vertices = vb->getData(); + const u32 vertexCount = vb->getCount(); + const E_VERTEX_TYPE vType = vb->getType(); const u32 vertexSize = getVertexPitchFromType(vType); accountHWBufferUpload(vertexSize * vertexCount); @@ -307,26 +307,26 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) // get or create buffer bool newBuffer = false; - if (!HWBuffer->vbo_verticesID) { - extGlGenBuffers(1, &HWBuffer->vbo_verticesID); - if (!HWBuffer->vbo_verticesID) + if (!HWBuffer->vbo_ID) { + extGlGenBuffers(1, &HWBuffer->vbo_ID); + if (!HWBuffer->vbo_ID) return false; newBuffer = true; - } else if (HWBuffer->vbo_verticesSize < vertexCount * vertexSize) { + } else if (HWBuffer->vbo_Size < vertexCount * vertexSize) { newBuffer = true; } - extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); + extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_ID); // copy data to graphics card if (!newBuffer) extGlBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, vbuf); else { - HWBuffer->vbo_verticesSize = vertexCount * vertexSize; + HWBuffer->vbo_Size = vertexCount * vertexSize; - if (HWBuffer->Mapped_Vertex == scene::EHM_STATIC) + if (vb->getHardwareMappingHint() == scene::EHM_STATIC) extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STATIC_DRAW); - else if (HWBuffer->Mapped_Vertex == scene::EHM_DYNAMIC) + else if (vb->getHardwareMappingHint() == scene::EHM_DYNAMIC) extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_DYNAMIC_DRAW); else // scene::EHM_STREAM extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STREAM_DRAW); @@ -349,13 +349,13 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) return false; #if defined(GL_ARB_vertex_buffer_object) - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; + const auto *ib = HWBuffer->IndexBuffer; - const void *indices = mb->getIndices(); - u32 indexCount = mb->getIndexCount(); + const void *indices = ib->getData(); + u32 indexCount = ib->getCount(); GLenum indexSize; - switch (mb->getIndexType()) { + switch (ib->getType()) { case EIT_16BIT: { indexSize = sizeof(u16); break; @@ -373,26 +373,26 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) // get or create buffer bool newBuffer = false; - if (!HWBuffer->vbo_indicesID) { - extGlGenBuffers(1, &HWBuffer->vbo_indicesID); - if (!HWBuffer->vbo_indicesID) + if (!HWBuffer->vbo_ID) { + extGlGenBuffers(1, &HWBuffer->vbo_ID); + if (!HWBuffer->vbo_ID) return false; newBuffer = true; - } else if (HWBuffer->vbo_indicesSize < indexCount * indexSize) { + } else if (HWBuffer->vbo_Size < indexCount * indexSize) { newBuffer = true; } - extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); + extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_ID); // copy data to graphics card if (!newBuffer) extGlBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices); else { - HWBuffer->vbo_indicesSize = indexCount * indexSize; + HWBuffer->vbo_Size = indexCount * indexSize; - if (HWBuffer->Mapped_Index == scene::EHM_STATIC) + if (ib->getHardwareMappingHint() == scene::EHM_STATIC) extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW); - else if (HWBuffer->Mapped_Index == scene::EHM_DYNAMIC) + else if (ib->getHardwareMappingHint() == scene::EHM_DYNAMIC) extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW); else // scene::EHM_STREAM extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STREAM_DRAW); @@ -412,51 +412,62 @@ bool COpenGLDriver::updateHardwareBuffer(SHWBufferLink *HWBuffer) if (!HWBuffer) return false; - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !((SHWBufferLink_opengl *)HWBuffer)->vbo_verticesID) { + auto *b = static_cast(HWBuffer); - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); - - if (!updateVertexHardwareBuffer((SHWBufferLink_opengl *)HWBuffer)) + if (b->IsVertex) { + assert(b->VertexBuffer); + if (b->ChangedID != b->VertexBuffer->getChangedID() || !b->vbo_ID) { + if (!updateVertexHardwareBuffer(b)) return false; + b->ChangedID = b->VertexBuffer->getChangedID(); + } + } else { + assert(b->IndexBuffer); + if (b->ChangedID != b->IndexBuffer->getChangedID() || !b->vbo_ID) { + if (!updateIndexHardwareBuffer(b)) + return false; + b->ChangedID = b->IndexBuffer->getChangedID(); } } - - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !((SHWBufferLink_opengl *)HWBuffer)->vbo_indicesID) { - - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - - if (!updateIndexHardwareBuffer((SHWBufferLink_opengl *)HWBuffer)) - return false; - } - } - return true; } //! Create hardware buffer from meshbuffer -COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IMeshBuffer *mb) +COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IVertexBuffer *vb) { #if defined(GL_ARB_vertex_buffer_object) - if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)) + if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER) return 0; - SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb); + SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb); // add to map HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - HWBuffer->Mapped_Vertex = mb->getHardwareMappingHint_Vertex(); - HWBuffer->Mapped_Index = mb->getHardwareMappingHint_Index(); - HWBuffer->vbo_verticesID = 0; - HWBuffer->vbo_indicesID = 0; - HWBuffer->vbo_verticesSize = 0; - HWBuffer->vbo_indicesSize = 0; + if (!updateVertexHardwareBuffer(HWBuffer)) { + deleteHardwareBuffer(HWBuffer); + return 0; + } - if (!updateHardwareBuffer(HWBuffer)) { + return HWBuffer; +#else + return 0; +#endif +} + +//! Create hardware buffer from meshbuffer +COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IIndexBuffer *ib) +{ +#if defined(GL_ARB_vertex_buffer_object) + if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER) + return 0; + + SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib); + + // add to map + HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + + if (!updateIndexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); return 0; } @@ -473,51 +484,51 @@ void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) return; #if defined(GL_ARB_vertex_buffer_object) - SHWBufferLink_opengl *HWBuffer = (SHWBufferLink_opengl *)_HWBuffer; - if (HWBuffer->vbo_verticesID) { - extGlDeleteBuffers(1, &HWBuffer->vbo_verticesID); - HWBuffer->vbo_verticesID = 0; - } - if (HWBuffer->vbo_indicesID) { - extGlDeleteBuffers(1, &HWBuffer->vbo_indicesID); - HWBuffer->vbo_indicesID = 0; + auto *HWBuffer = (SHWBufferLink_opengl *)_HWBuffer; + if (HWBuffer->vbo_ID) { + extGlDeleteBuffers(1, &HWBuffer->vbo_ID); + HWBuffer->vbo_ID = 0; } #endif CNullDriver::deleteHardwareBuffer(_HWBuffer); } -//! Draw hardware buffer -void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) +void COpenGLDriver::drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 PrimitiveCount, + scene::E_PRIMITIVE_TYPE PrimitiveType) { - if (!_HWBuffer) + if (!vb || !ib) return; - updateHardwareBuffer(_HWBuffer); // check if update is needed - #if defined(GL_ARB_vertex_buffer_object) - SHWBufferLink_opengl *HWBuffer = (SHWBufferLink_opengl *)_HWBuffer; + auto *hwvert = (SHWBufferLink_opengl *) getBufferLink(vb); + auto *hwidx = (SHWBufferLink_opengl *) getBufferLink(ib); + updateHardwareBuffer(hwvert); + updateHardwareBuffer(hwidx); - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; - const void *vertices = mb->getVertices(); - const void *indexList = mb->getIndices(); - - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) { - extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); + const void *vertices = vb->getData(); + if (hwvert) { + extGlBindBuffer(GL_ARRAY_BUFFER, hwvert->vbo_ID); vertices = 0; } - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) { - extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); + const void *indexList = ib->getData(); + if (hwidx) { + extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hwidx->vbo_ID); indexList = 0; } - drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType()); + drawVertexPrimitiveList(vertices, vb->getCount(), indexList, + PrimitiveCount, vb->getType(), PrimitiveType, ib->getType()); - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) + if (hwvert) extGlBindBuffer(GL_ARRAY_BUFFER, 0); - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + if (hwidx) extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#else + drawVertexPrimitiveList(vb->getData(), vb->getCount(), ib->getData(), + PrimitiveCount, vb->getType(), PrimitiveType, ib->getType()); #endif } diff --git a/irr/src/COpenGLDriver.h b/irr/src/COpenGLDriver.h index 3c0a718fc..9c4ecd3b3 100644 --- a/irr/src/COpenGLDriver.h +++ b/irr/src/COpenGLDriver.h @@ -58,27 +58,28 @@ public: struct SHWBufferLink_opengl : public SHWBufferLink { - SHWBufferLink_opengl(const scene::IMeshBuffer *_MeshBuffer) : - SHWBufferLink(_MeshBuffer), vbo_verticesID(0), vbo_indicesID(0) {} + SHWBufferLink_opengl(const scene::IVertexBuffer *vb) : SHWBufferLink(vb) {} + SHWBufferLink_opengl(const scene::IIndexBuffer *ib) : SHWBufferLink(ib) {} - GLuint vbo_verticesID; // tmp - GLuint vbo_indicesID; // tmp - - GLuint vbo_verticesSize; // tmp - GLuint vbo_indicesSize; // tmp + GLuint vbo_ID = 0; + u32 vbo_Size = 0; }; //! updates hardware buffer if needed bool updateHardwareBuffer(SHWBufferLink *HWBuffer) override; - //! Create hardware buffer from mesh - SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer *mb) override; + //! Create hardware buffer from vertex buffer + SHWBufferLink *createHardwareBuffer(const scene::IVertexBuffer *vb) override; + + //! Create hardware buffer from index buffer + SHWBufferLink *createHardwareBuffer(const scene::IIndexBuffer *ib) override; //! Delete hardware buffer (only some drivers can) void deleteHardwareBuffer(SHWBufferLink *HWBuffer) override; - //! Draw hardware buffer - void drawHardwareBuffer(SHWBufferLink *HWBuffer) override; + void drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 primCount, + scene::E_PRIMITIVE_TYPE pType = scene::EPT_TRIANGLES) override; //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp index f681a3de9..46aa36d5c 100644 --- a/irr/src/OpenGL/Driver.cpp +++ b/irr/src/OpenGL/Driver.cpp @@ -477,44 +477,36 @@ void COpenGL3DriverBase::setTransform(E_TRANSFORMATION_STATE state, const core:: Transformation3DChanged = true; } -bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) +bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink_opengl *HWBuffer, + const void *buffer, size_t bufferSize, scene::E_HARDWARE_MAPPING hint) { - if (!HWBuffer) - return false; + assert(HWBuffer); - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; - const void *vertices = mb->getVertices(); - const u32 vertexCount = mb->getVertexCount(); - const E_VERTEX_TYPE vType = mb->getVertexType(); - const u32 vertexSize = getVertexPitchFromType(vType); - - const void *buffer = vertices; - size_t bufferSize = vertexSize * vertexCount; accountHWBufferUpload(bufferSize); // get or create buffer bool newBuffer = false; - if (!HWBuffer->vbo_verticesID) { - GL.GenBuffers(1, &HWBuffer->vbo_verticesID); - if (!HWBuffer->vbo_verticesID) + if (!HWBuffer->vbo_ID) { + GL.GenBuffers(1, &HWBuffer->vbo_ID); + if (!HWBuffer->vbo_ID) return false; newBuffer = true; - } else if (HWBuffer->vbo_verticesSize < bufferSize) { + } else if (HWBuffer->vbo_Size < bufferSize) { newBuffer = true; } - GL.BindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); + GL.BindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_ID); // copy data to graphics card if (!newBuffer) GL.BufferSubData(GL_ARRAY_BUFFER, 0, bufferSize, buffer); else { - HWBuffer->vbo_verticesSize = bufferSize; + HWBuffer->vbo_Size = bufferSize; GLenum usage = GL_STATIC_DRAW; - if (HWBuffer->Mapped_Index == scene::EHM_STREAM) + if (hint == scene::EHM_STREAM) usage = GL_STREAM_DRAW; - else if (HWBuffer->Mapped_Index == scene::EHM_DYNAMIC) + else if (hint == scene::EHM_DYNAMIC) usage = GL_DYNAMIC_DRAW; GL.BufferData(GL_ARRAY_BUFFER, bufferSize, buffer, usage); } @@ -524,67 +516,47 @@ bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuff return (!TEST_GL_ERROR(this)); } +bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) +{ + if (!HWBuffer) + return false; + + assert(HWBuffer->IsVertex); + const auto *vb = HWBuffer->VertexBuffer; + assert(vb); + + const u32 vertexSize = getVertexPitchFromType(vb->getType()); + const size_t bufferSize = vertexSize * vb->getCount(); + + return updateHardwareBuffer(HWBuffer, vb->getData(), bufferSize, vb->getHardwareMappingHint()); +} + bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) { if (!HWBuffer) return false; - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; + assert(!HWBuffer->IsVertex); + const auto *ib = HWBuffer->IndexBuffer; + assert(ib); - const void *indices = mb->getIndices(); - u32 indexCount = mb->getIndexCount(); - - GLenum indexSize; - switch (mb->getIndexType()) { - case (EIT_16BIT): { + u32 indexSize; + switch (ib->getType()) { + case EIT_16BIT: indexSize = sizeof(u16); break; - } - case (EIT_32BIT): { + case EIT_32BIT: indexSize = sizeof(u32); break; - } - default: { + default: return false; } - } - const size_t bufferSize = indexCount * indexSize; - accountHWBufferUpload(bufferSize); + const size_t bufferSize = ib->getCount() * indexSize; - // get or create buffer - bool newBuffer = false; - if (!HWBuffer->vbo_indicesID) { - GL.GenBuffers(1, &HWBuffer->vbo_indicesID); - if (!HWBuffer->vbo_indicesID) - return false; - newBuffer = true; - } else if (HWBuffer->vbo_indicesSize < bufferSize) { - newBuffer = true; - } - - GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); - - // copy data to graphics card - if (!newBuffer) - GL.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, bufferSize, indices); - else { - HWBuffer->vbo_indicesSize = bufferSize; - - GLenum usage = GL_STATIC_DRAW; - if (HWBuffer->Mapped_Index == scene::EHM_STREAM) - usage = GL_STREAM_DRAW; - else if (HWBuffer->Mapped_Index == scene::EHM_DYNAMIC) - usage = GL_DYNAMIC_DRAW; - GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, indices, usage); - } - - GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - return (!TEST_GL_ERROR(this)); + return updateHardwareBuffer(HWBuffer, ib->getData(), bufferSize, ib->getHardwareMappingHint()); } -//! updates hardware buffer if needed bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink *HWBuffer) { if (!HWBuffer) @@ -592,50 +564,35 @@ bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink *HWBuffer) auto *b = static_cast(HWBuffer); - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !b->vbo_verticesID) { - - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); - + if (b->IsVertex) { + assert(b->VertexBuffer); + if (b->ChangedID != b->VertexBuffer->getChangedID() || !b->vbo_ID) { if (!updateVertexHardwareBuffer(b)) return false; + b->ChangedID = b->VertexBuffer->getChangedID(); } - } - - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !b->vbo_indicesID) { - - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - + } else { + assert(b->IndexBuffer); + if (b->ChangedID != b->IndexBuffer->getChangedID() || !b->vbo_ID) { if (!updateIndexHardwareBuffer(b)) return false; + b->ChangedID = b->IndexBuffer->getChangedID(); } } - return true; } -//! Create hardware buffer from meshbuffer -COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(const scene::IMeshBuffer *mb) +COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(const scene::IVertexBuffer *vb) { - if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)) + if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER) return 0; - SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb); + SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb); // add to map HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - HWBuffer->Mapped_Vertex = mb->getHardwareMappingHint_Vertex(); - HWBuffer->Mapped_Index = mb->getHardwareMappingHint_Index(); - HWBuffer->vbo_verticesID = 0; - HWBuffer->vbo_indicesID = 0; - HWBuffer->vbo_verticesSize = 0; - HWBuffer->vbo_indicesSize = 0; - - if (!updateHardwareBuffer(HWBuffer)) { + if (!updateVertexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); return 0; } @@ -643,57 +600,70 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons return HWBuffer; } -void COpenGL3DriverBase::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) +COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(const scene::IIndexBuffer *ib) { - if (!_HWBuffer) - return; + if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER) + return 0; - SHWBufferLink_opengl *HWBuffer = static_cast(_HWBuffer); - if (HWBuffer->vbo_verticesID) { - GL.DeleteBuffers(1, &HWBuffer->vbo_verticesID); - HWBuffer->vbo_verticesID = 0; - } - if (HWBuffer->vbo_indicesID) { - GL.DeleteBuffers(1, &HWBuffer->vbo_indicesID); - HWBuffer->vbo_indicesID = 0; + SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib); + + // add to map + HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + + if (!updateIndexHardwareBuffer(HWBuffer)) { + deleteHardwareBuffer(HWBuffer); + return 0; } - CNullDriver::deleteHardwareBuffer(_HWBuffer); + return HWBuffer; } -//! Draw hardware buffer -void COpenGL3DriverBase::drawHardwareBuffer(SHWBufferLink *_HWBuffer) +void COpenGL3DriverBase::deleteHardwareBuffer(SHWBufferLink *HWBuffer) { - if (!_HWBuffer) + if (!HWBuffer) return; - SHWBufferLink_opengl *HWBuffer = static_cast(_HWBuffer); - - updateHardwareBuffer(HWBuffer); // check if update is needed - - const scene::IMeshBuffer *mb = HWBuffer->MeshBuffer; - const void *vertices = mb->getVertices(); - const void *indexList = mb->getIndices(); - - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) { - GL.BindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); - vertices = 0; + auto *b = static_cast(HWBuffer); + if (b->vbo_ID) { + GL.DeleteBuffers(1, &b->vbo_ID); + b->vbo_ID = 0; } - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) { - GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); - indexList = 0; + CNullDriver::deleteHardwareBuffer(HWBuffer); +} + +void COpenGL3DriverBase::drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 PrimitiveCount, + scene::E_PRIMITIVE_TYPE PrimitiveType) +{ + if (!vb || !ib) + return; + + auto *hwvert = static_cast(getBufferLink(vb)); + auto *hwidx = static_cast(getBufferLink(ib)); + updateHardwareBuffer(hwvert); + updateHardwareBuffer(hwidx); + + const void *vertices = vb->getData(); + if (hwvert) { + assert(hwvert->IsVertex); + GL.BindBuffer(GL_ARRAY_BUFFER, hwvert->vbo_ID); + vertices = nullptr; } - drawVertexPrimitiveList(vertices, mb->getVertexCount(), - indexList, mb->getPrimitiveCount(), - mb->getVertexType(), mb->getPrimitiveType(), - mb->getIndexType()); + const void *indexList = ib->getData(); + if (hwidx) { + assert(!hwidx->IsVertex); + GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, hwidx->vbo_ID); + indexList = nullptr; + } - if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) + drawVertexPrimitiveList(vertices, vb->getCount(), indexList, + PrimitiveCount, vb->getType(), PrimitiveType, ib->getType()); + + if (hwvert) GL.BindBuffer(GL_ARRAY_BUFFER, 0); - - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + if (hwidx) GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/irr/src/OpenGL/Driver.h b/irr/src/OpenGL/Driver.h index be4e4db9e..3104b164d 100644 --- a/irr/src/OpenGL/Driver.h +++ b/irr/src/OpenGL/Driver.h @@ -46,16 +46,11 @@ public: struct SHWBufferLink_opengl : public SHWBufferLink { - SHWBufferLink_opengl(const scene::IMeshBuffer *meshBuffer) : - SHWBufferLink(meshBuffer), vbo_verticesID(0), vbo_indicesID(0), vbo_verticesSize(0), vbo_indicesSize(0) - { - } + SHWBufferLink_opengl(const scene::IVertexBuffer *vb) : SHWBufferLink(vb) {} + SHWBufferLink_opengl(const scene::IIndexBuffer *ib) : SHWBufferLink(ib) {} - u32 vbo_verticesID; // tmp - u32 vbo_indicesID; // tmp - - u32 vbo_verticesSize; // tmp - u32 vbo_indicesSize; // tmp + GLuint vbo_ID = 0; + u32 vbo_Size = 0; }; bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); @@ -64,14 +59,18 @@ public: //! updates hardware buffer if needed bool updateHardwareBuffer(SHWBufferLink *HWBuffer) override; - //! Create hardware buffer from mesh - SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer *mb) override; + //! Create hardware buffer from vertex buffer + SHWBufferLink *createHardwareBuffer(const scene::IVertexBuffer *vb) override; + + //! Create hardware buffer from index buffer + SHWBufferLink *createHardwareBuffer(const scene::IIndexBuffer *ib) override; //! Delete hardware buffer (only some drivers can) void deleteHardwareBuffer(SHWBufferLink *HWBuffer) override; - //! Draw hardware buffer - void drawHardwareBuffer(SHWBufferLink *HWBuffer) override; + void drawBuffers(const scene::IVertexBuffer *vb, + const scene::IIndexBuffer *ib, u32 primCount, + scene::E_PRIMITIVE_TYPE pType = scene::EPT_TRIANGLES) override; IRenderTarget *addRenderTarget() override; @@ -291,10 +290,7 @@ protected: LockRenderStateMode = false; } - void draw2D3DVertexPrimitiveList(const void *vertices, - u32 vertexCount, const void *indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, - E_INDEX_TYPE iType, bool is3D); + bool updateHardwareBuffer(SHWBufferLink_opengl *b, const void *buffer, size_t bufferSize, scene::E_HARDWARE_MAPPING hint); void createMaterialRenderers();