#include <stdexcept>
#include <msp/core/algorithm.h>
+#include <msp/io/print.h>
+#include "error.h"
#include "pipelinestate.h"
+#include "program.h"
+#include "uniformblock.h"
using namespace std;
namespace GL {
template<typename T>
-void PipelineState::set(T &target, T value, unsigned flag)
+void PipelineState::set(T &target, const T &value, unsigned flag)
{
if(value!=target)
{
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);
}
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));
-void PipelineState::set_front_face(FaceWinding w)
-{
- set(front_face, w, FACE_CULL);
+ 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_face_cull(CullMode c)
+void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp)
{
- set(face_cull, c, FACE_CULL);
+ set_texture(binding, tex, -1, samp);
}
-void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp)
+void PipelineState::set_texture(unsigned binding, const Texture *tex, int level, const Sampler *samp)
{
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_storage_texture(unsigned binding, const Texture *tex)
+{
+ set_texture_resource(binding, tex, 0, 0);
+}
+
+void PipelineState::set_texture_resource(unsigned binding, const Texture *tex, int level, const Sampler *samp)
+{
+ auto i = lower_bound_member(resources, static_cast<int>(binding), &BoundResource::binding);
+ if(i==resources.end() || i->binding!=static_cast<int>(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_blend(const Blend *b)
+void PipelineState::set_front_face(FaceWinding w)
{
- set(blend, b, BLEND);
+ set(front_face, w, FACE_CULL);
}
+void PipelineState::set_face_cull(CullMode c)
+{
+ set(face_cull, c, FACE_CULL);
+}
-PipelineState::BoundTexture::BoundTexture(unsigned b):
- binding(b),
- changed(false),
- texture(0),
- sampler(0)
-{ }
+void PipelineState::set_depth_test(const DepthTest &dt)
+{
+ set(depth_test, dt, DEPTH_TEST);
+}
+
+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