else
samp = 0;
- if(texture_stack.size()>state.texture_count)
+ set_resource(texture_stack, state.texture_count, tag, { tex, samp, level });
+}
+
+template<typename T>
+void Renderer::set_resource(vector<BoundResource<T>> &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<T> &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<T> &bound_res = stack.back();
+ bound_res.tag = tag;
+ bound_res.resource = res;
+ count = stack.size();
}
void Renderer::flush_shader_data()
shdata_stack.erase(shdata_stack.begin()+state.shdata_count, shdata_stack.end());
}
-void Renderer::flush_textures()
+template<typename T>
+void Renderer::flush_resources(vector<BoundResource<T>> &stack, unsigned &count)
{
- const State &state = get_state();
+ for(unsigned i=0; i<count; ++i)
+ if(stack[i].replaced>=static_cast<int>(count))
+ stack[i].replaced = -1;
- for(unsigned i=0; i<state.texture_count; ++i)
- if(texture_stack[i].replaced>=static_cast<int>(state.texture_count))
- texture_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)
void Renderer::apply_state()
{
- const State &state = get_state();
+ State &state = get_state();
if(!state.shprog)
throw invalid_operation("Renderer::apply_state");
ps.set_face_cull(state.face_cull);
if(state.texture_count<texture_stack.size())
- flush_textures();
+ flush_resources(texture_stack, state.texture_count);
- for(const BoundTexture &t: texture_stack)
- if(t.texture && t.replaced<0)
+ for(const BoundResource<SampledTexture> &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);
+ ps.set_texture(t.binding, t.resource.texture, t.resource.level, t.resource.sampler);
}
static const DepthTest default_depth_test;
};
private:
- struct BoundTexture
+ struct SampledTexture
{
- Tag tag;
- mutable int binding = -1;
const Texture *texture = 0;
const Sampler *sampler = 0;
int level = -1;
+
+ SampledTexture() = default;
+ SampledTexture(const Texture *t, const Sampler *s, int l): texture(t), sampler(s), level(l) { }
+
+ bool operator==(const SampledTexture &o) const { return texture==o.texture && sampler==o.sampler && level==o.level; }
+ };
+
+ template<typename T>
+ struct BoundResource
+ {
+ Tag tag;
+ mutable int binding = -1;
int replaced = -1;
+ T resource;
};
struct BoundProgramData
State *current_state = 0;
ProgramData standard_shdata;
std::vector<BoundProgramData> shdata_stack;
- std::vector<BoundTexture> texture_stack;
+ std::vector<BoundResource<SampledTexture>> texture_stack;
const Texture &placeholder_texture;
const Sampler &default_sampler;
PipelineState *last_pipeline = 0;
void set_texture(Tag, const Texture *, int, const Sampler * = 0);
private:
+ template<typename T>
+ static void set_resource(std::vector<BoundResource<T>> &, unsigned &, Tag, const T &);
+
void flush_shader_data();
- void flush_textures();
+
+ template<typename T>
+ static void flush_resources(std::vector<BoundResource<T>> &, unsigned &);
public:
void set_vertex_setup(const VertexSetup *);