void draw_set_clip_state( struct draw_context *draw,
const struct pipe_clip_state *clip )
{
- draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
memcpy(&draw->plane[6], clip->ucp, sizeof(clip->ucp));
}
void draw_set_viewport_state( struct draw_context *draw,
const struct pipe_viewport_state *viewport )
{
- draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
draw->viewport = *viewport; /* struct copy */
draw->identity_viewport = (viewport->scale[0] == 1.0f &&
viewport->scale[1] == 1.0f &&
shader_type == PIPE_SHADER_GEOMETRY);
debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS);
+ draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
+
switch (shader_type) {
case PIPE_SHADER_VERTEX:
draw->pt.user.vs_constants[slot] = buffer;
unsigned flags )
{
draw->pipeline.first->flush( draw->pipeline.first, flags );
- if (!(flags & DRAW_FLUSH_BACKEND))
+ if (flags & DRAW_FLUSH_STATE_CHANGE)
draw->pipeline.first = draw->pipeline.validate;
}
unsigned opt; /**< bitmask of PT_x flags */
unsigned eltSize; /* saved eltSize for flushing */
+ boolean rebind_parameters;
+
struct {
struct draw_pt_middle_end *fetch_emit;
struct draw_pt_middle_end *fetch_shade_emit;
* Flushing
*/
-#define DRAW_FLUSH_STATE_CHANGE 0x8
-#define DRAW_FLUSH_BACKEND 0x10
+#define DRAW_FLUSH_PARAMETER_CHANGE 0x1 /**< Constants, viewport, etc */
+#define DRAW_FLUSH_STATE_CHANGE 0x2 /**< Other/heavy state changes */
+#define DRAW_FLUSH_BACKEND 0x4 /**< Flush the output buffer */
void draw_do_flush( struct draw_context *draw, unsigned flags );
draw->pt.opt = opt;
}
+ if (draw->pt.rebind_parameters) {
+ /* update constants, viewport dims, clip planes, etc */
+ middle->bind_parameters(middle);
+ draw->pt.rebind_parameters = FALSE;
+ }
+
frontend->run( frontend, start, count );
return TRUE;
void draw_pt_flush( struct draw_context *draw, unsigned flags )
{
+ assert(flags);
+
if (draw->pt.frontend) {
draw->pt.frontend->flush( draw->pt.frontend, flags );
/* don't prepare if we only are flushing the backend */
- if (!(flags & DRAW_FLUSH_BACKEND))
+ if (flags & DRAW_FLUSH_STATE_CHANGE)
draw->pt.frontend = NULL;
}
+
+ if (flags & DRAW_FLUSH_PARAMETER_CHANGE) {
+ draw->pt.rebind_parameters = TRUE;
+ }
}
unsigned opt,
unsigned *max_vertices );
+ /**
+ * Bind/update parameter state such as constants, viewport dims
+ * and clip planes. Basically, stuff which isn't "baked" into the
+ * shader or pipeline state.
+ */
+ void (*bind_parameters)(struct draw_pt_middle_end *);
+
void (*run)( struct draw_pt_middle_end *,
const unsigned *fetch_elts,
unsigned fetch_count,
}
+static void
+fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle)
+{
+ /* No-op since the vertex shader executor and drawing pipeline
+ * just grab the constants, viewport, etc. from the draw context state.
+ */
+}
+
+
static void fetch( struct pt_fetch *fetch,
const struct draw_fetch_info *fetch_info,
char *output)
goto fail;
fpme->base.prepare = fetch_pipeline_prepare;
+ fpme->base.bind_parameters = fetch_pipeline_bind_parameters;
fpme->base.run = fetch_pipeline_run;
fpme->base.run_linear = fetch_pipeline_linear_run;
fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
fpme->current_variant = variant;
}
+}
- /* Bind the VS and GS input constants, clip planes and viewport */
- {
- unsigned i;
- for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) {
- fpme->llvm->jit_context.vs_constants[i] =
- draw->pt.user.vs_constants[i];
- }
- for (i = 0; i < Elements(fpme->llvm->jit_context.gs_constants); ++i) {
- fpme->llvm->jit_context.gs_constants[i] =
- draw->pt.user.gs_constants[i];
- }
- fpme->llvm->jit_context.planes =
- (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
- fpme->llvm->jit_context.viewport =
- (float *) draw->viewport.scale;
- }
+/**
+ * Bind/update constant buffer pointers, clip planes and viewport dims.
+ * These are "light weight" parameters which aren't baked into the
+ * generated code. Updating these items is much cheaper than revalidating
+ * and rebuilding the generated pipeline code.
+ */
+static void
+llvm_middle_end_bind_parameters(struct draw_pt_middle_end *middle)
+{
+ struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ unsigned i;
+
+ for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) {
+ fpme->llvm->jit_context.vs_constants[i] = draw->pt.user.vs_constants[i];
+ }
+
+ for (i = 0; i < Elements(fpme->llvm->jit_context.gs_constants); ++i) {
+ fpme->llvm->jit_context.gs_constants[i] = draw->pt.user.gs_constants[i];
+ }
+
+ fpme->llvm->jit_context.planes =
+ (float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
+
+ fpme->llvm->jit_context.viewport = (float *) draw->viewport.scale;
}
goto fail;
fpme->base.prepare = llvm_middle_end_prepare;
+ fpme->base.bind_parameters = llvm_middle_end_bind_parameters;
fpme->base.run = llvm_middle_end_run;
fpme->base.run_linear = llvm_middle_end_linear_run;
fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
{
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
- if (!(flags & DRAW_FLUSH_BACKEND)) {
+ if (flags & DRAW_FLUSH_STATE_CHANGE) {
vsplit->middle->finish(vsplit->middle);
vsplit->middle = NULL;
}