From 578368f452a2d3dc1702d522d88e3bd320c2e724 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 21 Apr 2012 08:18:24 +0000 Subject: [PATCH] gpu: abstraction class for index buffers; the cube tutorial no longer needs to know about Direct3D headers etc. --- src/Makefile.am | 2 +- src/core.h | 2 +- src/gpu/indexbuffer.cpp | 134 +++++++++++++++++++++++++++++++ src/gpu/{vbo.h => indexbuffer.h} | 30 ++++--- src/gpu/vbo.cpp | 100 ----------------------- src/gpu/vertexbuffer.cpp | 25 ++++++ src/gpu/vertexbuffer.h | 2 + test/tutorial/02_cube.cpp | 67 ++-------------- win32/lolcore.vcxproj | 2 - win32/lolcore.vcxproj.filters | 8 +- 10 files changed, 188 insertions(+), 184 deletions(-) create mode 100644 src/gpu/indexbuffer.cpp rename src/gpu/{vbo.h => indexbuffer.h} (50%) delete mode 100644 src/gpu/vbo.cpp diff --git a/src/Makefile.am b/src/Makefile.am index c0196736..1537c453 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,7 @@ liblol_a_SOURCES = \ math/vector.cpp math/real.cpp math/half.cpp math/trig.cpp math/trig.h \ \ gpu/shader.cpp gpu/shader.h \ - gpu/vbo.cpp gpu/vbo.h \ + gpu/indexbuffer.cpp gpu/indexbuffer.h \ gpu/vertexbuffer.cpp gpu/vertexbuffer.h \ \ image/image.cpp image/image.h image/image-private.h \ diff --git a/src/core.h b/src/core.h index 397c0fe7..719f9b12 100644 --- a/src/core.h +++ b/src/core.h @@ -100,8 +100,8 @@ static inline int isnan(float f) #include "map.h" #include "layer.h" #include "gpu/shader.h" +#include "gpu/indexbuffer.h" #include "gpu/vertexbuffer.h" -#include "gpu/vbo.h" #include "image/image.h" #include "application/application.h" diff --git a/src/gpu/indexbuffer.cpp b/src/gpu/indexbuffer.cpp new file mode 100644 index 00000000..c69283c5 --- /dev/null +++ b/src/gpu/indexbuffer.cpp @@ -0,0 +1,134 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2012 Sam Hocevar +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include "core.h" +#include "lolgl.h" + +#if defined _WIN32 && defined USE_D3D9 +# define FAR +# define NEAR +# include +#endif + +using namespace std; + +#if defined USE_D3D9 +extern IDirect3DDevice9 *g_d3ddevice; +#elif defined _XBOX +extern D3DDevice *g_d3ddevice; +#endif + +namespace lol +{ + +// +// The IndexBufferData class +// -------------------------- +// + +class IndexBufferData +{ + friend class IndexBuffer; + +#if defined USE_D3D9 + IDirect3DIndexBuffer9 *m_ibo; +#elif defined _XBOX + D3DIndexBuffer *m_ibo; +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + GLuint m_ibo; + uint8_t *m_memory; + size_t m_size; +#endif +}; + +// +// The IndexBuffer class +// ---------------------- +// + +IndexBuffer::IndexBuffer(size_t size) + : m_data(new IndexBufferData) +{ +#if defined USE_D3D9 || defined _XBOX + if (FAILED(g_d3ddevice->CreateIndexBuffer(size, D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, D3DPOOL_MANAGED, + &m_data->m_ibo, NULL))) + Abort(); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + glGenBuffers(1, &m_data->m_ibo); + m_data->m_memory = new uint8_t[size]; + m_data->m_size = size; +#endif +} + +IndexBuffer::~IndexBuffer() +{ +#if defined USE_D3D9 || defined _XBOX + if (FAILED(m_data->m_ibo->Release())) + Abort(); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + glDeleteBuffers(1, &m_data->m_ibo); + delete[] m_data->m_memory; +#endif +} + +void *IndexBuffer::Lock(size_t offset, size_t size) +{ +#if defined USE_D3D9 || defined _XBOX + void *ret; + if (FAILED(m_data->m_ibo->Lock(offset, size, (void **)&ret, 0))) + Abort(); + return ret; +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + return m_data->m_memory + offset; +#endif +} + +void IndexBuffer::Unlock() +{ +#if defined USE_D3D9 || defined _XBOX + if (FAILED(m_data->m_ibo->Unlock())) + Abort(); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_data->m_size, m_data->m_memory, + GL_STATIC_DRAW); +#endif +} + +void IndexBuffer::Bind() +{ +#if defined USE_D3D9 || defined _XBOX + if (FAILED(g_d3ddevice->SetIndices(m_data->m_ibo))) + Abort(); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_ibo); + /* XXX: not necessary because we kept track of the size */ + //int size; + //glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); +#endif +} + +void IndexBuffer::Unbind() +{ +#if defined USE_D3D9 || defined _XBOX + if (FAILED(g_d3ddevice->SetIndices(NULL))) + Abort(); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif +} + +} /* namespace lol */ + diff --git a/src/gpu/vbo.h b/src/gpu/indexbuffer.h similarity index 50% rename from src/gpu/vbo.h rename to src/gpu/indexbuffer.h index 4f8b0c5e..4d84060b 100644 --- a/src/gpu/vbo.h +++ b/src/gpu/indexbuffer.h @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright: (c) 2010-2011 Sam Hocevar +// Copyright: (c) 2010-2012 Sam Hocevar // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See @@ -9,37 +9,35 @@ // // -// The GpuVbo class -// ---------------- +// The IndexBuffer class +// --------------------- // -#if !defined __LOL_VBO_H__ -#define __LOL_VBO_H__ +#if !defined __LOL_INDEXBUFFER_H__ +#define __LOL_INDEXBUFFER_H__ + +#include namespace lol { -class GpuVboData; - -class GpuVbo +class IndexBuffer { public: - GpuVbo(); - ~GpuVbo(); + IndexBuffer(size_t size); + ~IndexBuffer(); - void SetSize(size_t elemsize, size_t elemcount); - size_t GetSize(); - uint8_t *GetData(); - uint8_t const *GetData() const; + void *Lock(size_t offset, size_t size); + void Unlock(); void Bind(); void Unbind(); private: - GpuVboData *data; + class IndexBufferData *m_data; }; } /* namespace lol */ -#endif // __LOL_VBO_H__ +#endif // __LOL_INDEXBUFFER_H__ diff --git a/src/gpu/vbo.cpp b/src/gpu/vbo.cpp deleted file mode 100644 index baee78cb..00000000 --- a/src/gpu/vbo.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// Lol Engine -// -// Copyright: (c) 2010-2011 Sam Hocevar -// This program is free software; you can redistribute it and/or -// modify it under the terms of the Do What The Fuck You Want To -// Public License, Version 2, as published by Sam Hocevar. See -// http://sam.zoy.org/projects/COPYING.WTFPL for more details. -// - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include "core.h" -#include "lolgl.h" -#include "gpu/vbo.h" - -using namespace std; - -namespace lol -{ - -/* - * GpuVbo implementation class - */ - -class GpuVboData -{ - friend class GpuVbo; - - size_t elemsize, elemcount; - uint8_t *alloc_buffer; - - static size_t const GPU_ALIGN = 128; -}; - -/* - * Public GpuVbo class - */ - -GpuVbo::GpuVbo() - : data(new GpuVboData()) -{ - data->elemsize = 0; - data->elemcount = 0; - data->alloc_buffer = 0; -} - -void GpuVbo::SetSize(size_t elemsize, size_t elemcount) -{ - size_t oldsize = data->elemsize * data->elemcount; - size_t newsize = elemsize * elemcount; - - if (newsize == oldsize) - return; - - if (oldsize) - delete[] data->alloc_buffer; - data->alloc_buffer = NULL; - if (newsize) - data->alloc_buffer = new uint8_t[newsize + GpuVboData::GPU_ALIGN - 1]; - - data->elemsize = elemsize; - data->elemcount = elemcount; -} - -size_t GpuVbo::GetSize() -{ - return data->elemsize * data->elemcount; -} - -uint8_t *GpuVbo::GetData() -{ - return (uint8_t *)(((uintptr_t)data->alloc_buffer) - & ~((uintptr_t)GpuVboData::GPU_ALIGN - 1)); -} - -uint8_t const *GpuVbo::GetData() const -{ - return (uint8_t const *)(((uintptr_t)data->alloc_buffer) - & ~((uintptr_t)GpuVboData::GPU_ALIGN - 1)); -} - -void GpuVbo::Bind() -{ -} - -void GpuVbo::Unbind() -{ -} - -GpuVbo::~GpuVbo() -{ - delete[] data->alloc_buffer; - delete data; -} - -} /* namespace lol */ - diff --git a/src/gpu/vertexbuffer.cpp b/src/gpu/vertexbuffer.cpp index 96d33f2e..61de6ceb 100644 --- a/src/gpu/vertexbuffer.cpp +++ b/src/gpu/vertexbuffer.cpp @@ -142,6 +142,31 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) #endif } +void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, + int vskip, int vcount, + int skip, int count) +{ +#if defined _XBOX || defined USE_D3D9 + if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW))) + Abort(); + switch (type) + { + case MeshPrimitive::Triangles: + if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vbase, vskip, vcount, skip, count))) + Abort(); + break; + } +#else + switch (type) + { + case MeshPrimitive::Triangles: + /* FIXME: ignores most of the arguments! */ + glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, 0); + break; + } +#endif +} + void VertexDeclaration::Unbind() { #if defined _XBOX || defined USE_D3D9 diff --git a/src/gpu/vertexbuffer.h b/src/gpu/vertexbuffer.h index 1ea63f42..09e636fa 100644 --- a/src/gpu/vertexbuffer.h +++ b/src/gpu/vertexbuffer.h @@ -177,6 +177,8 @@ public: void Bind(); void DrawElements(MeshPrimitive type, int skip, int count); + void DrawIndexedElements(MeshPrimitive type, int vbase, int vskip, + int vcount, int skip, int count); void Unbind(); void SetStream(VertexBuffer *vb, ShaderAttrib attr1, ShaderAttrib attr2 = ShaderAttrib(), diff --git a/test/tutorial/02_cube.cpp b/test/tutorial/02_cube.cpp index c8e042c3..5c489530 100644 --- a/test/tutorial/02_cube.cpp +++ b/test/tutorial/02_cube.cpp @@ -13,18 +13,11 @@ #endif #include "core.h" -#include "lolgl.h" #include "loldebug.h" using namespace std; using namespace lol; -#if defined _WIN32 && defined USE_D3D9 -# define FAR -# define NEAR -# include -#endif - #if USE_SDL && defined __APPLE__ # include #endif @@ -34,12 +27,6 @@ using namespace lol; # include #endif -#if defined USE_D3D9 -extern IDirect3DDevice9 *g_d3ddevice; -#elif defined _XBOX -extern D3DDevice *g_d3ddevice; -#endif - class Cube : public WorldEntity { public: @@ -144,23 +131,10 @@ public: memcpy(mesh, &m_mesh[0], m_mesh.Bytes()); m_vbo->Unlock(); -#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ && !defined _XBOX && !defined USE_D3D9 - /* Method 1: store vertex buffer on the GPU memory */ - glGenBuffers(1, &m_ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.Bytes(), - &m_indices[0], GL_STATIC_DRAW); -#elif defined _XBOX || defined USE_D3D9 - int16_t *indices; - if (FAILED(g_d3ddevice->CreateIndexBuffer(m_indices.Bytes(), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_ibo, NULL))) - Abort(); - if (FAILED(m_ibo->Lock(0, 0, (void **)&indices, 0))) - Abort(); + m_ibo = new IndexBuffer(m_indices.Bytes()); + void *indices = m_ibo->Lock(0, 0); memcpy(indices, &m_indices[0], m_indices.Bytes()); m_ibo->Unlock(); -#else - /* TODO */ -#endif /* FIXME: this object never cleans up */ m_ready = true; @@ -172,29 +146,10 @@ public: m_shader->SetUniform(m_mvp, m_matrix); m_vdecl->SetStream(m_vbo, m_coord, m_color); m_vdecl->Bind(); - -#if defined _XBOX || defined USE_D3D9 - if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW))) - Abort(); - if (FAILED(g_d3ddevice->SetIndices(m_ibo))) - Abort(); - if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, m_indices.Count()))) - Abort(); -#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo); - int size; - glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - - - glDrawElements(GL_TRIANGLES, size / sizeof(uint16_t), GL_UNSIGNED_SHORT, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); -#else - /* FIXME */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, m_vertices); - glDisableClientState(GL_VERTEX_ARRAY); -#endif + m_ibo->Bind(); + m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0, 8, 0, + m_indices.Count()); + m_ibo->Unbind(); m_vdecl->Unbind(); } @@ -208,15 +163,7 @@ private: ShaderUniform m_mvp; VertexDeclaration *m_vdecl; VertexBuffer *m_vbo; -#if defined USE_D3D9 - IDirect3DIndexBuffer9 *m_ibo; -#elif defined _XBOX - D3DIndexBuffer *m_ibo; -#else -#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ - GLuint m_ibo; -#endif -#endif + IndexBuffer *m_ibo; bool m_ready; }; diff --git a/win32/lolcore.vcxproj b/win32/lolcore.vcxproj index 233b2344..a92b68b7 100644 --- a/win32/lolcore.vcxproj +++ b/win32/lolcore.vcxproj @@ -86,7 +86,6 @@ - @@ -140,7 +139,6 @@ - diff --git a/win32/lolcore.vcxproj.filters b/win32/lolcore.vcxproj.filters index 8292dc7b..0965997c 100644 --- a/win32/lolcore.vcxproj.filters +++ b/win32/lolcore.vcxproj.filters @@ -160,10 +160,10 @@ src - + src\gpu - + src\gpu @@ -336,10 +336,10 @@ src\lol - + src\gpu - + src\gpu