From: Mikko Rasa Date: Fri, 12 Nov 2021 16:55:36 +0000 (+0200) Subject: Reorder members of Renderer and PipelineState X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=3930e89d1dab90a27542c3798782216499b3ab44;p=libs%2Fgl.git Reorder members of Renderer and PipelineState --- diff --git a/source/backends/opengl/pipelinestate_backend.cpp b/source/backends/opengl/pipelinestate_backend.cpp index 58e12e7f..91789701 100644 --- a/source/backends/opengl/pipelinestate_backend.cpp +++ b/source/backends/opengl/pipelinestate_backend.cpp @@ -106,37 +106,28 @@ void OpenGLPipelineState::apply(unsigned mask) const } } - if(mask&PipelineState::VERTEX_SETUP) + if(mask&PipelineState::UNIFORMS) { - const VertexSetup *vertex_setup = self->vertex_setup; - glBindVertexArray(vertex_setup ? vertex_setup->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) + for(const PipelineState::BoundUniformBlock &u: self->uniform_blocks) + if(u.changed || mask==~0U) { - if(!restart_index) - glEnable(GL_PRIMITIVE_RESTART); - glPrimitiveRestartIndex(ri); - restart_index = ri; - } - } - } - - if(mask&PipelineState::FACE_CULL) - { - glFrontFace(self->front_face==CLOCKWISE ? GL_CW : GL_CCW); + if(u.block) + { + if(u.binding>=0) + { + glBindBufferRange(GL_UNIFORM_BUFFER, u.binding, u.block->get_buffer()->id, u.block->get_offset(), u.block->get_data_size()); + bound_uniform_blocks[u.binding] = 1; + } + else if(self->shprog) + { + const char *data = static_cast(u.block->get_data_pointer()); + for(const Program::UniformCall &call: self->shprog->uniform_calls) + call.func(call.location, call.size, data+call.location*16); + } + } - if(self->face_cull!=NO_CULL && self->front_face!=NON_MANIFOLD) - { - glEnable(GL_CULL_FACE); - glCullFace(self->face_cull==CULL_FRONT ? GL_FRONT : GL_BACK); - } - else - glDisable(GL_CULL_FACE); + u.changed = false; + } } if(mask&PipelineState::TEXTURES) @@ -166,28 +157,37 @@ void OpenGLPipelineState::apply(unsigned mask) const } } - if(mask&PipelineState::UNIFORMS) + if(mask&PipelineState::VERTEX_SETUP) { - for(const PipelineState::BoundUniformBlock &u: self->uniform_blocks) - if(u.changed || mask==~0U) - { - if(u.block) - { - if(u.binding>=0) - { - glBindBufferRange(GL_UNIFORM_BUFFER, u.binding, u.block->get_buffer()->id, u.block->get_offset(), u.block->get_data_size()); - bound_uniform_blocks[u.binding] = 1; - } - else if(self->shprog) - { - const char *data = static_cast(u.block->get_data_pointer()); - for(const Program::UniformCall &call: self->shprog->uniform_calls) - call.func(call.location, call.size, data+call.location*16); - } - } + const VertexSetup *vertex_setup = self->vertex_setup; + glBindVertexArray(vertex_setup ? vertex_setup->id : 0); + if(vertex_setup) + { + static Require _req(MSP_primitive_restart); - u.changed = false; + 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&PipelineState::FACE_CULL) + { + glFrontFace(self->front_face==CLOCKWISE ? GL_CW : GL_CCW); + + if(self->face_cull!=NO_CULL && self->front_face!=NON_MANIFOLD) + { + glEnable(GL_CULL_FACE); + glCullFace(self->face_cull==CULL_FRONT ? GL_FRONT : GL_BACK); + } + else + glDisable(GL_CULL_FACE); } if(mask&PipelineState::DEPTH_TEST) diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index 933109e6..0306a262 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -37,19 +37,17 @@ void PipelineState::set_shader_program(const Program *p) set(shprog, p, SHPROG); } -void PipelineState::set_vertex_setup(const VertexSetup *s) -{ - set(vertex_setup, s, VERTEX_SETUP); -} - -void PipelineState::set_front_face(FaceWinding w) -{ - set(front_face, w, FACE_CULL); -} - -void PipelineState::set_face_cull(CullMode c) +void PipelineState::set_uniform_block(int binding, const UniformBlock *block) { - set(face_cull, c, FACE_CULL); + auto i = lower_bound_member(uniform_blocks, binding, &BoundUniformBlock::binding); + if(i==uniform_blocks.end() || i->binding!=binding) + i = uniform_blocks.insert(i, BoundUniformBlock(binding)); + if(block!=i->block || binding<0) + { + i->block = block; + i->changed = true; + changes |= UNIFORMS; + } } void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp) @@ -69,17 +67,19 @@ void PipelineState::set_texture(unsigned binding, const Texture *tex, const Samp } } -void PipelineState::set_uniform_block(int binding, const UniformBlock *block) +void PipelineState::set_vertex_setup(const VertexSetup *s) { - auto i = lower_bound_member(uniform_blocks, binding, &BoundUniformBlock::binding); - if(i==uniform_blocks.end() || i->binding!=binding) - i = uniform_blocks.insert(i, BoundUniformBlock(binding)); - if(block!=i->block || binding<0) - { - i->block = block; - i->changed = true; - changes |= UNIFORMS; - } + set(vertex_setup, s, VERTEX_SETUP); +} + +void PipelineState::set_front_face(FaceWinding w) +{ + set(front_face, w, FACE_CULL); +} + +void PipelineState::set_face_cull(CullMode c) +{ + set(face_cull, c, FACE_CULL); } void PipelineState::set_depth_test(const DepthTest *dt) diff --git a/source/core/pipelinestate.h b/source/core/pipelinestate.h index 47870536..31938829 100644 --- a/source/core/pipelinestate.h +++ b/source/core/pipelinestate.h @@ -51,28 +51,28 @@ private: enum ChangeMask { - SHPROG = 1, - VERTEX_SETUP = 2, - FACE_CULL = 4, - TEXTURES = 16, - UNIFORMS = 32, - DEPTH_TEST = 64, - STENCIL_TEST = 128, - BLEND = 256, - FRAMEBUFFER = 512, - VIEWPORT = 1024, - SCISSOR = 2048 + FRAMEBUFFER = 1, + VIEWPORT = 2, + SCISSOR = 4, + SHPROG = 8, + UNIFORMS = 16, + TEXTURES = 32, + VERTEX_SETUP = 64, + FACE_CULL = 128, + DEPTH_TEST = 256, + STENCIL_TEST = 512, + BLEND = 1024 }; const Framebuffer *framebuffer = 0; const Rect *viewport = 0; const Rect *scissor = 0; const Program *shprog = 0; + std::vector uniform_blocks; + std::vector textures; const VertexSetup *vertex_setup = 0; FaceWinding front_face = COUNTERCLOCKWISE; CullMode face_cull = NO_CULL; - std::vector textures; - std::vector uniform_blocks; const DepthTest *depth_test = 0; const StencilTest *stencil_test = 0; const Blend *blend = 0; @@ -85,11 +85,11 @@ public: void set_viewport(const Rect *); void set_scissor(const Rect *); void set_shader_program(const Program *); + void set_uniform_block(int, const UniformBlock *); + void set_texture(unsigned, const Texture *, const Sampler *); void set_vertex_setup(const VertexSetup *); void set_front_face(FaceWinding); void set_face_cull(CullMode); - void set_texture(unsigned, const Texture *, const Sampler *); - void set_uniform_block(int, const UniformBlock *); void set_depth_test(const DepthTest *); void set_stencil_test(const StencilTest *); void set_blend(const Blend *); diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 044ab55d..3b28d854 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -34,6 +34,34 @@ Renderer::~Renderer() end(); } +void Renderer::end() +{ + if(state_stack.size()>1) + throw invalid_operation("Renderer::end"); + + *state = State(); + shdata_stack.clear(); + add_shader_data(standard_shdata); + + commands.use_pipeline(0); +} + +void Renderer::push_state() +{ + state_stack.push_back(state_stack.back()); + state = &state_stack.back(); +} + +void Renderer::pop_state() +{ + if(state_stack.size()==1) + throw stack_underflow("Renderer::pop_state"); + + state_stack.pop_back(); + state = &state_stack.back(); + changed |= MATRIX; +} + void Renderer::set_camera(const Camera &c) { state->camera = &c; @@ -68,6 +96,31 @@ void Renderer::set_scissor(const Rect *s) state->scissor = s; } +void Renderer::set_shader_program(const Program *p, const ProgramData *d) +{ + state->shprog = p; + if(p && d) + add_shader_data(*d); +} + +void Renderer::add_shader_data(const ProgramData &d) +{ + if(state->shdata_countshdata_count; + return; + } + } + + flush_shader_data(); + shdata_stack.push_back(&d); + state->shdata_count = shdata_stack.size(); + changed |= SHADER_DATA; +} + void Renderer::set_texture(Tag tag, const Texture *tex, const Sampler *samp) { if(tex) @@ -101,6 +154,12 @@ void Renderer::set_texture(Tag tag, const Texture *tex, const Sampler *samp) state->texture_count = texture_stack.size(); } +void Renderer::flush_shader_data() +{ + if(shdata_stack.size()>state->shdata_count) + shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end()); +} + void Renderer::flush_textures() { for(unsigned i=0; itexture_count; ++i) @@ -110,37 +169,6 @@ void Renderer::flush_textures() texture_stack.erase(texture_stack.begin()+state->texture_count, texture_stack.end()); } -void Renderer::set_shader_program(const Program *p, const ProgramData *d) -{ - state->shprog = p; - if(p && d) - add_shader_data(*d); -} - -void Renderer::add_shader_data(const ProgramData &d) -{ - if(state->shdata_countshdata_count; - return; - } - } - - flush_shader_data(); - shdata_stack.push_back(&d); - state->shdata_count = shdata_stack.size(); - changed |= SHADER_DATA; -} - -void Renderer::flush_shader_data() -{ - if(shdata_stack.size()>state->shdata_count) - shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end()); -} - void Renderer::set_vertex_setup(const VertexSetup *vs) { state->vertex_setup = vs; @@ -176,34 +204,6 @@ void Renderer::set_object_lod_bias(unsigned b) state->object_lod_bias = b; } -void Renderer::push_state() -{ - state_stack.push_back(state_stack.back()); - state = &state_stack.back(); -} - -void Renderer::pop_state() -{ - if(state_stack.size()==1) - throw stack_underflow("Renderer::pop_state"); - - state_stack.pop_back(); - state = &state_stack.back(); - changed |= MATRIX; -} - -void Renderer::end() -{ - if(state_stack.size()>1) - throw invalid_operation("Renderer::end"); - - *state = State(); - shdata_stack.clear(); - add_shader_data(standard_shdata); - - commands.use_pipeline(0); -} - void Renderer::clear(const ClearValue *values) { pipeline_state.set_framebuffer(state->framebuffer); @@ -259,6 +259,13 @@ void Renderer::apply_state() if(!state->shprog) throw invalid_operation("Renderer::apply_state"); + pipeline_state.set_framebuffer(state->framebuffer); + pipeline_state.set_viewport(state->viewport); + pipeline_state.set_scissor(state->scissor); + + bool shprog_changed = (state->shprog!=pipeline_state.get_shader_program()); + pipeline_state.set_shader_program(state->shprog); + if(changed&MATRIX) { standard_shdata.uniform("world_obj_matrix", state->model_matrix); @@ -268,12 +275,22 @@ void Renderer::apply_state() changed &= ~MATRIX; } - pipeline_state.set_framebuffer(state->framebuffer); - pipeline_state.set_viewport(state->viewport); - pipeline_state.set_scissor(state->scissor); + bool shdata_changed = changed&SHADER_DATA; + for(auto i=shdata_stack.begin(); (!shdata_changed && i!=shdata_stack.end()); ++i) + shdata_changed = (i->shdata->get_generation()!=i->generation); + bool extra_shdata = (shdata_stack.size()>state->shdata_count); - bool shprog_changed = (state->shprog!=pipeline_state.get_shader_program()); - pipeline_state.set_shader_program(state->shprog); + if(shdata_changed || shprog_changed || extra_shdata) + { + if(extra_shdata) + shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end()); + for(const BoundProgramData &d: shdata_stack) + { + d.shdata->apply(*state->shprog, pipeline_state); + d.generation = d.shdata->get_generation(); + } + changed &= ~SHADER_DATA; + } if(state->vertex_setup) { @@ -299,23 +316,6 @@ void Renderer::apply_state() pipeline_state.set_texture(t.binding, t.texture, t.sampler); } - bool shdata_changed = changed&SHADER_DATA; - for(auto i=shdata_stack.begin(); (!shdata_changed && i!=shdata_stack.end()); ++i) - shdata_changed = (i->shdata->get_generation()!=i->generation); - bool extra_shdata = (shdata_stack.size()>state->shdata_count); - - if(shdata_changed || shprog_changed || extra_shdata) - { - if(extra_shdata) - shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end()); - for(const BoundProgramData &d: shdata_stack) - { - d.shdata->apply(*state->shprog, pipeline_state); - d.generation = d.shdata->get_generation(); - } - changed &= ~SHADER_DATA; - } - pipeline_state.set_depth_test(state->depth_test); pipeline_state.set_stencil_test(state->stencil_test); pipeline_state.set_blend(state->blend); diff --git a/source/render/renderer.h b/source/render/renderer.h index 36fe6c91..0371e837 100644 --- a/source/render/renderer.h +++ b/source/render/renderer.h @@ -101,9 +101,9 @@ private: unsigned char changed = 0; std::vector state_stack; State *state; - std::vector texture_stack; ProgramData standard_shdata; std::vector shdata_stack; + std::vector texture_stack; PipelineState pipeline_state; Commands commands; @@ -111,6 +111,19 @@ public: Renderer(); ~Renderer(); + + /** Unbinds all objects and resets related state. There must be no unpopped + state in the stack. The Renderer remains valid and may be reused for + further rendering. */ + void end(); + + /** Saves the current state so it can be restored later. */ + void push_state(); + + /** Restores a previously saved state. Must be matched with an earlier + push_state call. */ + void pop_state(); + /** Sets the camera to render from. The model matrix is reset to identity. */ void set_camera(const Camera &); @@ -131,11 +144,6 @@ public: const Framebuffer *get_framebuffer() const { return state->framebuffer; } - void set_texture(Tag, const Texture *, const Sampler * = 0); -private: - void flush_textures(); - -public: /** Sets the shader program to use. As a convenience, uniform values may be specified at the same time. */ void set_shader_program(const Program *prog, const ProgramData *data = 0); @@ -145,8 +153,11 @@ public: last will be used. */ void add_shader_data(const ProgramData &data); + void set_texture(Tag, const Texture *, const Sampler * = 0); + private: void flush_shader_data(); + void flush_textures(); public: void set_vertex_setup(const VertexSetup *); @@ -160,18 +171,6 @@ public: void set_object_lod_bias(unsigned); unsigned get_object_lod_bias() const { return state->object_lod_bias; } - /** Saves the current state so it can be restored later. */ - void push_state(); - - /** Restores a previously saved state. Must be matched with an earlier - push_state call. */ - void pop_state(); - - /** Unbinds all objects and resets related state. There must be no unpopped - state in the stack. The Renderer remains valid and may be reused for - further rendering. */ - void end(); - void clear(const ClearValue *); /** Draws a batch of primitives. A shader must be active. */