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