+ commands.begin_frame(frame_index);
+}
+
+void Renderer::end()
+{
+ if(!current_state || state_stack.size()>1)
+ throw invalid_operation("Renderer::end");
+
+ RendererBackend::end();
+
+ current_state = 0;
+ state_stack.clear();
+ texture_stack.clear();
+ shdata_stack.clear();
+}
+
+void Renderer::push_state()
+{
+ if(state_stack.empty())
+ throw invalid_operation("Renderer::push_state");
+
+ state_stack.push_back(state_stack.back());
+ current_state = &state_stack.back();
+}
+
+void Renderer::pop_state()
+{
+ if(state_stack.size()==1)
+ throw stack_underflow("Renderer::pop_state");
+
+ uintptr_t old_pipeline = current_state->pipeline_key;
+
+ state_stack.pop_back();
+ current_state = &state_stack.back();
+ changed |= MATRIX;
+
+ if(current_state->pipeline_key!=old_pipeline)
+ changed |= PIPELINE_KEY;