X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Frender%2Frenderer.cpp;h=5262d09a90ee2862e6c0db07dcd02e71044241fd;hp=2b1503ce23c847b025b75325e2b7e2cb13960a53;hb=HEAD;hpb=b84ce32a8dfcacd54c3497c6e7facb5d65e82827 diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 2b1503ce..7e010b3f 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -25,7 +25,8 @@ const Tag Renderer::world_obj_matrix_tag("world_obj_matrix"); const Tag Renderer::world_obj_normal_matrix_tag("world_obj_normal_matrix"); Renderer::Renderer(): - placeholder_texture(Resources::get_global().get("_placeholder.png")) + placeholder_texture(Resources::get_global().get("_placeholder.png")), + default_sampler(Resources::get_global().get("_linear_clamp.samp")) { state_stack.reserve(16); shdata_stack.reserve(32); @@ -70,7 +71,7 @@ void Renderer::push_state() void Renderer::pop_state() { - if(state_stack.size()==1) + if(state_stack.size()<=1) throw stack_underflow("Renderer::pop_state"); uintptr_t old_pipeline = current_state->pipeline_key; @@ -171,34 +172,48 @@ void Renderer::set_texture(Tag tag, const Texture *tex, int level, const Sampler res_mgr->resource_used(*tex); if(!tex->is_loaded()) tex = &placeholder_texture; + if(!samp) + samp = &default_sampler; } + else + samp = 0; - if(texture_stack.size()>state.texture_count) + set_resource(texture_stack, state.texture_count, tag, { tex, samp, level }); +} + +void Renderer::set_storage_texture(Tag tag, const Texture *tex) +{ + State &state = get_state(); + set_resource(texture_stack, state.texture_count, tag, { tex, 0, 0 }); +} + +template +void Renderer::set_resource(vector> &stack, unsigned &count, Tag tag, const T &res) +{ + if(stack.size()>count) { - BoundTexture &bt = texture_stack[state.texture_count]; - if(bt.tag==tag && bt.texture==tex && bt.sampler==samp) + BoundResource &top = stack[count]; + if(top.tag==tag && top.resource==res) { - ++state.texture_count; + ++count; return; } else - flush_textures(); + flush_resources(stack, count); } - for(auto i=texture_stack.end(); i!=texture_stack.begin(); ) + for(auto i=stack.end(); i!=stack.begin(); ) if((--i)->tag==tag) { - i->replaced = texture_stack.size(); + i->replaced = stack.size(); break; } - texture_stack.emplace_back(); - BoundTexture &bound_tex = texture_stack.back(); - bound_tex.tag = tag; - bound_tex.texture = tex; - bound_tex.sampler = samp; - bound_tex.level = level; - state.texture_count = texture_stack.size(); + stack.emplace_back(); + BoundResource &bound_res = stack.back(); + bound_res.tag = tag; + bound_res.resource = res; + count = stack.size(); } void Renderer::flush_shader_data() @@ -209,15 +224,14 @@ void Renderer::flush_shader_data() shdata_stack.erase(shdata_stack.begin()+state.shdata_count, shdata_stack.end()); } -void Renderer::flush_textures() +template +void Renderer::flush_resources(vector> &stack, unsigned &count) { - const State &state = get_state(); - - for(unsigned i=0; i=static_cast(state.texture_count)) - texture_stack[i].replaced = -1; + for(unsigned i=0; i=static_cast(count)) + stack[i].replaced = -1; - texture_stack.erase(texture_stack.begin()+state.texture_count, texture_stack.end()); + stack.erase(stack.begin()+count, stack.end()); } void Renderer::set_vertex_setup(const VertexSetup *vs) @@ -265,38 +279,45 @@ void Renderer::clear(const ClearValue *values) void Renderer::draw(const Batch &batch) { apply_state(); - batch.refresh(frame_index); - PipelineState &ps = get_pipeline_state(); - ps.set_primitive_type(batch.get_type()); - commands.use_pipeline(&ps); + apply_batch(batch); commands.draw(batch); } void Renderer::draw_instanced(const Batch &batch, unsigned count) { apply_state(); + apply_batch(batch); + commands.draw_instanced(batch, count); +} + +void Renderer::apply_batch(const Batch &batch) +{ batch.refresh(frame_index); PipelineState &ps = get_pipeline_state(); ps.set_primitive_type(batch.get_type()); + if(batch.get_type()==PATCHES) + ps.set_patch_size(batch.get_patch_size()); commands.use_pipeline(&ps); - commands.draw_instanced(batch, count); } -void Renderer::resolve_multisample(Framebuffer &target) +void Renderer::dispatch(unsigned count_x, unsigned count_y, unsigned count_z) +{ + apply_state(); + PipelineState &ps = get_pipeline_state(); + commands.use_pipeline(&ps); + commands.dispatch(count_x, count_y, count_z); +} + +void Renderer::resolve_multisample() { const State &state = get_state(); if(!state.framebuffer) throw invalid_operation("Renderer::resolve_multisample"); - unsigned width = state.framebuffer->get_width(); - unsigned height = state.framebuffer->get_height(); - if(target.get_width()!=width || target.get_height()!=height) - throw incompatible_data("Renderer::resolve_multisample"); - apply_framebuffer(); commands.use_pipeline(&get_pipeline_state()); - commands.resolve_multisample(target); + commands.resolve_multisample(); } void Renderer::begin_query(const QueryPool &pool, unsigned index) @@ -334,7 +355,7 @@ void Renderer::apply_framebuffer() void Renderer::apply_state() { - const State &state = get_state(); + State &state = get_state(); if(!state.shprog) throw invalid_operation("Renderer::apply_state"); @@ -362,7 +383,7 @@ void Renderer::apply_state() if(changed&MATRIX) { standard_shdata.uniform(world_obj_matrix_tag, state.model_matrix); - LinAl::SquareMatrix nm = state.model_matrix.block<3, 3>(0, 0); + LinAl::Matrix nm = state.model_matrix.block<3, 3>(0, 0); nm = transpose(invert(nm)); standard_shdata.uniform(world_obj_normal_matrix_tag, nm); changed &= ~MATRIX; @@ -397,15 +418,20 @@ void Renderer::apply_state() ps.set_face_cull(state.face_cull); if(state.texture_count &t: texture_stack) + if(t.resource.texture && t.replaced<0) { if(t.binding<0 || shprog_changed) t.binding = state.shprog->get_uniform_binding(t.tag); if(t.binding>=0) - ps.set_texture(t.binding, t.texture, t.level, t.sampler); + { + if(t.resource.sampler) + ps.set_texture(t.binding, t.resource.texture, t.resource.level, t.resource.sampler); + else + ps.set_storage_texture(t.binding, t.resource.texture); + } } static const DepthTest default_depth_test;