From 6000dcc973cdc1bd61621b432aed27d21059ae5d Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 23 Jan 2008 23:08:59 -0700 Subject: [PATCH] gallium: improved vertex layout and interpolant setup in softpipe --- src/mesa/pipe/draw/draw_vertex.h | 2 + src/mesa/pipe/softpipe/sp_context.h | 4 +- src/mesa/pipe/softpipe/sp_prim_setup.c | 217 +++++++++------------- src/mesa/pipe/softpipe/sp_prim_vbuf.c | 4 +- src/mesa/pipe/softpipe/sp_state_derived.c | 55 +++--- 5 files changed, 123 insertions(+), 159 deletions(-) diff --git a/src/mesa/pipe/draw/draw_vertex.h b/src/mesa/pipe/draw/draw_vertex.h index e76a17c198b..7e9d8abcce1 100644 --- a/src/mesa/pipe/draw/draw_vertex.h +++ b/src/mesa/pipe/draw/draw_vertex.h @@ -36,6 +36,7 @@ /** * Vertex attribute format + * XXX rename to "EMIT" */ enum attrib_format { FORMAT_OMIT, /**< don't emit the attribute */ @@ -54,6 +55,7 @@ enum attrib_format { */ enum interp_mode { INTERP_NONE, /**< never interpolate vertex header info */ + INTERP_POS, /**< special case for frag position */ INTERP_CONSTANT, INTERP_LINEAR, INTERP_PERSPECTIVE diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index daf7dd5accc..aff8c2cc5dc 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -89,8 +89,8 @@ struct softpipe_context { /** Vertex format */ struct vertex_info vertex_info; - unsigned attr_mask; - unsigned nr_frag_attrs; /**< number of active fragment attribs */ + struct vertex_info vertex_info_vbuf; + int psize_slot; #if 0 diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c index 4b6b7a0fd12..478ecff2fb5 100644 --- a/src/mesa/pipe/softpipe/sp_prim_setup.c +++ b/src/mesa/pipe/softpipe/sp_prim_setup.c @@ -85,8 +85,6 @@ struct setup_stage { struct tgsi_interp_coef posCoef; /* For Z, W */ struct quad_header quad; - uint firstFpInput; /** Semantic type of first frag input */ - struct { int left[2]; /**< [0] = row0, [1] = row1 */ int right[2]; @@ -515,22 +513,10 @@ setup_fragcoord_coeff(struct setup_stage *setup) */ static void setup_tri_coefficients( struct setup_stage *setup ) { - const enum interp_mode *interp; -#define USE_INPUT_MAP 01 -#if USE_INPUT_MAP - const struct pipe_shader_state *fs = &setup->softpipe->fs->shader; -#endif + const struct softpipe_context *softpipe = setup->softpipe; + const struct pipe_shader_state *fs = &softpipe->fs->shader; uint fragSlot; - if (setup->softpipe->vertex_info.format[0] == FORMAT_HEADER) { - /* skip header, pos slots */ - interp = setup->softpipe->vertex_info.interp_mode + 2; - } - else { - /* skip pos slot */ - interp = setup->softpipe->vertex_info.interp_mode + 1; - } - /* z and w are done by linear interpolation: */ tri_linear_coeff(setup, &setup->posCoef, 0, 2); @@ -538,64 +524,37 @@ static void setup_tri_coefficients( struct setup_stage *setup ) /* setup interpolation for all the remaining attributes: */ - for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) { - /* which vertex output maps to this fragment input: */ -#if !USE_INPUT_MAP - uint vertSlot; - if (setup->firstFpInput == TGSI_SEMANTIC_POSITION) { - if (fragSlot == 0) { - setup_fragcoord_coeff(setup); - continue; - } - vertSlot = fragSlot; - } - else { - vertSlot = fragSlot + 1; - } - -#else - uint vertSlot = fs->input_map[fragSlot]; - - if (vertSlot == 0) { - /* special case: shader is reading gl_FragCoord */ - /* XXX with a new INTERP_POSITION token, we could just add a - * new case to the switch below. - */ + for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) { + const uint vertSlot = softpipe->vertex_info.src_index[fragSlot]; + uint j; + + switch (softpipe->vertex_info.interp_mode[fragSlot]) { + case INTERP_CONSTANT: + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_LINEAR: + for (j = 0; j < NUM_CHANNELS; j++) + tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_PERSPECTIVE: + for (j = 0; j < NUM_CHANNELS; j++) + tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_POS: + assert(fragSlot == 0); setup_fragcoord_coeff(setup); + break; + default: + assert(0); } - else { -#endif - uint j; - switch (interp[fragSlot]) { - case INTERP_CONSTANT: - for (j = 0; j < NUM_CHANNELS; j++) - const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - case INTERP_LINEAR: - for (j = 0; j < NUM_CHANNELS; j++) - tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - case INTERP_PERSPECTIVE: - for (j = 0; j < NUM_CHANNELS; j++) - tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - default: - /* invalid interp mode */ - /* assert(0); re-enable this and run demos/fogcoord.c ... */ - ; - } - if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) { - /* FOG.y = front/back facing XXX fix this */ - setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing; - setup->coef[fragSlot].dadx[1] = 0.0; - setup->coef[fragSlot].dady[1] = 0.0; - } - - -#if USE_INPUT_MAP + if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) { + /* FOG.y = front/back facing XXX fix this */ + setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing; + setup->coef[fragSlot].dadx[1] = 0.0; + setup->coef[fragSlot].dady[1] = 0.0; } -#endif } } @@ -797,9 +756,9 @@ line_persp_coeff(struct setup_stage *setup, static INLINE void setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim) { - const enum interp_mode *interp = setup->softpipe->vertex_info.interp_mode; + const struct softpipe_context *softpipe = setup->softpipe; const struct pipe_shader_state *fs = &setup->softpipe->fs->shader; - unsigned fragSlot; + uint fragSlot; /* use setup->vmin, vmax to point to vertices */ setup->vprovoke = prim->v[1]; @@ -819,34 +778,37 @@ setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim) /* setup interpolation for all the remaining attributes: */ - for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) { - /* which vertex output maps to this fragment input: */ - uint vertSlot = fs->input_map[fragSlot]; - - if (vertSlot == 0) { - /* special case: shader is reading gl_FragCoord */ + for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) { + const uint vertSlot = softpipe->vertex_info.src_index[fragSlot]; + uint j; + + switch (softpipe->vertex_info.interp_mode[fragSlot]) { + case INTERP_CONSTANT: + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_LINEAR: + for (j = 0; j < NUM_CHANNELS; j++) + line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_PERSPECTIVE: + for (j = 0; j < NUM_CHANNELS; j++) + line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_POS: + assert(fragSlot == 0); + assert(0); /* XXX fix this: */ setup_fragcoord_coeff(setup); + break; + default: + assert(0); } - else { - uint j; - switch (interp[vertSlot]) { - case INTERP_CONSTANT: - for (j = 0; j < NUM_CHANNELS; j++) - const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - case INTERP_LINEAR: - for (j = 0; j < NUM_CHANNELS; j++) - line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - case INTERP_PERSPECTIVE: - for (j = 0; j < NUM_CHANNELS; j++) - line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - - default: - /* invalid interp mode */ - assert(0); - } + + if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) { + /* FOG.y = front/back facing XXX fix this */ + setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing; + setup->coef[fragSlot].dadx[1] = 0.0; + setup->coef[fragSlot].dady[1] = 0.0; } } } @@ -1005,8 +967,8 @@ static void setup_point(struct draw_stage *stage, struct prim_header *prim) { struct setup_stage *setup = setup_stage( stage ); - const struct pipe_shader_state *fs = &setup->softpipe->fs->shader; - const enum interp_mode *interp = setup->softpipe->vertex_info.interp_mode; + struct softpipe_context *softpipe = setup->softpipe; + const struct pipe_shader_state *fs = &softpipe->fs->shader; const struct vertex_header *v0 = prim->v[0]; const int sizeAttr = setup->softpipe->psize_slot; const float size @@ -1040,31 +1002,36 @@ setup_point(struct draw_stage *stage, struct prim_header *prim) const_coeff(setup, &setup->posCoef, 0, 2); const_coeff(setup, &setup->posCoef, 0, 3); - for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) { - /* which vertex output maps to this fragment input: */ - uint vertSlot = fs->input_map[fragSlot]; - - if (vertSlot == 0) { - /* special case: shader is reading gl_FragCoord */ + for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) { + const uint vertSlot = softpipe->vertex_info.src_index[fragSlot]; + uint j; + + switch (softpipe->vertex_info.interp_mode[fragSlot]) { + case INTERP_CONSTANT: + /* fall-through */ + case INTERP_LINEAR: + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_PERSPECTIVE: + for (j = 0; j < NUM_CHANNELS; j++) + point_persp_coeff(setup, setup->vprovoke, + &setup->coef[fragSlot], vertSlot, j); + break; + case INTERP_POS: + assert(fragSlot == 0); + assert(0); /* XXX fix this: */ setup_fragcoord_coeff(setup); + break; + default: + assert(0); } - else { - uint j; - switch (interp[vertSlot]) { - case INTERP_CONSTANT: - /* fall-through */ - case INTERP_LINEAR: - for (j = 0; j < NUM_CHANNELS; j++) - const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); - break; - case INTERP_PERSPECTIVE: - for (j = 0; j < NUM_CHANNELS; j++) - point_persp_coeff(setup, setup->vprovoke, - &setup->coef[fragSlot], vertSlot, j); - break; - default: - assert(0); - } + + if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) { + /* FOG.y = front/back facing XXX fix this */ + setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing; + setup->coef[fragSlot].dadx[1] = 0.0; + setup->coef[fragSlot].dady[1] = 0.0; } } @@ -1200,9 +1167,7 @@ static void setup_begin( struct draw_stage *stage ) struct softpipe_context *sp = setup->softpipe; const struct pipe_shader_state *fs = &setup->softpipe->fs->shader; - setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs; - - setup->firstFpInput = fs->input_semantic_name[0]; + setup->quad.nr_attrs = fs->num_inputs; sp->quad.first->begin(sp->quad.first); } diff --git a/src/mesa/pipe/softpipe/sp_prim_vbuf.c b/src/mesa/pipe/softpipe/sp_prim_vbuf.c index 0ab8a55d7d4..dfabae83025 100644 --- a/src/mesa/pipe/softpipe/sp_prim_vbuf.c +++ b/src/mesa/pipe/softpipe/sp_prim_vbuf.c @@ -75,7 +75,7 @@ sp_vbuf_get_vertex_info(struct vbuf_render *vbr) struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); /* XXX check for state changes? */ assert(!cvbr->softpipe->dirty ); - return &cvbr->softpipe->vertex_info; + return &cvbr->softpipe->vertex_info_vbuf; } @@ -140,7 +140,7 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices) struct softpipe_context *softpipe = cvbr->softpipe; struct draw_stage *setup = softpipe->setup; struct prim_header prim; - unsigned vertex_size = softpipe->vertex_info.size * sizeof(float); + unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float); unsigned i, j; void *vertex_buffer = cvbr->vertex_buffer; diff --git a/src/mesa/pipe/softpipe/sp_state_derived.c b/src/mesa/pipe/softpipe/sp_state_derived.c index d399868f244..4be3641d677 100644 --- a/src/mesa/pipe/softpipe/sp_state_derived.c +++ b/src/mesa/pipe/softpipe/sp_state_derived.c @@ -50,9 +50,9 @@ find_vs_output(const struct pipe_shader_state *vs, /** - * Determine which post-transform / pre-rasterization vertex attributes - * we need. - * Derived from: fs, setup states. + * Determine how to map vertex program outputs to fragment program inputs. + * Basically, this will be used when computing the triangle interpolation + * coefficients from the post-transform vertex attributes. */ static void calculate_vertex_layout( struct softpipe_context *softpipe ) { @@ -61,35 +61,33 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe ) const enum interp_mode colorInterp = softpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR; struct vertex_info *vinfo = &softpipe->vertex_info; + struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf; uint i; int src; - memset(vinfo, 0, sizeof(*vinfo)); - - softpipe->psize_slot = -1; - if (softpipe->vbuf) { - /* softpipe's setup/rasterizer stage expects vertex to have a header */ - draw_emit_vertex_attr(vinfo, FORMAT_HEADER, INTERP_LINEAR, 0); + /* if using the post-transform vertex buffer, tell draw_vbuf to + * simply emit the whole post-xform vertex as-is: + */ + vinfo_vbuf->num_attribs = 0; + draw_emit_vertex_attr(vinfo_vbuf, FORMAT_HEADER, INTERP_NONE, 0); + for (i = 0; i < vs->num_outputs; i++) { + draw_emit_vertex_attr(vinfo_vbuf, FORMAT_4F, INTERP_NONE, i); + } + draw_compute_vertex_size(vinfo_vbuf); } - /* always emit pos for softpipe rasterization */ - src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0); - assert(src >= 0); - draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_LINEAR, src); - /* - * XXX I think we need to reconcile the vertex shader outputs with - * the fragment shader inputs here to make sure the slots line up. - * Might just be getting lucky so far. - * Or maybe do that in the state tracker? + * Loop over fragment shader inputs, searching for the matching output + * from the vertex shader. */ - + vinfo->num_attribs = 0; for (i = 0; i < fs->num_inputs; i++) { switch (fs->input_semantic_name[i]) { - case TGSI_SEMANTIC_POSITION: - /* handled above */ + src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0); + assert(src >= 0); + draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_POS, src); break; case TGSI_SEMANTIC_COLOR: @@ -122,16 +120,13 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe ) } } - src = find_vs_output(vs, TGSI_SEMANTIC_PSIZE, 0); - if (src >= 0) { - softpipe->psize_slot = src; - draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_CONSTANT, src); + softpipe->psize_slot = find_vs_output(vs, TGSI_SEMANTIC_PSIZE, 0); + if (softpipe->psize_slot >= 0) { + draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_CONSTANT, + softpipe->psize_slot); } - draw_compute_vertex_size(vinfo); - - softpipe->nr_frag_attrs = fs->num_inputs; } @@ -175,7 +170,9 @@ compute_cliprect(struct softpipe_context *sp) */ void softpipe_update_derived( struct softpipe_context *softpipe ) { - if (softpipe->dirty & (SP_NEW_RASTERIZER | SP_NEW_FS | SP_NEW_VS)) + if (softpipe->dirty & (SP_NEW_RASTERIZER | + SP_NEW_FS | + SP_NEW_VS)) calculate_vertex_layout( softpipe ); if (softpipe->dirty & (SP_NEW_SCISSOR | -- 2.30.2