diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 69236c86dd..19c3bd8673 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -44,6 +44,7 @@ #include "gl/shaders/gl_shaderprogram.h" #include "gl_debug.h" #include "r_videoscale.h" +#include "glsys_vertexbuffer.h" EXTERN_CVAR (Bool, vid_vsync) @@ -361,6 +362,16 @@ IShaderProgram *OpenGLFrameBuffer::CreateShaderProgram() return new FShaderProgram; } +IVertexBuffer *OpenGLFrameBuffer::CreateVertexBuffer() +{ + return new GLVertexBuffer; +} + +IIndexBuffer *OpenGLFrameBuffer::CreateIndexBuffer() +{ + return new GLIndexBuffer; +} + void OpenGLFrameBuffer::TextureFilterChanged() { diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 4c1c59ce17..2a6ff6457f 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -43,6 +43,8 @@ public: void BlurScene(float amount) override; IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) override; IShaderProgram *CreateShaderProgram() override; + IVertexBuffer *CreateVertexBuffer() override; + IIndexBuffer *CreateIndexBuffer() override; // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer diff --git a/src/gl/system/glsys_vertexbuffer.cpp b/src/gl/system/glsys_vertexbuffer.cpp index 22685b5392..9797821515 100644 --- a/src/gl/system/glsys_vertexbuffer.cpp +++ b/src/gl/system/glsys_vertexbuffer.cpp @@ -30,7 +30,7 @@ //========================================================================== // -// Create / destroy the VBO +// Vertex buffer implementation // //========================================================================== @@ -47,6 +47,7 @@ GLVertexBuffer::~GLVertexBuffer() glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &vbo_id); + gl_RenderState.ResetVertexBuffer(); } } @@ -141,3 +142,41 @@ void GLVertexBuffer::Bind(size_t *offsets) i++; } } + +//========================================================================== +// +// Index buffer implementation +// +//========================================================================== + +GLIndexBuffer::GLIndexBuffer() +{ + glGenBuffers(1, &ibo_id); +} + +GLIndexBuffer::~GLIndexBuffer() +{ + if (ibo_id != 0) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &ibo_id); + } +} + +void GLIndexBuffer::SetData(size_t size, void *data, bool staticdata) +{ + if (data != nullptr) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, staticdata? GL_STATIC_DRAW : GL_STREAM_DRAW); + } + buffersize = size; + gl_RenderState.ResetVertexBuffer(); // This is needed because glBindBuffer overwrites the setting stored in the render state. +} + +void GLIndexBuffer::Bind() +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); +} diff --git a/src/gl/system/glsys_vertexbuffer.h b/src/gl/system/glsys_vertexbuffer.h index eaf2b97304..d0f74e6a31 100644 --- a/src/gl/system/glsys_vertexbuffer.h +++ b/src/gl/system/glsys_vertexbuffer.h @@ -2,7 +2,7 @@ #include "hwrenderer/data/vertexbuffer.h" -class GLVertexBuffer : IVertexBuffer +class GLVertexBuffer : public IVertexBuffer { // If this could use the modern (since GL 4.3) binding system, things would be simpler... :( struct GLVertexBufferAttribute @@ -22,10 +22,21 @@ class GLVertexBuffer : IVertexBuffer public: GLVertexBuffer(); ~GLVertexBuffer(); - void SetData(size_t size, void *data, bool staticdata) = 0; + void SetData(size_t size, void *data, bool staticdata) override; void SetFormat(int numBindingPoints, int numAttributes, size_t stride, FVertexBufferAttribute *attrs) override; void Bind(size_t *offsets); void Map() override; void Unmap() override; }; +class GLIndexBuffer : public IIndexBuffer +{ + unsigned int ibo_id = 0; + +public: + GLIndexBuffer(); + ~GLIndexBuffer(); + void SetData(size_t size, void *data, bool staticdata) override; + void Bind(); +}; + diff --git a/src/hwrenderer/data/vertexbuffer.h b/src/hwrenderer/data/vertexbuffer.h index 411f3e2906..d590061276 100644 --- a/src/hwrenderer/data/vertexbuffer.h +++ b/src/hwrenderer/data/vertexbuffer.h @@ -48,3 +48,16 @@ public: void *Memory() { assert(map); return map; } }; + +class IIndexBuffer +{ +protected: + // Element size is fixed to 4, thanks to OpenGL requiring this info to be coded into the glDrawElements call. + // This mostly prohibits a more flexible buffer setup but GZDoom doesn't use any other format anyway. + // Ob Vulkam, element size is a buffer property and of no concern to the drawing functions (as it should be.) + size_t buffersize = 0; +public: + virtual ~IIndexBuffer() {} + virtual void SetData(size_t size, void *data, bool staticdata = true) = 0; +}; + diff --git a/src/v_video.h b/src/v_video.h index 7e583a92a5..2087be8c6e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -50,6 +50,8 @@ class IShaderProgram; class FTexture; struct FPortalSceneState; class FSkyDomeCreator; +class IIndexBuffer; +class IVertexBuffer; enum EHWCaps { @@ -450,6 +452,8 @@ public: // Interface to hardware rendering resources virtual IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) { return nullptr; } virtual IShaderProgram *CreateShaderProgram() { return nullptr; } + virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; } + virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; } bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); } // Begin/End 2D drawing operations.