From 2abc1b3641e435e0b68490fa6b0a7ffa7c030c76 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 1 May 2008 12:38:51 -0400 Subject: abstract fetching elts --- src/gallium/auxiliary/draw/draw_pt_varray.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index 355093f945..b0bd2b983e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -43,6 +43,8 @@ struct varray_frontend { unsigned draw_count; unsigned fetch_count; + unsigned fetch_start; + struct draw_pt_middle_end *middle; unsigned input_prim; @@ -68,15 +70,18 @@ static void varray_flush(struct varray_frontend *varray) varray->draw_count = 0; } -#if 0 -static void varray_check_flush(struct varray_frontend *varray) +static INLINE void fetch_init(struct varray_frontend *varray, + unsigned current_count, + unsigned count) { - if (varray->draw_count + 6 >= DRAW_MAX/* || - varray->fetch_count + 4 >= FETCH_MAX*/) { - varray_flush(varray); + unsigned idx; + const unsigned end = MIN2(FETCH_MAX, count - current_count); + for (idx = 0; idx < end; ++idx) { + varray->fetch_elts[idx] = varray->fetch_start + idx; } + varray->fetch_start += idx; + varray->fetch_count = idx; } -#endif static INLINE void add_draw_el(struct varray_frontend *varray, int idx, ushort flags) -- cgit v1.2.3 From 90a46ed277cc887d49c8d8c627174c3bd693ecf7 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 1 May 2008 23:54:39 -0400 Subject: split larger primitives in the simple varray pt --- src/gallium/auxiliary/draw/draw_pt.c | 3 +- src/gallium/auxiliary/draw/draw_pt_varray.c | 62 ++++++++- src/gallium/auxiliary/draw/draw_pt_varray_tmp.h | 169 +++++++++++++++++------- 3 files changed, 180 insertions(+), 54 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index c9c5d18313..bccde6c5fd 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -80,8 +80,7 @@ draw_pt_arrays(struct draw_context *draw, /* Pick the right frontend */ - if (draw->pt.user.elts || - count >= 256) { + if (draw->pt.user.elts) { frontend = draw->pt.front.vcache; } else { frontend = draw->pt.front.varray; diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index b0bd2b983e..c9843bded0 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -58,6 +58,11 @@ static void varray_flush(struct varray_frontend *varray) debug_printf("FLUSH fc = %d, dc = %d\n", varray->fetch_count, varray->draw_count); + debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n", + varray->fetch_elts[0], + varray->fetch_elts[varray->fetch_count-1], + varray->draw_elts[0], + varray->draw_elts[varray->draw_count-1]); #endif varray->middle->run(varray->middle, varray->fetch_elts, @@ -71,18 +76,69 @@ static void varray_flush(struct varray_frontend *varray) } static INLINE void fetch_init(struct varray_frontend *varray, - unsigned current_count, unsigned count) { unsigned idx; - const unsigned end = MIN2(FETCH_MAX, count - current_count); - for (idx = 0; idx < end; ++idx) { +#if 0 + debug_printf("FETCH INIT c = %d, fs = %d\n", + count, + varray->fetch_start); +#endif + for (idx = 0; idx < count; ++idx) { varray->fetch_elts[idx] = varray->fetch_start + idx; } varray->fetch_start += idx; varray->fetch_count = idx; } + +static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + *first = 1; + *incr = 1; + return TRUE; + case PIPE_PRIM_LINES: + *first = 2; + *incr = 2; + return TRUE; + case PIPE_PRIM_LINE_STRIP: + *first = 2; + *incr = 1; + return TRUE; + case PIPE_PRIM_TRIANGLES: + *first = 3; + *incr = 3; + return TRUE; + case PIPE_PRIM_TRIANGLE_STRIP: + *first = 3; + *incr = 1; + return TRUE; + case PIPE_PRIM_TRIANGLE_FAN: + *first = 3; + *incr = 1; + return TRUE; + case PIPE_PRIM_QUADS: + *first = 4; + *incr = 4; + return TRUE; + case PIPE_PRIM_QUAD_STRIP: + *first = 4; + *incr = 2; + return TRUE; + case PIPE_PRIM_POLYGON: + *first = 3; + *incr = 1; + return TRUE; + default: + *first = 0; + *incr = 1; /* set to one so that count % incr works */ + return FALSE; + } +} + + static INLINE void add_draw_el(struct varray_frontend *varray, int idx, ushort flags) { diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index a3509613f5..073c1aadbf 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -10,30 +10,42 @@ static void FUNC(struct draw_pt_front_end *frontend, boolean flatfirst = (draw->rasterizer->flatshade && draw->rasterizer->flatshade_first); - unsigned i, flags; + unsigned i, j, flags; + unsigned first, incr; -#if 0 - debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count); -#endif -#if 0 - debug_printf("INPUT PRIM = %d (start = %d, count = %d)\n", varray->input_prim, + varray->fetch_start = start; + + split_prim_inplace(varray->input_prim, &first, &incr); + +#if 1 + debug_printf("%s (%d) %d/%d\n", __FUNCTION__, + varray->input_prim, start, count); #endif - varray->fetch_start = start; - fetch_init(varray, 0, count); - switch (varray->input_prim) { case PIPE_PRIM_POINTS: - for (i = 0; i < count; i ++) { - POINT(varray, i + 0); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i < count; i ++) { + POINT(varray, i + 0); + } + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_LINES: - for (i = 0; i+1 < count; i += 2) { - LINE(varray, DRAW_PIPE_RESET_STIPPLE, - i + 0, i + 1); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+1 < end; i += 2) { + LINE(varray, DRAW_PIPE_RESET_STIPPLE, + i + 0, i + 1); + } + fetch_init(varray, end); + varray_flush(varray); } break; @@ -41,38 +53,68 @@ static void FUNC(struct draw_pt_front_end *frontend, if (count >= 2) { flags = DRAW_PIPE_RESET_STIPPLE; - for (i = 1; i < count; i++, flags = 0) { - LINE(varray, flags, i - 1, i); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + LINE(varray, flags, i - 1, 0); + fetch_init(varray, end); + varray_flush(varray); } - LINE(varray, flags, i - 1, 0); } break; case PIPE_PRIM_LINE_STRIP: flags = DRAW_PIPE_RESET_STIPPLE; - for (i = 1; i < count; i++, flags = 0) { - LINE(varray, flags, i - 1, i); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0, i + 1, i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i += 3) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0, i + 1, i + 2); + } + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_TRIANGLE_STRIP: if (flatfirst) { - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0, i + 1 + (i&1), i + 2 - (i&1)); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0, i + 1 + (i&1), i + 2 - (i&1)); + } + fetch_init(varray, end); + varray_flush(varray); } } else { - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0 + (i&1), i + 1 - (i&1), i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0 + (i&1), i + 1 - (i&1), i + 2); + } + fetch_init(varray, end); + varray_flush(varray); } } break; @@ -81,51 +123,80 @@ static void FUNC(struct draw_pt_front_end *frontend, if (count >= 3) { if (flatfirst) { flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, flags, i + 1, i + 2, 0); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + fetch_init(varray, end); + varray_flush(varray); } } else { flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, flags, 0, i + 1, i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, 0, i + 1, i + 2); + } + fetch_init(varray, end); + varray_flush(varray); } } } break; case PIPE_PRIM_QUADS: - for (i = 0; i+3 < count; i += 4) { - QUAD(varray, i + 0, i + 1, i + 2, i + 3); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 4) { + QUAD(varray, i + 0, i + 1, i + 2, i + 3); + } + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 0; i+3 < count; i += 2) { - QUAD(varray, i + 2, i + 0, i + 1, i + 3); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 2) { + QUAD(varray, i + 2, i + 0, i + 1, i + 3); + } + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_POLYGON: { - /* These bitflags look a little odd because we submit the - * vertices as (1,2,0) to satisfy flatshade requirements. - */ - const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; - const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; - const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; - - flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; - - for (i = 0; i+2 < count; i++, flags = edge_middle) { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; + const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; + + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++, flags = edge_middle) { if (i + 3 == count) flags |= edge_last; - TRIANGLE(varray, flags, i + 1, i + 2, 0); - } + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + fetch_init(varray, end); + varray_flush(varray); } - break; + } + break; default: assert(0); -- cgit v1.2.3 From abb08e9335b5d7cb004dc9e6cec390ab6968abe5 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Sat, 3 May 2008 22:32:17 -0400 Subject: implement linear emition and fetching and plug it in the varray paths --- src/gallium/auxiliary/draw/draw_pt.h | 18 +++++ src/gallium/auxiliary/draw/draw_pt_emit.c | 45 +++++++++++ src/gallium/auxiliary/draw/draw_pt_fetch.c | 36 +++++++++ .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c | 88 ++++++++++++++++++++-- src/gallium/auxiliary/draw/draw_pt_varray.c | 26 ++++++- src/gallium/auxiliary/draw/draw_pt_varray_tmp.h | 4 +- 6 files changed, 208 insertions(+), 9 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 2dec376cee..2f96ceaf00 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -92,6 +92,12 @@ struct draw_pt_middle_end { const ushort *draw_elts, unsigned draw_count ); + void (*run_linear)(struct draw_pt_middle_end *, + unsigned fetch_start, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count); + void (*finish)( struct draw_pt_middle_end * ); void (*destroy)( struct draw_pt_middle_end * ); }; @@ -152,6 +158,13 @@ void draw_pt_emit( struct pt_emit *emit, const ushort *elts, unsigned count ); +void draw_pt_emit_linear( struct pt_emit *emit, + const float (*vertex_data)[4], + unsigned vertex_count, + unsigned stride, + unsigned start, + unsigned count ); + void draw_pt_emit_destroy( struct pt_emit *emit ); struct pt_emit *draw_pt_emit_create( struct draw_context *draw ); @@ -170,6 +183,11 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, unsigned count, char *verts ); +void draw_pt_fetch_run_linear( struct pt_fetch *fetch, + unsigned start, + unsigned count, + char *verts ); + void draw_pt_fetch_destroy( struct pt_fetch *fetch ); struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw ); diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c index f9ac16786e..2a961b7088 100644 --- a/src/gallium/auxiliary/draw/draw_pt_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_emit.c @@ -179,6 +179,51 @@ void draw_pt_emit( struct pt_emit *emit, } +void draw_pt_emit_linear(struct pt_emit *emit, + const float (*vertex_data)[4], + unsigned vertex_count, + unsigned stride, + unsigned start, + unsigned count) +{ + struct draw_context *draw = emit->draw; + struct translate *translate = emit->translate; + struct vbuf_render *render = draw->render; + void *hw_verts; + + debug_printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = render->allocate_vertices(render, + (ushort)translate->key.output_stride, + (ushort)count); + if (!hw_verts) { + assert(0); + return; + } + + translate->set_buffer(translate, 0, + vertex_data, stride); + + translate->set_buffer(translate, 1, + &draw->rasterizer->point_size, + 0); + + translate->run(translate, + 0, + vertex_count, + hw_verts); + + render->draw_arrays(render, start, count); + + render->release_vertices(render, + hw_verts, + translate->key.output_stride, + vertex_count); +} + struct pt_emit *draw_pt_emit_create( struct draw_context *draw ) { struct pt_emit *emit = CALLOC_STRUCT(pt_emit); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c index 1f765b73ad..d7cc1807d7 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c @@ -167,6 +167,42 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, } +void draw_pt_fetch_run_linear( struct pt_fetch *fetch, + unsigned start, + unsigned count, + char *verts ) +{ + struct draw_context *draw = fetch->draw; + struct translate *translate = fetch->translate; + unsigned i; + + for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { + translate->set_buffer(translate, + i, + ((char *)draw->pt.user.vbuffer[i] + + draw->pt.vertex_buffer[i].buffer_offset), + draw->pt.vertex_buffer[i].pitch ); + } + + translate->run( translate, + start, + count, + verts ); + + /* Edgeflags are hard to fit into a translate program, populate + * them separately if required. In the setup above they are + * defaulted to one, so only need this if there is reason to change + * that default: + */ + if (fetch->need_edgeflags) { + for (i = 0; i < count; i++) { + struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size); + vh->edgeflag = draw_pt_get_edgeflag( draw, start + i ); + } + } +} + + struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw ) { struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 4ec20493c4..b1e08a8f40 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -162,7 +162,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, fpme->vertex_size, draw_elts, draw_count ); - } + } else { draw_pt_emit( fpme->emit, (const float (*)[4])pipeline_verts->data, @@ -177,6 +177,83 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, } +static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, + unsigned fetch_start, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; + struct draw_context *draw = fpme->draw; + struct draw_vertex_shader *shader = draw->vertex_shader; + unsigned opt = fpme->opt; + unsigned alloc_count = align_int( fetch_count, 4 ); + + struct vertex_header *pipeline_verts = + (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count); + + if (!pipeline_verts) { + /* Not much we can do here - just skip the rendering. + */ + assert(0); + return; + } + + /* Fetch into our vertex buffer + */ + draw_pt_fetch_run_linear( fpme->fetch, + fetch_start, + fetch_count, + (char *)pipeline_verts ); + + /* Run the shader, note that this overwrites the data[] parts of + * the pipeline verts. If there is no shader, ie a bypass shader, + * then the inputs == outputs, and are already in the correct + * place. + */ + if (opt & PT_SHADE) + { + shader->run_linear(shader, + (const float (*)[4])pipeline_verts->data, + ( float (*)[4])pipeline_verts->data, + (const float (*)[4])draw->pt.user.constants, + fetch_count, + fpme->vertex_size, + fpme->vertex_size); + } + + if (draw_pt_post_vs_run( fpme->post_vs, + pipeline_verts, + fetch_count, + fpme->vertex_size )) + { + opt |= PT_PIPELINE; + } + + /* Do we need to run the pipeline? + */ + if (opt & PT_PIPELINE) { + draw_pipeline_run( fpme->draw, + fpme->prim, + pipeline_verts, + fetch_count, + fpme->vertex_size, + draw_elts, + draw_count ); + } + else { + draw_pt_emit_linear( fpme->emit, + (const float (*)[4])pipeline_verts->data, + fetch_count, + fpme->vertex_size, + 0, /*start*/ + draw_count ); + } + + FREE(pipeline_verts); +} + + static void fetch_pipeline_finish( struct draw_pt_middle_end *middle ) { @@ -206,10 +283,11 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context * if (!fpme) goto fail; - fpme->base.prepare = fetch_pipeline_prepare; - fpme->base.run = fetch_pipeline_run; - fpme->base.finish = fetch_pipeline_finish; - fpme->base.destroy = fetch_pipeline_destroy; + fpme->base.prepare = fetch_pipeline_prepare; + fpme->base.run = fetch_pipeline_run; + fpme->base.run_linear = fetch_pipeline_linear_run; + fpme->base.finish = fetch_pipeline_finish; + fpme->base.destroy = fetch_pipeline_destroy; fpme->draw = draw; diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index c9843bded0..916373acc8 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -75,6 +75,28 @@ static void varray_flush(struct varray_frontend *varray) varray->draw_count = 0; } +static void varray_flush_linear(struct varray_frontend *varray) +{ + if (varray->draw_count) { + debug_printf("FLUSH LINEAR fc = %d, dc = %d\n", + varray->fetch_count, + varray->draw_count); + debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n", + varray->fetch_elts[0], + varray->fetch_elts[varray->fetch_count-1], + varray->draw_elts[0], + varray->draw_elts[varray->draw_count-1]); + varray->middle->run_linear(varray->middle, + varray->fetch_elts[0], + varray->fetch_count, + varray->draw_elts, + varray->draw_count); + } + + varray->fetch_count = 0; + varray->draw_count = 0; +} + static INLINE void fetch_init(struct varray_frontend *varray, unsigned count) { @@ -265,8 +287,8 @@ static void varray_prepare(struct draw_pt_front_end *frontend, if (opt & PT_PIPELINE) { varray->base.run = varray_run_extras; - } - else + } + else { varray->base.run = varray_run; } diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index 073c1aadbf..67baafa3be 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -17,7 +17,7 @@ static void FUNC(struct draw_pt_front_end *frontend, split_prim_inplace(varray->input_prim, &first, &incr); -#if 1 +#if 0 debug_printf("%s (%d) %d/%d\n", __FUNCTION__, varray->input_prim, start, count); @@ -88,7 +88,7 @@ static void FUNC(struct draw_pt_front_end *frontend, i + 0, i + 1, i + 2); } fetch_init(varray, end); - varray_flush(varray); + varray_flush_linear(varray); } break; -- cgit v1.2.3 From ff1fee2cae9fabb47d6a2eb1f9f8094fec3c377f Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Sun, 4 May 2008 00:44:27 -0400 Subject: don't fill in linear fetch_elts --- src/gallium/auxiliary/draw/draw_pt_varray.c | 4 +++- src/gallium/auxiliary/draw/draw_pt_varray_tmp.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index 916373acc8..fb1b59d53e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -78,6 +78,7 @@ static void varray_flush(struct varray_frontend *varray) static void varray_flush_linear(struct varray_frontend *varray) { if (varray->draw_count) { +#if 0 debug_printf("FLUSH LINEAR fc = %d, dc = %d\n", varray->fetch_count, varray->draw_count); @@ -86,8 +87,9 @@ static void varray_flush_linear(struct varray_frontend *varray) varray->fetch_elts[varray->fetch_count-1], varray->draw_elts[0], varray->draw_elts[varray->draw_count-1]); +#endif varray->middle->run_linear(varray->middle, - varray->fetch_elts[0], + varray->fetch_start, varray->fetch_count, varray->draw_elts, varray->draw_count); diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index 67baafa3be..a9f844a357 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -87,8 +87,9 @@ static void FUNC(struct draw_pt_front_end *frontend, TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, i + 0, i + 1, i + 2); } - fetch_init(varray, end); + varray->fetch_count = end; varray_flush_linear(varray); + varray->fetch_start += end; } break; -- cgit v1.2.3 From a24cb269e1ba5434acf8c94abd03517c149b9c51 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Sun, 4 May 2008 01:23:01 -0400 Subject: implement linear path for fetch_emit pipeline --- src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 64 +++++++++++++++++++++++-- src/gallium/auxiliary/draw/draw_pt_varray.c | 1 + 2 files changed, 61 insertions(+), 4 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index a4de341df8..6d5a54cf0e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -257,6 +257,61 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, } +static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, + unsigned fetch_start, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)fetch_count ); + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices and emit HW verts. + */ + feme->translate->run( feme->translate, + fetch_start, + fetch_count, + hw_verts ); + + if (0) { + unsigned i; + for (i = 0; i < fetch_count; i++) { + debug_printf("\n\nvertex %d:\n", i); + draw_dump_emitted_vertex( feme->vinfo, + (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); + } + } + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, /*start*/ + draw_count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->translate->key.output_stride, + fetch_count ); + +} + + static void fetch_emit_finish( struct draw_pt_middle_end *middle ) { @@ -285,10 +340,11 @@ struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ) return NULL; } - fetch_emit->base.prepare = fetch_emit_prepare; - fetch_emit->base.run = fetch_emit_run; - fetch_emit->base.finish = fetch_emit_finish; - fetch_emit->base.destroy = fetch_emit_destroy; + fetch_emit->base.prepare = fetch_emit_prepare; + fetch_emit->base.run = fetch_emit_run; + fetch_emit->base.run_linear = fetch_emit_run_linear; + fetch_emit->base.finish = fetch_emit_finish; + fetch_emit->base.destroy = fetch_emit_destroy; fetch_emit->draw = draw; diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index fb1b59d53e..e7e21e4bf6 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -88,6 +88,7 @@ static void varray_flush_linear(struct varray_frontend *varray) varray->draw_elts[0], varray->draw_elts[varray->draw_count-1]); #endif + assert(varray->middle->run_linear); varray->middle->run_linear(varray->middle, varray->fetch_start, varray->fetch_count, -- cgit v1.2.3 From fe586f8612dd517b9a1f0d87fbaf3a75e3caf588 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Tue, 6 May 2008 18:59:45 -0400 Subject: redo the linear paths --- src/gallium/auxiliary/draw/draw_pipe.c | 39 ++++ src/gallium/auxiliary/draw/draw_private.h | 6 + src/gallium/auxiliary/draw/draw_pt.h | 6 +- src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 18 +- .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c | 36 ++-- src/gallium/auxiliary/draw/draw_pt_varray.c | 27 +-- src/gallium/auxiliary/draw/draw_pt_varray_tmp.h | 5 +- .../auxiliary/draw/draw_pt_varray_tmp_linear.h | 198 +++++++++++++++++++++ 8 files changed, 279 insertions(+), 56 deletions(-) create mode 100644 src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 46afb0f41f..cb97f955b2 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -212,6 +212,45 @@ void draw_pipeline_run( struct draw_context *draw, draw->pipeline.vertex_count = 0; } +void draw_pipeline_run_linear( struct draw_context *draw, + unsigned prim, + struct vertex_header *vertices, + unsigned count, + unsigned stride ) +{ + char *verts = (char *)vertices; + unsigned i; + + draw->pipeline.verts = verts; + draw->pipeline.vertex_stride = stride; + draw->pipeline.vertex_count = count; + + switch (prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < count; i++) + do_point( draw, + verts + stride * i ); + break; + case PIPE_PRIM_LINES: + for (i = 0; i+1 < count; i += 2) + do_line( draw, + i+0, /* flags */ + verts + stride * ((i+0) & ~DRAW_PIPE_FLAG_MASK), + verts + stride * (i+1)); + break; + case PIPE_PRIM_TRIANGLES: + for (i = 0; i+2 < count; i += 3) + do_triangle( draw, + (i+0), /* flags */ + verts + stride * ((i+0) & ~DRAW_PIPE_FLAG_MASK), + verts + stride * (i+1), + verts + stride * (i+2)); + break; + } + + draw->pipeline.verts = NULL; + draw->pipeline.vertex_count = 0; +} void draw_pipeline_flush( struct draw_context *draw, diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index cee58bbf73..e036d498b8 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -247,6 +247,12 @@ void draw_pipeline_run( struct draw_context *draw, const ushort *elts, unsigned count ); +void draw_pipeline_run_linear( struct draw_context *draw, + unsigned prim, + struct vertex_header *vertices, + unsigned count, + unsigned stride ); + void draw_pipeline_flush( struct draw_context *draw, diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 2f96ceaf00..312fdbe4f4 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -93,10 +93,8 @@ struct draw_pt_middle_end { unsigned draw_count ); void (*run_linear)(struct draw_pt_middle_end *, - unsigned fetch_start, - unsigned fetch_count, - const ushort *draw_elts, - unsigned draw_count); + unsigned start, + unsigned count); void (*finish)( struct draw_pt_middle_end * ); void (*destroy)( struct draw_pt_middle_end * ); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 6d5a54cf0e..8df4241b82 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -258,10 +258,8 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, - unsigned fetch_start, - unsigned fetch_count, - const ushort *draw_elts, - unsigned draw_count ) + unsigned start, + unsigned count ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; @@ -273,7 +271,7 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, hw_verts = draw->render->allocate_vertices( draw->render, (ushort)feme->translate->key.output_stride, - (ushort)fetch_count ); + (ushort)count ); if (!hw_verts) { assert(0); return; @@ -282,13 +280,13 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, /* Single routine to fetch vertices and emit HW verts. */ feme->translate->run( feme->translate, - fetch_start, - fetch_count, + start, + count, hw_verts ); if (0) { unsigned i; - for (i = 0; i < fetch_count; i++) { + for (i = 0; i < count; i++) { debug_printf("\n\nvertex %d:\n", i); draw_dump_emitted_vertex( feme->vinfo, (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); @@ -300,14 +298,14 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, */ draw->render->draw_arrays( draw->render, 0, /*start*/ - draw_count ); + count ); /* Done -- that was easy, wasn't it: */ draw->render->release_vertices( draw->render, hw_verts, feme->translate->key.output_stride, - fetch_count ); + count ); } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index b1e08a8f40..dad54690a5 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -178,18 +178,16 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, - unsigned fetch_start, - unsigned fetch_count, - const ushort *draw_elts, - unsigned draw_count ) + unsigned start, + unsigned count) { struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; struct draw_context *draw = fpme->draw; struct draw_vertex_shader *shader = draw->vertex_shader; unsigned opt = fpme->opt; - unsigned alloc_count = align_int( fetch_count, 4 ); + unsigned alloc_count = align_int( count, 4 ); - struct vertex_header *pipeline_verts = + struct vertex_header *pipeline_verts = (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count); if (!pipeline_verts) { @@ -202,8 +200,8 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, /* Fetch into our vertex buffer */ draw_pt_fetch_run_linear( fpme->fetch, - fetch_start, - fetch_count, + start, + count, (char *)pipeline_verts ); /* Run the shader, note that this overwrites the data[] parts of @@ -213,18 +211,18 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, */ if (opt & PT_SHADE) { - shader->run_linear(shader, + shader->run_linear(shader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, (const float (*)[4])draw->pt.user.constants, - fetch_count, + count, fpme->vertex_size, fpme->vertex_size); } if (draw_pt_post_vs_run( fpme->post_vs, pipeline_verts, - fetch_count, + count, fpme->vertex_size )) { opt |= PT_PIPELINE; @@ -233,21 +231,19 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, /* Do we need to run the pipeline? */ if (opt & PT_PIPELINE) { - draw_pipeline_run( fpme->draw, - fpme->prim, - pipeline_verts, - fetch_count, - fpme->vertex_size, - draw_elts, - draw_count ); + draw_pipeline_run_linear( fpme->draw, + fpme->prim, + pipeline_verts, + count, + fpme->vertex_size); } else { draw_pt_emit_linear( fpme->emit, (const float (*)[4])pipeline_verts->data, - fetch_count, + count, fpme->vertex_size, 0, /*start*/ - draw_count ); + count ); } FREE(pipeline_verts); diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index e7e21e4bf6..59a9569270 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -75,29 +75,18 @@ static void varray_flush(struct varray_frontend *varray) varray->draw_count = 0; } -static void varray_flush_linear(struct varray_frontend *varray) +static void varray_flush_linear(struct varray_frontend *varray, + unsigned start, unsigned count) { - if (varray->draw_count) { + if (count) { #if 0 - debug_printf("FLUSH LINEAR fc = %d, dc = %d\n", - varray->fetch_count, - varray->draw_count); - debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n", - varray->fetch_elts[0], - varray->fetch_elts[varray->fetch_count-1], - varray->draw_elts[0], - varray->draw_elts[varray->draw_count-1]); + debug_printf("FLUSH LINEAR start = %d, count = %d\n", + start, + count); #endif assert(varray->middle->run_linear); - varray->middle->run_linear(varray->middle, - varray->fetch_start, - varray->fetch_count, - varray->draw_elts, - varray->draw_count); + varray->middle->run_linear(varray->middle, start, count); } - - varray->fetch_count = 0; - varray->draw_count = 0; } static INLINE void fetch_init(struct varray_frontend *varray, @@ -261,7 +250,7 @@ static INLINE void varray_ef_quad( struct varray_frontend *varray, #define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1) #define POINT(vc,i0) varray_point(vc,i0) #define FUNC varray_run -#include "draw_pt_varray_tmp.h" +#include "draw_pt_varray_tmp_linear.h" diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index 10ac08ea30..335c4c89ca 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -92,9 +92,8 @@ static void FUNC(struct draw_pt_front_end *frontend, i + 0, i + 1, i + 2); } i = end; - varray->fetch_count = end; - varray_flush_linear(varray); - varray->fetch_start += end; + fetch_init(varray, end); + varray_flush(varray); } break; diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h new file mode 100644 index 0000000000..dfa4338407 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h @@ -0,0 +1,198 @@ + +static void FUNC(struct draw_pt_front_end *frontend, + pt_elt_func get_elt, + const void *elts, + unsigned count) +{ + struct varray_frontend *varray = (struct varray_frontend *)frontend; + struct draw_context *draw = varray->draw; + unsigned start = (unsigned)elts; + + boolean flatfirst = (draw->rasterizer->flatshade && + draw->rasterizer->flatshade_first); + unsigned i, j, flags; + unsigned first, incr; + + varray->fetch_start = start; + + split_prim_inplace(varray->input_prim, &first, &incr); + +#if 0 + debug_printf("%s (%d) %d/%d\n", __FUNCTION__, + varray->input_prim, + start, count); +#endif + + switch (varray->input_prim) { + case PIPE_PRIM_POINTS: + case PIPE_PRIM_LINES: + case PIPE_PRIM_TRIANGLES: + j = 0; + while (j + first <= count) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + varray_flush_linear(varray, start + j, end); + j += end; + } + break; + + case PIPE_PRIM_LINE_LOOP: + if (count >= 2) { + flags = DRAW_PIPE_RESET_STIPPLE; + + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + LINE(varray, flags, i - 1, 0); + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + } + break; + + case PIPE_PRIM_LINE_STRIP: + flags = DRAW_PIPE_RESET_STIPPLE; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + break; + + case PIPE_PRIM_TRIANGLE_STRIP: + if (flatfirst) { + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0, i + 1 + (i&1), i + 2 - (i&1)); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + } + else { + for (j = 0; j + first <= count;) { + unsigned end = MIN2(FETCH_MAX, count - j); + //end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0 + (i&1), i + 1 - (i&1), i + 2); + } + fetch_init(varray, end); + varray_flush(varray); + j += end; + if (j <= count) + j -= incr; + } + } + break; + + case PIPE_PRIM_TRIANGLE_FAN: + if (count >= 3) { + if (flatfirst) { + flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + } + else { + flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, 0, i + 1, i + 2); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + } + } + break; + + case PIPE_PRIM_QUADS: + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 4) { + QUAD(varray, i + 0, i + 1, i + 2, i + 3); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + break; + + case PIPE_PRIM_QUAD_STRIP: + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 2) { + QUAD(varray, i + 2, i + 0, i + 1, i + 3); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + break; + + case PIPE_PRIM_POLYGON: + { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; + const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; + + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++, flags = edge_middle) { + + if (i + 3 == count) + flags |= edge_last; + + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + } + } + break; + + default: + assert(0); + break; + } + + varray_flush(varray); +} + +#undef TRIANGLE +#undef QUAD +#undef POINT +#undef LINE +#undef FUNC -- cgit v1.2.3 From 44463b2997826cd14def00abf724a7a65a4fc7cb Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 12 May 2008 17:36:35 +0100 Subject: draw: streamline the varray path - drop support for running the pipeline (ie. don't populate the flags values) - pass through all split-able primitives intact to the middle end - only primitives that can't be split are shunted on the draw-element path --- src/gallium/auxiliary/draw/draw_pt.c | 2 +- src/gallium/auxiliary/draw/draw_pt_varray.c | 106 +++---------- .../auxiliary/draw/draw_pt_varray_tmp_linear.h | 165 +++------------------ 3 files changed, 44 insertions(+), 229 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 448deef98c..d9e73a2396 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -81,7 +81,7 @@ draw_pt_arrays(struct draw_context *draw, /* Pick the right frontend */ - if (draw->pt.user.elts) { + if (draw->pt.user.elts || (opt & PT_PIPELINE)) { frontend = draw->pt.front.vcache; } else if (opt == PT_SHADE && draw->pt.test_fse) { /* should be a middle end.. */ diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index 59a9569270..d92ad4fda1 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -154,9 +154,9 @@ static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr static INLINE void add_draw_el(struct varray_frontend *varray, - int idx, ushort flags) + int idx) { - varray->draw_elts[varray->draw_count++] = idx | flags; + varray->draw_elts[varray->draw_count++] = idx; } @@ -165,106 +165,47 @@ static INLINE void varray_triangle( struct varray_frontend *varray, unsigned i1, unsigned i2 ) { - add_draw_el(varray, i0, 0); - add_draw_el(varray, i1, 0); - add_draw_el(varray, i2, 0); -} - -static INLINE void varray_triangle_flags( struct varray_frontend *varray, - ushort flags, - unsigned i0, - unsigned i1, - unsigned i2 ) -{ - add_draw_el(varray, i0, flags); - add_draw_el(varray, i1, 0); - add_draw_el(varray, i2, 0); + add_draw_el(varray, i0); + add_draw_el(varray, i1); + add_draw_el(varray, i2); } static INLINE void varray_line( struct varray_frontend *varray, unsigned i0, unsigned i1 ) { - add_draw_el(varray, i0, 0); - add_draw_el(varray, i1, 0); -} - - -static INLINE void varray_line_flags( struct varray_frontend *varray, - ushort flags, - unsigned i0, - unsigned i1 ) -{ - add_draw_el(varray, i0, flags); - add_draw_el(varray, i1, 0); + add_draw_el(varray, i0); + add_draw_el(varray, i1); } static INLINE void varray_point( struct varray_frontend *varray, unsigned i0 ) { - add_draw_el(varray, i0, 0); -} - -static INLINE void varray_quad( struct varray_frontend *varray, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) -{ - varray_triangle( varray, i0, i1, i3 ); - varray_triangle( varray, i1, i2, i3 ); + add_draw_el(varray, i0); } -static INLINE void varray_ef_quad( struct varray_frontend *varray, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) -{ - const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2; - const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1; - - varray_triangle_flags( varray, - DRAW_PIPE_RESET_STIPPLE | omitEdge1, - i0, i1, i3 ); - - varray_triangle_flags( varray, - omitEdge2, - i1, i2, i3 ); -} -/* At least for now, we're back to using a template include file for - * this. The two paths aren't too different though - it may be - * possible to reunify them. - */ -#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle_flags(vc,flags,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) varray_ef_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) varray_line_flags(vc,flags,i0,i1) -#define POINT(vc,i0) varray_point(vc,i0) -#define FUNC varray_run_extras -#include "draw_pt_varray_tmp.h" -#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle(vc,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) varray_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1) +#define TRIANGLE(vc,i0,i1,i2) varray_triangle(vc,i0,i1,i2) +#define LINE(vc,i0,i1) varray_line(vc,i0,i1) #define POINT(vc,i0) varray_point(vc,i0) #define FUNC varray_run #include "draw_pt_varray_tmp_linear.h" -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { +static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = { PIPE_PRIM_POINTS, PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, + PIPE_PRIM_LINE_STRIP, + PIPE_PRIM_LINES, /* decomposed */ PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES + PIPE_PRIM_TRIANGLE_STRIP, + PIPE_PRIM_TRIANGLES, /* decomposed */ + PIPE_PRIM_QUADS, + PIPE_PRIM_QUAD_STRIP, + PIPE_PRIM_TRIANGLES /* decomposed */ }; @@ -276,17 +217,10 @@ static void varray_prepare(struct draw_pt_front_end *frontend, { struct varray_frontend *varray = (struct varray_frontend *)frontend; - if (opt & PT_PIPELINE) - { - varray->base.run = varray_run_extras; - } - else - { - varray->base.run = varray_run; - } + varray->base.run = varray_run; varray->input_prim = prim; - varray->output_prim = reduced_prim[prim]; + varray->output_prim = decompose_prim[prim]; varray->middle = middle; middle->prepare(middle, varray->output_prim, opt); diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h index 6e2b16d9be..b6f1f0cadc 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h @@ -1,3 +1,7 @@ +static unsigned trim( unsigned count, unsigned first, unsigned incr ) +{ + return count - (count - first) % incr; +} static void FUNC(struct draw_pt_front_end *frontend, pt_elt_func get_elt, @@ -5,12 +9,9 @@ static void FUNC(struct draw_pt_front_end *frontend, unsigned count) { struct varray_frontend *varray = (struct varray_frontend *)frontend; - struct draw_context *draw = varray->draw; unsigned start = (unsigned)elts; - boolean flatfirst = (draw->rasterizer->flatshade && - draw->rasterizer->flatshade_first); - unsigned i, j, flags; + unsigned i, j; unsigned first, incr; varray->fetch_start = start; @@ -27,26 +28,30 @@ static void FUNC(struct draw_pt_front_end *frontend, case PIPE_PRIM_POINTS: case PIPE_PRIM_LINES: case PIPE_PRIM_TRIANGLES: - j = 0; - while (j + first <= count) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - varray_flush_linear(varray, start + j, end); - j += end; + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + + for (j = 0; j < count;) { + unsigned remaining = count - j; + unsigned nr = trim( MIN2(FETCH_MAX, remaining), first, incr ); + varray_flush_linear(varray, start + j, nr); + j += nr; + if (nr != remaining) + j -= (first - incr); } break; case PIPE_PRIM_LINE_LOOP: if (count >= 2) { - flags = DRAW_PIPE_RESET_STIPPLE; - for (j = 0; j + first <= count; j += i) { unsigned end = MIN2(FETCH_MAX, count - j); end -= (end % incr); - for (i = 1; i < end; i++, flags = 0) { - LINE(varray, flags, i - 1, i); + for (i = 1; i < end; i++) { + LINE(varray, i - 1, i); } - LINE(varray, flags, i - 1, 0); + LINE(varray, i - 1, 0); i = end; fetch_init(varray, end); varray_flush(varray); @@ -54,145 +59,21 @@ static void FUNC(struct draw_pt_front_end *frontend, } break; - case PIPE_PRIM_LINE_STRIP: - flags = DRAW_PIPE_RESET_STIPPLE; - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 1; i < end; i++, flags = 0) { - LINE(varray, flags, i - 1, i); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - } - break; - - case PIPE_PRIM_TRIANGLE_STRIP: - if (flatfirst) { - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+2 < end; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0, i + 1 + (i&1), i + 2 - (i&1)); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - if (j + first + i <= count) { - varray->fetch_start -= 2; - i -= 2; - } - } - } - else { - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+2 < end; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0 + (i&1), i + 1 - (i&1), i + 2); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - if (j + first + i <= count) { - varray->fetch_start -= 2; - i -= 2; - } - } - } - break; + case PIPE_PRIM_POLYGON: case PIPE_PRIM_TRIANGLE_FAN: - if (count >= 3) { - if (flatfirst) { - flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+2 < end; i++) { - TRIANGLE(varray, flags, i + 1, i + 2, 0); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - } - } - else { - flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+2 < end; i++) { - TRIANGLE(varray, flags, 0, i + 1, i + 2); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - } - } - } - break; - - case PIPE_PRIM_QUADS: - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+3 < end; i += 4) { - QUAD(varray, i + 0, i + 1, i + 2, i + 3); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - } - break; - - case PIPE_PRIM_QUAD_STRIP: for (j = 0; j + first <= count; j += i) { unsigned end = MIN2(FETCH_MAX, count - j); end -= (end % incr); - for (i = 0; i+3 < end; i += 2) { - QUAD(varray, i + 2, i + 0, i + 1, i + 3); + for (i = 2; i < end; i++) { + TRIANGLE(varray, 0, i - 1, i); } i = end; fetch_init(varray, end); varray_flush(varray); - if (j + first + i <= count) { - varray->fetch_start -= 2; - i -= 2; - } } break; - case PIPE_PRIM_POLYGON: - { - /* These bitflags look a little odd because we submit the - * vertices as (1,2,0) to satisfy flatshade requirements. - */ - const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; - const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; - const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; - - flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; - for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); - end -= (end % incr); - for (i = 0; i+2 < end; i++, flags = edge_middle) { - - if (i + 3 == count) - flags |= edge_last; - - TRIANGLE(varray, flags, i + 1, i + 2, 0); - } - i = end; - fetch_init(varray, end); - varray_flush(varray); - } - } - break; - default: assert(0); break; -- cgit v1.2.3 From bbda45ec769120324f44febf00c6bb170f594f23 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 12 May 2008 19:40:20 +0100 Subject: draw: turn fse path into a middle end Also add some util functions in pt_util.c --- src/gallium/auxiliary/draw/Makefile | 2 + src/gallium/auxiliary/draw/draw_private.h | 2 +- src/gallium/auxiliary/draw/draw_pt.c | 34 +- src/gallium/auxiliary/draw/draw_pt.h | 9 +- .../auxiliary/draw/draw_pt_fetch_shade_emit.c | 39 +- src/gallium/auxiliary/draw/draw_pt_middle_fse.c | 705 +++++++++++++++++++++ src/gallium/auxiliary/draw/draw_pt_util.c | 103 +++ src/gallium/auxiliary/draw/draw_pt_varray.c | 45 -- src/gallium/auxiliary/draw/draw_pt_varray_tmp.h | 2 +- .../auxiliary/draw/draw_pt_varray_tmp_linear.h | 9 +- src/gallium/auxiliary/draw/draw_pt_vcache.c | 15 +- 11 files changed, 847 insertions(+), 118 deletions(-) create mode 100644 src/gallium/auxiliary/draw/draw_pt_middle_fse.c create mode 100644 src/gallium/auxiliary/draw/draw_pt_util.c (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile index 68e7744cc5..67d78bdbbd 100644 --- a/src/gallium/auxiliary/draw/Makefile +++ b/src/gallium/auxiliary/draw/Makefile @@ -27,8 +27,10 @@ C_SOURCES = \ draw_pt_fetch.c \ draw_pt_fetch_emit.c \ draw_pt_fetch_shade_emit.c \ + draw_pt_middle_fse.c \ draw_pt_fetch_shade_pipeline.c \ draw_pt_post_vs.c \ + draw_pt_util.c \ draw_pt_varray.c \ draw_pt_vcache.c \ draw_vertex.c \ diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index cbe64cd290..86b901a3c8 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -124,7 +124,7 @@ struct draw_context struct { struct { struct draw_pt_middle_end *fetch_emit; - /*struct draw_pt_middle_end *fetch_shade_emit;*/ + struct draw_pt_middle_end *fetch_shade_emit; struct draw_pt_middle_end *general; } middle; diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index d9e73a2396..91e35db819 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -75,6 +75,8 @@ draw_pt_arrays(struct draw_context *draw, if (opt == 0) middle = draw->pt.middle.fetch_emit; + else if (opt == PT_SHADE && draw->pt.test_fse) + middle = draw->pt.middle.fetch_shade_emit; else middle = draw->pt.middle.general; @@ -83,9 +85,11 @@ draw_pt_arrays(struct draw_context *draw, */ if (draw->pt.user.elts || (opt & PT_PIPELINE)) { frontend = draw->pt.front.vcache; +#if 0 } else if (opt == PT_SHADE && draw->pt.test_fse) { /* should be a middle end.. */ frontend = draw->pt.front.fetch_shade_emit; +#endif } else { frontend = draw->pt.front.varray; } @@ -105,6 +109,8 @@ draw_pt_arrays(struct draw_context *draw, boolean draw_pt_init( struct draw_context *draw ) { + draw->pt.test_fse = GETENV("DRAW_FSE") != NULL; + draw->pt.front.vcache = draw_pt_vcache( draw ); if (!draw->pt.front.vcache) return FALSE; @@ -117,8 +123,11 @@ boolean draw_pt_init( struct draw_context *draw ) if (!draw->pt.middle.fetch_emit) return FALSE; - draw->pt.test_fse = GETENV("DRAW_FSE") != NULL; if (draw->pt.test_fse) { + draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw ); + if (!draw->pt.middle.fetch_shade_emit) + return FALSE; + draw->pt.front.fetch_shade_emit = draw_pt_fetch_shade_emit( draw ); if (!draw->pt.front.fetch_shade_emit) return FALSE; @@ -145,6 +154,11 @@ void draw_pt_destroy( struct draw_context *draw ) draw->pt.middle.fetch_emit = NULL; } + if (draw->pt.middle.fetch_shade_emit) { + draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit ); + draw->pt.middle.fetch_shade_emit = NULL; + } + if (draw->pt.front.fetch_shade_emit) { draw->pt.front.fetch_shade_emit->destroy( draw->pt.front.fetch_shade_emit ); draw->pt.front.fetch_shade_emit = NULL; @@ -163,19 +177,6 @@ void draw_pt_destroy( struct draw_context *draw ) -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; - /** * Draw vertex arrays @@ -188,9 +189,10 @@ void draw_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { - if (reduced_prim[prim] != draw->reduced_prim) { + unsigned reduced_prim = draw_pt_reduced_prim(prim); + if (reduced_prim != draw->reduced_prim) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); - draw->reduced_prim = reduced_prim[prim]; + draw->reduced_prim = reduced_prim; } /* drawing done here: */ diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index bcd89f6bd6..cdae46b8d2 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -134,7 +134,7 @@ struct draw_pt_front_end *draw_pt_fetch_shade_emit( struct draw_context *draw ); * vertex_elements. */ struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ); -//struct draw_pt_middle_end *draw_pt_fetch_shade_emit( struct draw_context *draw ); +struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw ); struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw); @@ -213,4 +213,11 @@ struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw ); void draw_pt_post_vs_destroy( struct pt_post_vs *pvs ); +/******************************************************************************* + * Utils: + */ +void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr); +unsigned draw_pt_reduced_prim(unsigned prim); + + #endif diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index 9e1d1add36..f756d3e0bb 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -434,43 +434,6 @@ static void fse_prepare( struct draw_pt_front_end *fe, } -static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr) -{ - switch (prim) { - case PIPE_PRIM_POINTS: - *first = 1; - *incr = 1; - return TRUE; - case PIPE_PRIM_LINES: - *first = 2; - *incr = 2; - return TRUE; - case PIPE_PRIM_LINE_STRIP: - *first = 2; - *incr = 1; - return TRUE; - case PIPE_PRIM_TRIANGLES: - *first = 3; - *incr = 3; - return TRUE; - case PIPE_PRIM_TRIANGLE_STRIP: - *first = 3; - *incr = 1; - return TRUE; - case PIPE_PRIM_QUADS: - *first = 4; - *incr = 4; - return TRUE; - case PIPE_PRIM_QUAD_STRIP: - *first = 4; - *incr = 2; - return TRUE; - default: - *first = 0; - *incr = 1; /* set to one so that count % incr works */ - return FALSE; - } -} @@ -596,7 +559,7 @@ fse_run(struct draw_pt_front_end *fe, //debug_printf("%s prim %d start %d count %d\n", __FUNCTION__, prim, start, count); - split_prim_inplace(fse->prim, &first, &incr); + draw_pt_split_prim(fse->prim, &first, &incr); count -= (count - first) % incr; diff --git a/src/gallium/auxiliary/draw/draw_pt_middle_fse.c b/src/gallium/auxiliary/draw/draw_pt_middle_fse.c new file mode 100644 index 0000000000..cdb7d260da --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_middle_fse.c @@ -0,0 +1,705 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + */ + + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vbuf.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pt.h" +#include "draw/draw_vs.h" + +#include "translate/translate.h" + +struct fetch_shade_emit; + +struct fse_shader { + struct translate_key key; + + void (*run_linear)( const struct fetch_shade_emit *fse, + unsigned start, + unsigned count, + char *buffer ); + + void (*run_elts)( const struct fetch_shade_emit *fse, + const unsigned *fetch_elts, + unsigned fetch_count, + char *buffer ); + +}; + +/* Prototype fetch, shade, emit-hw-verts all in one go. + */ +struct fetch_shade_emit { + struct draw_pt_middle_end base; + struct draw_context *draw; + + struct translate_key key; + + /* Temporaries: + */ + const float *constants; + unsigned pitch[PIPE_MAX_ATTRIBS]; + const ubyte *src[PIPE_MAX_ATTRIBS]; + unsigned prim; + + /* Points to one of the three hardwired example shaders, below: + */ + struct fse_shader *active; + + /* Temporary: A list of hard-wired shaders. Of course the plan + * would be to generate these for a given (vertex-shader, + * translate-key) pair... + */ + struct fse_shader shader[10]; + int nr_shaders; +}; + + + +/* Not quite passthrough yet -- we're still running the 'shader' here, + * inlined into the vertex fetch function. + */ +static void shader0_run_linear( const struct fetch_shade_emit *fse, + unsigned start, + unsigned count, + char *buffer ) +{ + unsigned i; + + const float *m = fse->constants; + const ubyte *xyz = fse->src[0] + start * fse->pitch[0]; + const ubyte *rgb = fse->src[1] + start * fse->pitch[1]; + const ubyte *st = fse->src[2] + start * fse->pitch[2]; + + float *out = (float *)buffer; + + /* loop over vertex attributes (vertex shader inputs) + */ + for (i = 0; i < count; i++) { + { + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + xyz += fse->pitch[0]; + } + + { + const float *in = (const float *)rgb; + out[4] = in[0]; + out[5] = in[1]; + out[6] = in[2]; + out[7] = 1.0f; + rgb += fse->pitch[1]; + } + + { + const float *in = (const float *)st; + out[8] = in[0]; + out[9] = in[1]; + out[10] = 0.0f; + out[11] = 1.0f; + st += fse->pitch[2]; + } + + out += 12; + } +} + + + +static void shader1_run_linear( const struct fetch_shade_emit *fse, + unsigned start, + unsigned count, + char *buffer ) +{ + unsigned i; + const float *m = (const float *)fse->constants; + const ubyte *xyz = fse->src[0] + start * fse->pitch[0]; + const ubyte *rgb = fse->src[1] + start * fse->pitch[1]; + float *out = (float *)buffer; + +// debug_printf("rgb %f %f %f\n", rgb[0], rgb[1], rgb[2]); + + + for (i = 0; i < count; i++) { + { + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + xyz += fse->pitch[0]; + } + + { + const float *in = (const float *)rgb; + out[4] = in[0]; + out[5] = in[1]; + out[6] = in[2]; + out[7] = 1.0f; + rgb += fse->pitch[1]; + } + + out += 8; + } +} + + + + +static void shader2_run_linear( const struct fetch_shade_emit *fse, + unsigned start, + unsigned count, + char *buffer ) +{ + unsigned i; + const float *m = (const float *)fse->constants; + const ubyte *xyz = fse->src[0] + start * fse->pitch[0]; + const ubyte *rgb = fse->src[1] + start * fse->pitch[1]; + const float psiz = 1.0; + float *out = (float *)buffer; + + + assert(fse->pitch[1] == 0); + + for (i = 0; i < count; i++) { + { + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + xyz += fse->pitch[0]; + } + + { + const float *in = (const float *)rgb; + out[4] = in[0]; + out[5] = in[1]; + out[6] = in[2]; + out[7] = 1.0f; + rgb += fse->pitch[1]; + } + + { + out[8] = psiz; + } + + out += 9; + } +} + + + + +static void shader0_run_elts( const struct fetch_shade_emit *fse, + const unsigned *elts, + unsigned count, + char *buffer ) +{ + unsigned i; + const float *m = fse->constants; + float *out = (float *)buffer; + + + /* loop over vertex attributes (vertex shader inputs) + */ + for (i = 0; i < count; i++) { + unsigned elt = elts[i]; + { + const ubyte *xyz = fse->src[0] + elt * fse->pitch[0]; + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + } + + { + const ubyte *rgb = fse->src[1] + elt * fse->pitch[1]; + const float *in = (const float *)rgb; + out[4] = in[0]; + out[5] = in[1]; + out[6] = in[2]; + out[7] = 1.0f; + } + + { + const ubyte *st = fse->src[2] + elt * fse->pitch[2]; + const float *in = (const float *)st; + out[8] = in[0]; + out[9] = in[1]; + out[10] = 0.0f; + out[11] = 1.0f; + } + + out += 12; + } +} + + + +static void shader1_run_elts( const struct fetch_shade_emit *fse, + const unsigned *elts, + unsigned count, + char *buffer ) +{ + unsigned i; + const float *m = (const float *)fse->constants; + float *out = (float *)buffer; + + for (i = 0; i < count; i++) { + unsigned elt = elts[i]; + + { + const ubyte *xyz = fse->src[0] + elt * fse->pitch[0]; + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + xyz += fse->pitch[0]; + } + + { + const ubyte *rgb = fse->src[1] + elt * fse->pitch[1]; + const float *in = (const float *)rgb; + out[4] = in[0]; + out[5] = in[1]; + out[6] = in[2]; + out[7] = 1.0f; + rgb += fse->pitch[1]; + } + + out += 8; + } +} + + + + +static void shader2_run_elts( const struct fetch_shade_emit *fse, + const unsigned *elts, + unsigned count, + char *buffer ) +{ + unsigned i; + const float *m = (const float *)fse->constants; + const float psiz = 1.0; + float *out = (float *)buffer; + + for (i = 0; i < count; i++) { + unsigned elt = elts[i]; + { + const ubyte *xyz = fse->src[0] + elt * fse->pitch[0]; + const float *in = (const float *)xyz; + const float ix = in[0], iy = in[1], iz = in[2]; + + out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12]; + out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13]; + out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14]; + out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15]; + } + + { + const ubyte *rgb = fse->src[1] + elt * fse->pitch[1]; + out[4] = rgb[0]; + out[5] = rgb[1]; + out[6] = rgb[2]; + out[7] = 1.0f; + } + + { + out[8] = psiz; + } + + out += 9; + } +} + + + +static void fse_prepare( struct draw_pt_middle_end *middle, + unsigned prim, + unsigned opt ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + unsigned num_vs_inputs = draw->vertex_shader->info.num_inputs; + unsigned num_vs_outputs = draw->vertex_shader->info.num_outputs; + const struct vertex_info *vinfo; + unsigned i; + boolean need_psize = 0; + + + if (draw->pt.user.elts) { + assert(0); + return ; + } + + if (!draw->render->set_primitive( draw->render, + prim )) { + assert(0); + return; + } + + /* Must do this after set_primitive() above: + */ + vinfo = draw->render->get_vertex_info(draw->render); + + + + fse->key.nr_elements = MAX2(num_vs_outputs, /* outputs - translate to hw format */ + num_vs_inputs); /* inputs - fetch from api format */ + + fse->key.output_stride = vinfo->size * 4; + memset(fse->key.element, 0, + fse->key.nr_elements * sizeof(fse->key.element[0])); + + for (i = 0; i < num_vs_inputs; i++) { + const struct pipe_vertex_element *src = &draw->pt.vertex_element[i]; + fse->key.element[i].input_format = src->src_format; + + /* Consider ignoring these at this point, ie make generated + * programs independent of this state: + */ + fse->key.element[i].input_buffer = 0; //src->vertex_buffer_index; + fse->key.element[i].input_offset = 0; //src->src_offset; + } + + + { + unsigned dst_offset = 0; + + for (i = 0; i < vinfo->num_attribs; i++) { + unsigned emit_sz = 0; + unsigned output_format = PIPE_FORMAT_NONE; + unsigned vs_output = vinfo->src_index[i]; + + switch (vinfo->emit[i]) { + case EMIT_4F: + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + emit_sz = 4 * sizeof(float); + break; + case EMIT_3F: + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + emit_sz = 3 * sizeof(float); + break; + case EMIT_2F: + output_format = PIPE_FORMAT_R32G32_FLOAT; + emit_sz = 2 * sizeof(float); + break; + case EMIT_1F: + output_format = PIPE_FORMAT_R32_FLOAT; + emit_sz = 1 * sizeof(float); + break; + case EMIT_1F_PSIZE: + need_psize = 1; + output_format = PIPE_FORMAT_R32_FLOAT; + emit_sz = 1 * sizeof(float); + vs_output = num_vs_outputs + 1; + + break; + default: + assert(0); + break; + } + + /* The elements in the key correspond to vertex shader output + * numbers, not to positions in the hw vertex description -- + * that's handled by the output_offset field. + */ + fse->key.element[vs_output].output_format = output_format; + fse->key.element[vs_output].output_offset = dst_offset; + + dst_offset += emit_sz; + assert(fse->key.output_stride >= dst_offset); + } + } + + /* To make psize work, really need to tell the vertex shader to + * copy that value from input->output. For 'translate' this was + * implicit for all elements. + */ +#if 0 + if (need_psize) { + unsigned input = num_vs_inputs + 1; + const struct pipe_vertex_element *src = &draw->pt.vertex_element[i]; + fse->key.element[i].input_format = PIPE_FORMAT_R32_FLOAT; + fse->key.element[i].input_buffer = 0; //nr_buffers + 1; + fse->key.element[i].input_offset = 0; + + fse->key.nr_elements += 1; + + } +#endif + + fse->constants = draw->pt.user.constants; + + /* Would normally look up a vertex shader and peruse its list of + * varients somehow. We omitted that step and put all the + * hardcoded "shaders" into an array. We're just making the + * assumption that this happens to be a matching shader... ie + * you're running isosurf, aren't you? + */ + fse->active = NULL; + for (i = 0; i < fse->nr_shaders; i++) { + if (translate_key_compare( &fse->key, &fse->shader[i].key) == 0) + fse->active = &fse->shader[i]; + } + + if (!fse->active) { + assert(0); + return ; + } + + /* Now set buffer pointers: + */ + for (i = 0; i < num_vs_inputs; i++) { + unsigned buf = draw->pt.vertex_element[i].vertex_buffer_index; + + fse->src[i] = ((const ubyte *) draw->pt.user.vbuffer[buf] + + draw->pt.vertex_buffer[buf].buffer_offset + + draw->pt.vertex_element[i].src_offset); + + fse->pitch[i] = draw->pt.vertex_buffer[buf].pitch; + + } + + + //return TRUE; +} + + + + + + + +static void fse_run_linear( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + + char *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)count ); + + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices, run shader and emit HW verts. + * Clipping and viewport transformation are done elsewhere -- + * either by the API or on hardware, or for some other reason not + * required... + */ + fse->active->run_linear( fse, + start, count, + hw_verts ); + + /* Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, + count ); + + + draw->render->release_vertices( draw->render, + hw_verts, + fse->key.output_stride, + count ); +} + + +static void +fse_run(struct draw_pt_middle_end *middle, + const unsigned *fetch_elts, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)fetch_count ); + if (!hw_verts) { + assert(0); + return; + } + + + /* Single routine to fetch vertices, run shader and emit HW verts. + */ + fse->active->run_elts( fse, + fetch_elts, + fetch_count, + hw_verts ); + + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + draw->render->release_vertices( draw->render, + hw_verts, + fse->key.output_stride, + fetch_count ); + +} + + +static void fse_finish( struct draw_pt_middle_end *middle ) +{ +} + + +static void +fse_destroy( struct draw_pt_middle_end *middle ) +{ + FREE(middle); +} + +struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw ) +{ + struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit); + if (!fse) + return NULL; + + fse->base.prepare = fse_prepare; + fse->base.run = fse_run; + fse->base.run_linear = fse_run_linear; + fse->base.finish = fse_finish; + fse->base.destroy = fse_destroy; + fse->draw = draw; + + fse->shader[0].run_linear = shader0_run_linear; + fse->shader[0].run_elts = shader0_run_elts; + fse->shader[0].key.nr_elements = 3; + fse->shader[0].key.output_stride = 12 * sizeof(float); + + fse->shader[0].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[0].key.element[0].input_buffer = 0; + fse->shader[0].key.element[0].input_offset = 0; + fse->shader[0].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[0].key.element[0].output_offset = 0; + + fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[0].key.element[1].input_buffer = 0; + fse->shader[0].key.element[1].input_offset = 0; + fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[0].key.element[1].output_offset = 16; + + fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32_FLOAT; + fse->shader[0].key.element[1].input_buffer = 0; + fse->shader[0].key.element[1].input_offset = 0; + fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[0].key.element[1].output_offset = 32; + + fse->shader[1].run_linear = shader1_run_linear; + fse->shader[1].run_elts = shader1_run_elts; + fse->shader[1].key.nr_elements = 2; + fse->shader[1].key.output_stride = 8 * sizeof(float); + + fse->shader[1].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[1].key.element[0].input_buffer = 0; + fse->shader[1].key.element[0].input_offset = 0; + fse->shader[1].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[1].key.element[0].output_offset = 0; + + fse->shader[1].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[1].key.element[1].input_buffer = 0; + fse->shader[1].key.element[1].input_offset = 0; + fse->shader[1].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[1].key.element[1].output_offset = 16; + + fse->shader[2].run_linear = shader2_run_linear; + fse->shader[2].run_elts = shader2_run_elts; + fse->shader[2].key.nr_elements = 3; + fse->shader[2].key.output_stride = 9 * sizeof(float); + + fse->shader[2].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[2].key.element[0].input_buffer = 0; + fse->shader[2].key.element[0].input_offset = 0; + fse->shader[2].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[2].key.element[0].output_offset = 0; + + fse->shader[2].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT; + fse->shader[2].key.element[1].input_buffer = 0; + fse->shader[2].key.element[1].input_offset = 0; + fse->shader[2].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fse->shader[2].key.element[1].output_offset = 16; + + /* psize is special + * -- effectively add it here as another input!?! + * -- who knows how to add it as a buffer? + */ + fse->shader[2].key.element[2].input_format = PIPE_FORMAT_R32_FLOAT; + fse->shader[2].key.element[2].input_buffer = 0; + fse->shader[2].key.element[2].input_offset = 0; + fse->shader[2].key.element[2].output_format = PIPE_FORMAT_R32_FLOAT; + fse->shader[2].key.element[2].output_offset = 32; + + fse->nr_shaders = 3; + + return &fse->base; +} diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c new file mode 100644 index 0000000000..32c8a9632c --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_util.c @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_pt.h" + +void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + *first = 1; + *incr = 1; + break; + case PIPE_PRIM_LINES: + *first = 2; + *incr = 2; + break; + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + *first = 2; + *incr = 1; + break; + case PIPE_PRIM_TRIANGLES: + *first = 3; + *incr = 3; + break; + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + *first = 3; + *incr = 1; + break; + case PIPE_PRIM_QUADS: + *first = 4; + *incr = 4; + break; + case PIPE_PRIM_QUAD_STRIP: + *first = 4; + *incr = 2; + break; + default: + assert(0); + *first = 0; + *incr = 1; /* set to one so that count % incr works */ + break; + } +} + + +unsigned draw_pt_reduced_prim(unsigned prim) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + return PIPE_PRIM_POINTS; + case PIPE_PRIM_LINES: + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + return PIPE_PRIM_LINES; + case PIPE_PRIM_TRIANGLES: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + return PIPE_PRIM_TRIANGLES; + default: + assert(0); + return PIPE_PRIM_POINTS; + } +} + + diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index d92ad4fda1..af6e2d5157 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -106,51 +106,6 @@ static INLINE void fetch_init(struct varray_frontend *varray, } -static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr) -{ - switch (prim) { - case PIPE_PRIM_POINTS: - *first = 1; - *incr = 1; - return TRUE; - case PIPE_PRIM_LINES: - *first = 2; - *incr = 2; - return TRUE; - case PIPE_PRIM_LINE_STRIP: - *first = 2; - *incr = 1; - return TRUE; - case PIPE_PRIM_TRIANGLES: - *first = 3; - *incr = 3; - return TRUE; - case PIPE_PRIM_TRIANGLE_STRIP: - *first = 3; - *incr = 1; - return TRUE; - case PIPE_PRIM_TRIANGLE_FAN: - *first = 3; - *incr = 1; - return TRUE; - case PIPE_PRIM_QUADS: - *first = 4; - *incr = 4; - return TRUE; - case PIPE_PRIM_QUAD_STRIP: - *first = 4; - *incr = 2; - return TRUE; - case PIPE_PRIM_POLYGON: - *first = 3; - *incr = 1; - return TRUE; - default: - *first = 0; - *incr = 1; /* set to one so that count % incr works */ - return FALSE; - } -} static INLINE void add_draw_el(struct varray_frontend *varray, diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index 1395275897..6979f6b544 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -15,7 +15,7 @@ static void FUNC(struct draw_pt_front_end *frontend, varray->fetch_start = start; - split_prim_inplace(varray->input_prim, &first, &incr); + draw_pt_split_prim(varray->input_prim, &first, &incr); #if 0 debug_printf("%s (%d) %d/%d\n", __FUNCTION__, diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h index b6f1f0cadc..114ed371a0 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h @@ -16,7 +16,13 @@ static void FUNC(struct draw_pt_front_end *frontend, varray->fetch_start = start; - split_prim_inplace(varray->input_prim, &first, &incr); + draw_pt_split_prim(varray->input_prim, &first, &incr); + + /* Sanitize primitive length: + */ + count = trim(count, first, incr); + if (count < first) + return; #if 0 debug_printf("%s (%d) %d/%d\n", __FUNCTION__, @@ -32,7 +38,6 @@ static void FUNC(struct draw_pt_front_end *frontend, case PIPE_PRIM_TRIANGLE_STRIP: case PIPE_PRIM_QUADS: case PIPE_PRIM_QUAD_STRIP: - for (j = 0; j < count;) { unsigned remaining = count - j; unsigned nr = trim( MIN2(FETCH_MAX, remaining), first, incr ); diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index 6b3fb1406b..a3495f2a30 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -204,19 +204,6 @@ static void vcache_ef_quad( struct vcache_frontend *vcache, -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; - static void vcache_prepare( struct draw_pt_front_end *frontend, @@ -236,7 +223,7 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, } vcache->input_prim = prim; - vcache->output_prim = reduced_prim[prim]; + vcache->output_prim = draw_pt_reduced_prim(prim); vcache->middle = middle; middle->prepare( middle, vcache->output_prim, opt ); -- cgit v1.2.3 From 1c624846a81b0218b4a07328f485e295432c6312 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Tue, 13 May 2008 16:06:09 -0400 Subject: decomposition from keith, adds decomposition of more prim to the pipeline --- src/gallium/auxiliary/draw/draw_pipe.c | 74 ++++++++---- src/gallium/auxiliary/draw/draw_pt_decompose.h | 153 +++++++++++++++++++++++++ src/gallium/auxiliary/draw/draw_pt_varray.c | 11 +- src/gallium/auxiliary/draw/draw_pt_vcache.c | 117 +++++++++---------- 4 files changed, 263 insertions(+), 92 deletions(-) create mode 100644 src/gallium/auxiliary/draw/draw_pt_decompose.h (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index cb97f955b2..1d26706dee 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -212,6 +212,55 @@ void draw_pipeline_run( struct draw_context *draw, draw->pipeline.vertex_count = 0; } +#define QUAD(i0,i1,i2,i3) \ + do_triangle( draw, \ + ( DRAW_PIPE_RESET_STIPPLE | \ + DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_2 ), \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ + verts + stride * (i3)); \ + do_triangle( draw, \ + ( DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_1 ), \ + verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i2), \ + verts + stride * (i3)) + +#define TRIANGLE(flags,i0,i1,i2) \ + do_triangle( draw, \ + flags, /* flags */ \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ + verts + stride * (i2)) + +#define LINE(flags,i0,i1) \ + do_line( draw, \ + flags, \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i+1)) + +#define POINT(i0) \ + do_point( draw, \ + verts + stride * i0 ) + +#define FUNC pipe_run_linear +#define ARGS \ + struct draw_context *draw, \ + unsigned prim, \ + struct vertex_header *vertices, \ + unsigned stride + +#define LOCAL_VARS \ + char *verts = (char *)vertices; \ + boolean flatfirst = (draw->rasterizer->flatshade && \ + draw->rasterizer->flatshade_first); \ + unsigned i, flags + +#define FLUSH + +#include "draw_pt_decompose.h" + void draw_pipeline_run_linear( struct draw_context *draw, unsigned prim, struct vertex_header *vertices, @@ -219,34 +268,11 @@ void draw_pipeline_run_linear( struct draw_context *draw, unsigned stride ) { char *verts = (char *)vertices; - unsigned i; - draw->pipeline.verts = verts; draw->pipeline.vertex_stride = stride; draw->pipeline.vertex_count = count; - switch (prim) { - case PIPE_PRIM_POINTS: - for (i = 0; i < count; i++) - do_point( draw, - verts + stride * i ); - break; - case PIPE_PRIM_LINES: - for (i = 0; i+1 < count; i += 2) - do_line( draw, - i+0, /* flags */ - verts + stride * ((i+0) & ~DRAW_PIPE_FLAG_MASK), - verts + stride * (i+1)); - break; - case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) - do_triangle( draw, - (i+0), /* flags */ - verts + stride * ((i+0) & ~DRAW_PIPE_FLAG_MASK), - verts + stride * (i+1), - verts + stride * (i+2)); - break; - } + pipe_run_linear(draw, prim, vertices, stride, count); draw->pipeline.verts = NULL; draw->pipeline.vertex_count = 0; diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h new file mode 100644 index 0000000000..dccfde99dd --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h @@ -0,0 +1,153 @@ + + +static void FUNC( ARGS, + unsigned count ) +{ + LOCAL_VARS; + + switch (prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < count; i ++) { + POINT( (i + 0) ); + } + break; + + case PIPE_PRIM_LINES: + for (i = 0; i+1 < count; i += 2) { + LINE( DRAW_PIPE_RESET_STIPPLE, + (i + 0), + (i + 1)); + } + break; + + case PIPE_PRIM_LINE_LOOP: + if (count >= 2) { + flags = DRAW_PIPE_RESET_STIPPLE; + + for (i = 1; i < count; i++, flags = 0) { + LINE( flags, + (i - 1), + (i )); + } + + LINE( flags, + (i - 1), + (0 )); + } + break; + + case PIPE_PRIM_LINE_STRIP: + flags = DRAW_PIPE_RESET_STIPPLE; + for (i = 1; i < count; i++, flags = 0) { + LINE( flags, + (i - 1), + (i )); + } + break; + + case PIPE_PRIM_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0), + (i + 1), + (i + 2 )); + } + break; + + case PIPE_PRIM_TRIANGLE_STRIP: + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0), + (i + 1 + (i&1)), + (i + 2 - (i&1))); + } + } + else { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0 + (i&1)), + (i + 1 - (i&1)), + (i + 2 )); + } + } + break; + + case PIPE_PRIM_TRIANGLE_FAN: + if (count >= 3) { + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 1), + (i + 2), + (0 )); + } + } + else { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (0), + (i + 1), + (i + 2 )); + } + } + } + break; + + + case PIPE_PRIM_QUADS: + for (i = 0; i+3 < count; i += 4) { + QUAD( (i + 0), + (i + 1), + (i + 2), + (i + 3)); + } + break; + + case PIPE_PRIM_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + QUAD( (i + 2), + (i + 0), + (i + 1), + (i + 3)); + } + break; + + case PIPE_PRIM_POLYGON: + { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; + const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; + + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + + for (i = 0; i+2 < count; i++, flags = edge_middle) { + + if (i + 3 == count) + flags |= edge_last; + + TRIANGLE( flags, + (i + 1), + (i + 2), + (0)); + } + } + break; + + default: + assert(0); + break; + } + + FLUSH; +} + + +#undef TRIANGLE +#undef QUAD +#undef POINT +#undef LINE +#undef FUNC diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index af6e2d5157..06fd866ccd 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -141,14 +141,19 @@ static INLINE void varray_point( struct varray_frontend *varray, } - +#if 0 +#define TRIANGLE(flags,i0,i1,i2) varray_triangle(varray,i0,i1,i2) +#define LINE(flags,i0,i1) varray_line(varray,i0,i1) +#define POINT(i0) varray_point(varray,i0) +#define FUNC varray_decompose +#include "draw_pt_decompose.h" +#else #define TRIANGLE(vc,i0,i1,i2) varray_triangle(vc,i0,i1,i2) #define LINE(vc,i0,i1) varray_line(vc,i0,i1) #define POINT(vc,i0) varray_point(vc,i0) #define FUNC varray_run #include "draw_pt_varray_tmp_linear.h" - - +#endif static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = { PIPE_PRIM_POINTS, diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index a3495f2a30..6c17edba34 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -104,22 +104,10 @@ static INLINE void vcache_elt( struct vcache_frontend *vcache, static void vcache_triangle( struct vcache_frontend *vcache, + ushort flags, unsigned i0, unsigned i1, unsigned i2 ) -{ - vcache_elt(vcache, i0, 0); - vcache_elt(vcache, i1, 0); - vcache_elt(vcache, i2, 0); - vcache_check_flush(vcache); -} - - -static void vcache_triangle_flags( struct vcache_frontend *vcache, - ushort flags, - unsigned i0, - unsigned i1, - unsigned i2 ) { vcache_elt(vcache, i0, flags); vcache_elt(vcache, i1, 0); @@ -128,19 +116,9 @@ static void vcache_triangle_flags( struct vcache_frontend *vcache, } static void vcache_line( struct vcache_frontend *vcache, + ushort flags, unsigned i0, unsigned i1 ) -{ - vcache_elt(vcache, i0, 0); - vcache_elt(vcache, i1, 0); - vcache_check_flush(vcache); -} - - -static void vcache_line_flags( struct vcache_frontend *vcache, - ushort flags, - unsigned i0, - unsigned i1 ) { vcache_elt(vcache, i0, flags); vcache_elt(vcache, i1, 0); @@ -161,46 +139,63 @@ static void vcache_quad( struct vcache_frontend *vcache, unsigned i2, unsigned i3 ) { - vcache_triangle( vcache, i0, i1, i3 ); - vcache_triangle( vcache, i1, i2, i3 ); -} - -static void vcache_ef_quad( struct vcache_frontend *vcache, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) -{ - const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2; - const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1; - - vcache_triangle_flags( vcache, - DRAW_PIPE_RESET_STIPPLE | omitEdge1, - i0, i1, i3 ); - - vcache_triangle_flags( vcache, - omitEdge2, - i1, i2, i3 ); + vcache_triangle( vcache, + ( DRAW_PIPE_RESET_STIPPLE | + DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_2 ), + i0, i1, i3 ); + + vcache_triangle( vcache, + ( DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_1 ), + i1, i2, i3 ); } /* At least for now, we're back to using a template include file for * this. The two paths aren't too different though - it may be * possible to reunify them. */ -#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1) -#define POINT(vc,i0) vcache_point(vc,i0) -#define FUNC vcache_run_extras -#include "draw_pt_vcache_tmp.h" - -#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1) -#define POINT(vc,i0) vcache_point(vc,i0) +#define TRIANGLE(flags,i0,i1,i2) \ + vcache_triangle(vcache, \ + flags, \ + get_elt(elts,i0), \ + get_elt(elts,i1), \ + get_elt(elts,i2)) + +#define QUAD(i0,i1,i2,i3) \ + vcache_quad(vcache, \ + get_elt(elts,i0), \ + get_elt(elts,i1), \ + get_elt(elts,i2), \ + get_elt(elts,i3)) + +#define LINE(flags,i0,i1) \ + vcache_line(vcache, \ + flags, \ + get_elt(elts,i0), \ + get_elt(elts,i1)) + +#define POINT(i0) \ + vcache_point(vcache, \ + get_elt(elts,i0)) + #define FUNC vcache_run -#include "draw_pt_vcache_tmp.h" +#define ARGS \ + struct draw_pt_front_end *frontend, \ + pt_elt_func get_elt, \ + const void *elts + +#define LOCAL_VARS \ + struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; \ + struct draw_context *draw = vcache->draw; \ + boolean flatfirst = (draw->rasterizer->flatshade && \ + draw->rasterizer->flatshade_first); \ + unsigned prim = vcache->input_prim; \ + unsigned i, flags; +#define FLUSH vcache_flush( vcache ) + +#include "draw_pt_decompose.h" @@ -213,15 +208,7 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; - if (opt & PT_PIPELINE) - { - vcache->base.run = vcache_run_extras; - } - else - { - vcache->base.run = vcache_run; - } - + vcache->base.run = vcache_run; vcache->input_prim = prim; vcache->output_prim = draw_pt_reduced_prim(prim); -- cgit v1.2.3 From 9f9f6c21be105de41a58128605b911e679efe8f0 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 27 May 2008 13:15:52 +0200 Subject: draw: Fixed typo in draw_pt_varray and added comments --- src/gallium/auxiliary/draw/draw_pt_varray.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_pt_varray.c') diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index 06fd866ccd..260f28f284 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -158,14 +158,14 @@ static INLINE void varray_point( struct varray_frontend *varray, static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = { PIPE_PRIM_POINTS, PIPE_PRIM_LINES, + PIPE_PRIM_LINES, /* decomposed LINELOOP */ PIPE_PRIM_LINE_STRIP, - PIPE_PRIM_LINES, /* decomposed */ PIPE_PRIM_TRIANGLES, PIPE_PRIM_TRIANGLE_STRIP, - PIPE_PRIM_TRIANGLES, /* decomposed */ + PIPE_PRIM_TRIANGLES, /* decomposed TRI_FAN */ PIPE_PRIM_QUADS, PIPE_PRIM_QUAD_STRIP, - PIPE_PRIM_TRIANGLES /* decomposed */ + PIPE_PRIM_TRIANGLES /* decomposed POLYGON */ }; -- cgit v1.2.3