From ebef7085e2672866189ccdb3a89e977e678a89b9 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 11 Sep 2021 13:40:18 +0300 Subject: [PATCH] Create a class for issuing drawing commands This is a precursor to command buffers in Vulkan. --- source/core/batch.cpp | 49 ------------------------ source/core/batch.h | 7 +--- source/core/commands.cpp | 70 +++++++++++++++++++++++++++++++++++ source/core/commands.h | 30 +++++++++++++++ source/core/pipelinestate.cpp | 14 +++++++ source/core/pipelinestate.h | 2 + source/render/renderer.cpp | 33 ++++------------- source/render/renderer.h | 2 + 8 files changed, 127 insertions(+), 80 deletions(-) create mode 100644 source/core/commands.cpp create mode 100644 source/core/commands.h diff --git a/source/core/batch.cpp b/source/core/batch.cpp index ebd7b049..d53156bd 100644 --- a/source/core/batch.cpp +++ b/source/core/batch.cpp @@ -1,4 +1,3 @@ -#include #include #include "batch.h" #include "buffer.h" @@ -187,54 +186,6 @@ unsigned Batch::get_index(unsigned i) const return *(UInt16 *)&data[i*sizeof(UInt16)]; } -void Batch::draw() const -{ - const void *data_ptr = setup_draw(); - glDrawElements(prim_type, size(), gl_index_type, data_ptr); -} - -void Batch::draw_instanced(unsigned count) const -{ - static Require req(ARB_draw_instanced); - - const void *data_ptr = setup_draw(); - glDrawElementsInstanced(prim_type, size(), gl_index_type, data_ptr, count); -} - -const void *Batch::setup_draw() const -{ - if(!get_buffer()) - throw invalid_operation("Batch::setup_draw"); - - if(restart) - { - unsigned index = (index_type==UNSIGNED_INT ? 0xFFFFFFFF : 0xFFFF); - - if(index!=restart_index) - set_restart_index(index); - } - else if(restart_index && restart_index<=max_index) - set_restart_index(0); - - refresh(); - - return reinterpret_cast(get_offset()); -} - -void Batch::set_restart_index(unsigned index) -{ - if(index>0) - { - if(!restart_index) - glEnable(GL_PRIMITIVE_RESTART); - glPrimitiveRestartIndex(index); - } - else - glDisable(GL_PRIMITIVE_RESTART); - - restart_index = index; -} - Batch::Loader::Loader(Batch &b): DataFile::ObjectLoader(b) diff --git a/source/core/batch.h b/source/core/batch.h index 0435feec..3fedeaf8 100644 --- a/source/core/batch.h +++ b/source/core/batch.h @@ -48,6 +48,7 @@ public: PrimitiveType get_type() const { return prim_type; } void set_index_type(DataType); DataType get_index_type() const { return index_type; } + GLenum get_gl_index_type() const { return gl_index_type; } DEPRECATED void set_data_type(DataType t) { set_index_type(t); } DEPRECATED DataType get_data_type() const { return index_type; } @@ -66,12 +67,6 @@ public: unsigned size() const { return data.size()/get_index_size(); } unsigned get_index(unsigned) const; - - void draw() const; - void draw_instanced(unsigned) const; -private: - const void *setup_draw() const; - static void set_restart_index(unsigned); }; } // namespace GL diff --git a/source/core/commands.cpp b/source/core/commands.cpp new file mode 100644 index 00000000..72b5a939 --- /dev/null +++ b/source/core/commands.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include "batch.h" +#include "commands.h" +#include "gl.h" +#include "pipelinestate.h" + +using namespace std; + +namespace Msp { +namespace GL { + +Commands::Commands(): + pipeline_state(0) +{ } + +void Commands::use_pipeline(const PipelineState &ps) +{ + pipeline_state = &ps; +} + +void Commands::clear(BufferBits buffers) +{ + pipeline_state->apply(); + glClear(buffers); +} + +void Commands::draw(const Batch &batch) +{ + pipeline_state->apply(); + void *data_ptr = reinterpret_cast(batch.get_offset()); + glDrawElements(batch.get_type(), batch.size(), batch.get_gl_index_type(), data_ptr); +} + +void Commands::draw_instanced(const Batch &batch, unsigned count) +{ + static Require req(ARB_draw_instanced); + + pipeline_state->apply(); + void *data_ptr = reinterpret_cast(batch.get_offset()); + glDrawElementsInstanced(batch.get_type(), batch.size(), batch.get_gl_index_type(), data_ptr, count); +} + +void Commands::resolve_multisample(Framebuffer &target, BufferBits buffers) +{ + const Framebuffer *source = pipeline_state->get_framebuffer(); + + unsigned width = min(source->get_width(), target.get_width()); + unsigned height = min(source->get_height(), target.get_height()); + + if(ARB_direct_state_access) + glBlitNamedFramebuffer(source->get_id(), target.get_id(), 0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST); + else + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, source->get_id()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.get_id()); + + target.refresh(); + + glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, source->get_id()); + } +} + +} // namespace GL +} // namespace Msp diff --git a/source/core/commands.h b/source/core/commands.h new file mode 100644 index 00000000..ec3281a0 --- /dev/null +++ b/source/core/commands.h @@ -0,0 +1,30 @@ +#ifndef COMMANDS_H_ +#define COMMANDS_H_ + +#include "framebuffer.h" + +namespace Msp { +namespace GL { + +class Batch; +class PipelineState; + +class Commands +{ +private: + const PipelineState *pipeline_state; + +public: + Commands(); + + void use_pipeline(const PipelineState &); + void clear(BufferBits); + void draw(const Batch &); + void draw_instanced(const Batch &, unsigned); + void resolve_multisample(Framebuffer &, BufferBits); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index 167e7de0..0d91f759 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "blend.h" #include "buffer.h" #include "deviceinfo.h" @@ -25,6 +26,7 @@ namespace GL { const PipelineState *PipelineState::last_applied = 0; vector PipelineState::bound_tex_targets; +unsigned PipelineState::restart_index = 0; PipelineState::PipelineState(): framebuffer(0), @@ -198,7 +200,19 @@ void PipelineState::apply(unsigned mask) const { glBindVertexArray(vertex_setup ? vertex_setup->get_id() : 0); if(vertex_setup) + { + static Require _req(MSP_primitive_restart); + vertex_setup->refresh(); + unsigned ri = (vertex_setup->get_index_type()==UNSIGNED_INT ? 0xFFFFFFFF : 0xFFFF); + if(ri!=restart_index) + { + if(!restart_index) + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(ri); + restart_index = ri; + } + } } if(mask&FACE_CULL) diff --git a/source/core/pipelinestate.h b/source/core/pipelinestate.h index 5c3bb9ce..f3c30030 100644 --- a/source/core/pipelinestate.h +++ b/source/core/pipelinestate.h @@ -76,6 +76,7 @@ private: static const PipelineState *last_applied; static std::vector bound_tex_targets; + static unsigned restart_index; public: PipelineState(); @@ -103,6 +104,7 @@ public: void set_stencil_test(const StencilTest *); void set_blend(const Blend *); + const Framebuffer *get_framebuffer() const { return framebuffer; } const Program *get_shader_program() const { return shprog; } const VertexSetup *get_vertex_setup() const { return vertex_setup; } FaceWinding get_front_face() const { return front_face; } diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 575b44a8..b6775202 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include "batch.h" #include "buffer.h" #include "camera.h" @@ -31,6 +28,7 @@ Renderer::Renderer() shdata_stack.reserve(32); state = &state_stack.back(); add_shader_data(standard_shdata); + commands.use_pipeline(pipeline_state); } Renderer::~Renderer() @@ -252,22 +250,21 @@ void Renderer::clear() void Renderer::clear(BufferBits buffers) { pipeline_state.set_framebuffer(state->framebuffer); - pipeline_state.apply(); - glClear(buffers); + commands.clear(buffers); } void Renderer::draw(const Batch &batch) { apply_state(); - - batch.draw(); + batch.refresh(); + commands.draw(batch); } void Renderer::draw_instanced(const Batch &batch, unsigned count) { apply_state(); - - batch.draw_instanced(count); + batch.refresh(); + commands.draw_instanced(batch, count); } void Renderer::resolve_multisample(Framebuffer &target, BufferBits buffers) @@ -280,20 +277,8 @@ void Renderer::resolve_multisample(Framebuffer &target, BufferBits buffers) if(target.get_width()!=width || target.get_height()!=height) throw incompatible_data("Renderer::resolve_multisample"); - if(ARB_direct_state_access) - glBlitNamedFramebuffer(state->framebuffer->get_id(), target.get_id(), 0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST); - else - { - glBindFramebuffer(GL_READ_FRAMEBUFFER, state->framebuffer->get_id()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.get_id()); - - target.refresh(); - - glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - pipeline_state.set_framebuffer(0); - } + apply_state(); + commands.resolve_multisample(target, buffers); } void Renderer::apply_state() @@ -360,8 +345,6 @@ void Renderer::apply_state() pipeline_state.set_depth_test(state->depth_test); pipeline_state.set_stencil_test(state->stencil_test); pipeline_state.set_blend(state->blend); - - pipeline_state.apply(); } diff --git a/source/render/renderer.h b/source/render/renderer.h index 7997b35c..ff2c2a2f 100644 --- a/source/render/renderer.h +++ b/source/render/renderer.h @@ -3,6 +3,7 @@ #include #include +#include "commands.h" #include "framebuffer.h" #include "matrix.h" #include "pipelinestate.h" @@ -119,6 +120,7 @@ private: std::vector shdata_stack; std::set excluded; PipelineState pipeline_state; + Commands commands; public: Renderer(); -- 2.43.0