X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fpipelinestate.cpp;h=8d59a31624eddc823e23cd7260ed444c4efc9129;hp=15de0b4dce3e91f39bc1aea641a0a6d32da7979a;hb=HEAD;hpb=160e9eea29bd10034733d59507fa1bcca36be401 diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index 15de0b4d..6078db5d 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -1,29 +1,18 @@ #include #include +#include +#include "error.h" #include "pipelinestate.h" +#include "program.h" +#include "uniformblock.h" using namespace std; namespace Msp { namespace GL { -PipelineState::PipelineState(): - framebuffer(0), - viewport(0), - scissor(0), - shprog(0), - vertex_setup(0), - front_face(COUNTERCLOCKWISE), - face_cull(NO_CULL), - enabled_clip_planes(0), - depth_test(0), - stencil_test(0), - blend(0), - changes(0) -{ } - template -void PipelineState::set(T &target, T value, unsigned flag) +void PipelineState::set(T &target, const T &value, unsigned flag) { if(value!=target) { @@ -37,12 +26,12 @@ void PipelineState::set_framebuffer(const Framebuffer *f) set(framebuffer, f, FRAMEBUFFER); } -void PipelineState::set_viewport(const Rect *v) +void PipelineState::set_viewport(const Rect &v) { set(viewport, v, VIEWPORT); } -void PipelineState::set_scissor(const Rect *s) +void PipelineState::set_scissor(const Rect &s) { set(scissor, s, SCISSOR); } @@ -52,85 +41,125 @@ void PipelineState::set_shader_program(const Program *p) set(shprog, p, SHPROG); } -void PipelineState::set_vertex_setup(const VertexSetup *s) +void PipelineState::set_uniform_block(int binding, const UniformBlock *block) { - set(vertex_setup, s, VERTEX_SETUP); + auto i = lower_bound_member(resources, binding, &BoundResource::binding); + if(i==resources.end() || i->binding!=binding) + i = resources.insert(i, BoundResource(binding)); + + ResourceType type = (block ? UNIFORM_BLOCK : NO_RESOURCE); + const Buffer *buffer = (block ? block->get_buffer() : 0); + if(i->type!=type || block!=i->block || buffer!=i->buffer || binding<0) + { + i->type = type; + i->block = block; + i->buffer = buffer; + i->changed = true; + i->used = block; + changes |= RESOURCES; + } } -void PipelineState::set_front_face(FaceWinding w) +void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp) { - set(front_face, w, FACE_CULL); + set_texture(binding, tex, -1, samp); } -void PipelineState::set_face_cull(CullMode c) +void PipelineState::set_texture(unsigned binding, const Texture *tex, int level, const Sampler *samp) { - set(face_cull, c, FACE_CULL); + if((tex!=0)!=(samp!=0)) + throw invalid_argument("PipelineState::set_texture"); + if(level>=0 && !can_bind_tex_level(level)) + throw invalid_operation("PipelineState::set_texture"); + + set_texture_resource(binding, tex, level, samp); } -void PipelineState::set_enabled_clip_planes(unsigned p) +void PipelineState::set_storage_texture(unsigned binding, const Texture *tex) { - set(enabled_clip_planes, p, CLIP_PLANES); + set_texture_resource(binding, tex, 0, 0); } -void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp) +void PipelineState::set_texture_resource(unsigned binding, const Texture *tex, int level, const Sampler *samp) { - if((tex!=0)!=(samp!=0)) - throw invalid_argument("PipelineState::set_texture"); + auto i = lower_bound_member(resources, static_cast(binding), &BoundResource::binding); + if(i==resources.end() || i->binding!=static_cast(binding)) + i = resources.insert(i, BoundResource(binding)); - auto i = lower_bound_member(textures, binding, &BoundTexture::binding); - if(i==textures.end() || i->binding!=binding) - i = textures.insert(i, BoundTexture(binding)); - if(tex!=i->texture || samp!=i->sampler) + ResourceType type = (tex ? samp ? SAMPLED_TEXTURE : STORAGE_TEXTURE : NO_RESOURCE); + if(i->type!=type || tex!=i->texture || level!=i->mip_level || samp!=i->sampler) { + i->type = type; i->texture = tex; i->sampler = samp; + i->mip_level = level; i->changed = true; - changes |= TEXTURES; + i->used = tex; + changes |= RESOURCES; } } -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_depth_test(const DepthTest *dt) +void PipelineState::set_primitive_type(PrimitiveType t) { - set(depth_test, dt, DEPTH_TEST); + set(primitive_type, t, PRIMITIVE_TYPE); } -void PipelineState::set_stencil_test(const StencilTest *st) +void PipelineState::set_patch_size(unsigned s) { - set(stencil_test, st, STENCIL_TEST); + set(patch_size, s, PATCH_SIZE); +} + +void PipelineState::set_front_face(FaceWinding w) +{ + set(front_face, w, FACE_CULL); } -void PipelineState::set_blend(const Blend *b) +void PipelineState::set_face_cull(CullMode c) { - set(blend, b, BLEND); + set(face_cull, c, FACE_CULL); } +void PipelineState::set_depth_test(const DepthTest &dt) +{ + set(depth_test, dt, DEPTH_TEST); +} -PipelineState::BoundTexture::BoundTexture(unsigned b): - binding(b), - changed(false), - texture(0), - sampler(0) -{ } +void PipelineState::set_stencil_test(const StencilTest &st) +{ + set(stencil_test, st, STENCIL_TEST); +} +void PipelineState::set_blend(const Blend &b) +{ + set(blend, b, BLEND); +} -PipelineState::BoundUniformBlock::BoundUniformBlock(int b): - binding(b), - changed(false), - block(0) -{ } +void PipelineState::check_bound_resources() const +{ + if(!shprog) + return; + + for(const ReflectData::UniformBlockInfo &b: shprog->get_uniform_blocks()) + if(b.bind_point!=ReflectData::DEFAULT_BLOCK) + { + auto i = lower_bound_member(resources, b.bind_point, &PipelineState::BoundResource::binding); + if(i==resources.end() || i->binding!=b.bind_point) + IO::print(IO::cerr, "Warning: No resource present for uniform block binding %d:%d (%s)\n", b.bind_point>>20, b.bind_point&0xFFFFF, b.name); + } + + for(const ReflectData::UniformInfo &u: shprog->get_uniforms()) + if(u.binding>=0 && is_image(u.type)) + { + auto i = lower_bound_member(resources, u.binding, &PipelineState::BoundResource::binding); + if(i==resources.end() || i->binding!=u.binding) + IO::print(IO::cerr, "Warning: No resource present for texture binding %d:%d (%s)\n", u.binding>>20, u.binding&0xFFFFF, u.name); + } +} } // namespace GL } // namespace Msp