diff options
author | Brian Paul <brianp@vmware.com> | 2010-12-10 17:03:23 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2010-12-10 17:03:25 -0700 |
commit | 7b0bb99bab6547f503a0176b5c0aef1482b02c97 (patch) | |
tree | f28736d441c5e5c3d4b26374e611c2a08148e941 | |
parent | 2cc926183f957f8abac18d71276dd5bbd1f27be2 (diff) |
st/mesa: checkpoint: implement fragment program variants
The fragment programs variants are per-context, as the vertex programs.
NOTE: glDrawPixels is totally broken at this point.
-rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 24 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.c | 88 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.h | 8 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 14 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_program.c | 10 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 1 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.c | 419 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.h | 47 |
8 files changed, 394 insertions, 217 deletions
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index f0981629b5..94890e9fea 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -51,20 +51,6 @@ -/** - * Translate fragment program if needed. - */ -static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) -{ - if (!stfp->tgsi.tokens) { - assert(stfp->Base.Base.NumInstructions > 0); - - st_translate_fragment_program(st, stfp); - } -} - /* * Translate geometry program if needed. */ @@ -168,12 +154,17 @@ static void update_fp( struct st_context *st ) { struct st_fragment_program *stfp; + struct st_fp_varient_key key; assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - translate_fp(st, stfp); + + memset(&key, 0, sizeof(key)); + key.st = st; + + st->fp_varient = st_get_fp_varient(st, stfp, &key); st_reference_fragprog(st, &st->fp, stfp); @@ -183,7 +174,8 @@ update_fp( struct st_context *st ) cso_set_fragment_shader_handle(st->cso_context, fs); } else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + cso_set_fragment_shader_handle(st->cso_context, + st->fp_varient->driver_shader); } } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index f08697fe23..a2ab743358 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -185,48 +185,47 @@ find_free_bit(uint bitfield) /** * Combine basic bitmap fragment program with the user-defined program. + * \param st current context + * \param fpIn the incoming fragment program + * \param fpOut the new fragment program which does fragment culling + * \param bitmap_sampler sampler number for the bitmap texture */ -static struct st_fragment_program * -combined_bitmap_fragment_program(struct gl_context *ctx) +void +st_make_combined_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp = st->fp; - - if (!stfp->bitmap_program) { - /* - * Generate new program which is the user-defined program prefixed - * with the bitmap sampler/kill instructions. - */ - struct st_fragment_program *bitmap_prog; - uint sampler; + struct st_fragment_program *bitmap_prog; + struct gl_program *newProg; + uint sampler; - sampler = find_free_bit(st->fp->Base.Base.SamplersUsed); - bitmap_prog = make_bitmap_fragment_program(ctx, sampler); - - stfp->bitmap_program = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &bitmap_prog->Base.Base, &stfp->Base.Base); - stfp->bitmap_program->bitmap_sampler = sampler; + /* + * Generate new program which is the user-defined program prefixed + * with the bitmap sampler/kill instructions. + */ + sampler = find_free_bit(fpIn->Base.SamplersUsed); + bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler); - /* done with this after combining */ - st_reference_fragprog(st, &bitmap_prog, NULL); + newProg = _mesa_combine_programs(st->ctx, + &bitmap_prog->Base.Base, + &fpIn->Base); + /* done with this after combining */ + st_reference_fragprog(st, &bitmap_prog, NULL); #if 0 - { - struct gl_program *p = &stfp->bitmap_program->Base.Base; - printf("Combined bitmap program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } -#endif - - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp->bitmap_program); + { + printf("Combined bitmap program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); } +#endif - return stfp->bitmap_program; + /* return results */ + *fpOut = (struct gl_fragment_program *) newProg; + *bitmap_sampler = sampler; } @@ -411,11 +410,16 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; - struct st_fragment_program *stfp; + struct st_fp_varient *fpv; + struct st_fp_varient_key key; GLuint maxSize; GLuint offset; - stfp = combined_bitmap_fragment_program(ctx); + memset(&key, 0, sizeof(key)); + key.st = st; + key.bitmap = GL_TRUE; + + fpv = st_get_fp_varient(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. @@ -428,7 +432,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } @@ -454,7 +458,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ - cso_set_fragment_shader_handle(cso, stfp->driver_shader); + cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); @@ -462,21 +466,21 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers); uint i; for (i = 0; i < st->state.num_samplers; i++) { samplers[i] = &st->state.samplers[i]; } - samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; + samplers[fpv->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures); memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); - sampler_views[stfp->bitmap_sampler] = sv; + sampler_views[fpv->bitmap_sampler] = sv; cso_set_fragment_sampler_views(cso, num, sampler_views); } diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h index d04b2b6779..041dda7dd4 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.h +++ b/src/mesa/state_tracker/st_cb_bitmap.h @@ -34,6 +34,8 @@ struct dd_function_table; struct st_context; +struct gl_fragment_program; +struct st_fragment_program; #if FEATURE_drawpix @@ -47,6 +49,12 @@ extern void st_destroy_bitmap(struct st_context *st); extern void +st_make_combined_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler); + +extern void st_flush_bitmap_cache(struct st_context *st); /* Flush bitmap cache and release vertex buffer. Needed at end of diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index c978602457..e2b1946f15 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -142,7 +142,9 @@ combined_drawpix_fragment_program(struct gl_context *ctx) #endif /* translate to TGSI tokens */ +#if 0000000000000 st_translate_fragment_program(st, stfp); +#endif /* save new program, update serial numbers */ st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; @@ -158,7 +160,11 @@ combined_drawpix_fragment_program(struct gl_context *ctx) */ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); +#if 00000000000 return stfp->driver_shader; +#else + return 0; +#endif } @@ -183,7 +189,11 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (st->drawpix.shaders[shaderIndex]) { /* already have the proper shader */ +#if 00000 return st->drawpix.shaders[shaderIndex]->driver_shader; +#else + return 0; +#endif } /* @@ -247,12 +257,16 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, stp = st_fragment_program((struct gl_fragment_program *) p); +#if 0000 /* save the new shader */ st->drawpix.shaders[shaderIndex] = stp; st_translate_fragment_program(st, stp); return stp->driver_shader; +#else + return 000; +#endif } diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 4d83fcc6cc..c803f84915 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -167,7 +167,10 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) break; case GL_FRAGMENT_PROGRAM_ARB: { - struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + struct st_fragment_program *stfp = + (struct st_fragment_program *) prog; + st_fp_release_varients(st, stfp); +#if 0 if (stfp->driver_shader) { cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); @@ -184,6 +187,8 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) _mesa_reference_program(ctx, &prg, NULL); stfp->bitmap_program = NULL; } +#endif + } break; default: @@ -214,6 +219,8 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, stfp->serialNo++; + st_fp_release_varients(st, stfp); +#if 00000 if (stfp->driver_shader) { cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); stfp->driver_shader = NULL; @@ -223,6 +230,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } +#endif if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index d342c0cff1..dbc6744eed 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -131,6 +131,7 @@ struct st_context struct st_geometry_program *gp; /**< Currently bound geometry program */ struct st_vp_varient *vp_varient; + struct st_fp_varient *fp_varient; struct gl_texture_object *default_texture; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index d7d9e0e36f..322eec880b 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -34,6 +34,7 @@ #include "main/imports.h" #include "main/hash.h" #include "main/mtypes.h" +#include "program/prog_parameter.h" #include "program/prog_print.h" #include "program/programopt.h" @@ -45,6 +46,7 @@ #include "tgsi/tgsi_ureg.h" #include "st_debug.h" +#include "st_cb_bitmap.h" #include "st_context.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" @@ -95,6 +97,39 @@ st_vp_release_varients( struct st_context *st, +/** + * Delete a fragment program varient. Note the caller must unlink + * the varient from the linked list. + */ +static void +delete_fp_varient(struct st_context *st, struct st_fp_varient *fpv) +{ + if (fpv->driver_shader) + cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); + + FREE(fpv); +} + + +/** + * Free all varients of a fragment program. + */ +void +st_fp_release_varients(struct st_context *st, struct st_fragment_program *stfp) +{ + struct st_fp_varient *fpv; + + for (fpv = stfp->varients; fpv; ) { + struct st_fp_varient *next = fpv->next; + delete_fp_varient(st, fpv); + fpv = next; + } + + stfp->varients = NULL; +} + + + /** * Translate a Mesa vertex shader into a TGSI shader. @@ -290,196 +325,253 @@ fail: /** - * Translate a Mesa fragment shader into a TGSI shader. + * Translate a Mesa fragment shader into a TGSI shader using extra info in + * the key. * \return pointer to cached pipe_shader object. */ -void +struct st_fp_varient * st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *stfp ) + struct st_fragment_program *stfp, + const struct st_fp_varient_key *key) { struct pipe_context *pipe = st->pipe; - GLuint outputMapping[FRAG_RESULT_MAX]; - GLuint inputMapping[FRAG_ATTRIB_MAX]; - GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ - GLuint attr; - enum pipe_error error; - const GLbitfield inputsRead = stfp->Base.Base.InputsRead; - struct ureg_program *ureg; + struct st_fp_varient *varient = MALLOC_STRUCT(st_fp_varient); - ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; - uint fs_num_inputs = 0; + if (!varient) + return NULL; - ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; - ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; - uint fs_num_outputs = 0; + if (key->bitmap) { + struct gl_fragment_program *fp; + st_make_combined_bitmap_fragment_program(st, &stfp->Base, + &fp, &varient->bitmap_sampler); - _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + varient->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + stfp = (struct st_fragment_program *) fp; + } - /* - * Convert Mesa program inputs to TGSI input register semantics. - */ - for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { - if (inputsRead & (1 << attr)) { - const GLuint slot = fs_num_inputs++; + if (!stfp->tgsi.tokens) { + /* need to translate Mesa instructions to TGSI now */ + GLuint outputMapping[FRAG_RESULT_MAX]; + GLuint inputMapping[FRAG_ATTRIB_MAX]; + GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ + GLuint attr; + enum pipe_error error; + const GLbitfield inputsRead = stfp->Base.Base.InputsRead; + struct ureg_program *ureg; - inputMapping[attr] = slot; + ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + uint fs_num_inputs = 0; - switch (attr) { - case FRAG_ATTRIB_WPOS: - input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL0: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL1: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 1; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_FOGC: - input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - case FRAG_ATTRIB_FACE: - input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; - break; - /* In most cases, there is nothing special about these - * inputs, so adopt a convention to use the generic - * semantic name and the mesa FRAG_ATTRIB_ number as the - * index. - * - * All that is required is that the vertex shader labels - * its own outputs similarly, and that the vertex shader - * generates at least every output required by the - * fragment shader plus fixed-function hardware (such as - * BFC). - * - * There is no requirement that semantic indexes start at - * zero or be restricted to a particular range -- nobody - * should be building tables based on semantic index. - */ - case FRAG_ATTRIB_PNTC: - case FRAG_ATTRIB_TEX0: - case FRAG_ATTRIB_TEX1: - case FRAG_ATTRIB_TEX2: - case FRAG_ATTRIB_TEX3: - case FRAG_ATTRIB_TEX4: - case FRAG_ATTRIB_TEX5: - case FRAG_ATTRIB_TEX6: - case FRAG_ATTRIB_TEX7: - case FRAG_ATTRIB_VAR0: - default: - /* Actually, let's try and zero-base this just for - * readability of the generated TGSI. - */ - assert(attr >= FRAG_ATTRIB_TEX0); - input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); - input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - if (attr == FRAG_ATTRIB_PNTC) - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - else - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - } - } - else { - inputMapping[attr] = -1; - } - } + ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; + ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; + uint fs_num_outputs = 0; - /* - * Semantics and mapping for outputs - */ - { - uint numColors = 0; - GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; - - /* if z is written, emit that first */ - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); - } - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); - } + _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + + /* + * Convert Mesa program inputs to TGSI input register semantics. + */ + for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { + if (inputsRead & (1 << attr)) { + const GLuint slot = fs_num_inputs++; + + inputMapping[attr] = slot; - /* handle remaning outputs (color) */ - for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { - if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { - case FRAG_RESULT_DEPTH: - case FRAG_RESULT_STENCIL: - /* handled above */ - assert(0); + case FRAG_ATTRIB_WPOS: + input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; + case FRAG_ATTRIB_COL0: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_COL1: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 1; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_FOGC: + input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + case FRAG_ATTRIB_FACE: + input_semantic_name[slot] = TGSI_SEMANTIC_FACE; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; + /* In most cases, there is nothing special about these + * inputs, so adopt a convention to use the generic + * semantic name and the mesa FRAG_ATTRIB_ number as the + * index. + * + * All that is required is that the vertex shader labels + * its own outputs similarly, and that the vertex shader + * generates at least every output required by the + * fragment shader plus fixed-function hardware (such as + * BFC). + * + * There is no requirement that semantic indexes start at + * zero or be restricted to a particular range -- nobody + * should be building tables based on semantic index. + */ + case FRAG_ATTRIB_PNTC: + case FRAG_ATTRIB_TEX0: + case FRAG_ATTRIB_TEX1: + case FRAG_ATTRIB_TEX2: + case FRAG_ATTRIB_TEX3: + case FRAG_ATTRIB_TEX4: + case FRAG_ATTRIB_TEX5: + case FRAG_ATTRIB_TEX6: + case FRAG_ATTRIB_TEX7: + case FRAG_ATTRIB_VAR0: default: - assert(attr == FRAG_RESULT_COLOR || - (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; - fs_output_semantic_index[fs_num_outputs] = numColors; - outputMapping[attr] = fs_num_outputs; - numColors++; + /* Actually, let's try and zero-base this just for + * readability of the generated TGSI. + */ + assert(attr >= FRAG_ATTRIB_TEX0); + input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); + input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + if (attr == FRAG_ATTRIB_PNTC) + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + else + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; } + } + else { + inputMapping[attr] = -1; + } + } + + /* + * Semantics and mapping for outputs + */ + { + uint numColors = 0; + GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; + + /* if z is written, emit that first */ + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; + fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); + } + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); + } + + /* handle remaning outputs (color) */ + for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { + if (outputsWritten & BITFIELD64_BIT(attr)) { + switch (attr) { + case FRAG_RESULT_DEPTH: + case FRAG_RESULT_STENCIL: + /* handled above */ + assert(0); + break; + default: + assert(attr == FRAG_RESULT_COLOR || + (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; + fs_output_semantic_index[fs_num_outputs] = numColors; + outputMapping[attr] = fs_num_outputs; + numColors++; + break; + } + + fs_num_outputs++; + } } } - } - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (ureg == NULL) - return; + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; - if (ST_DEBUG & DEBUG_MESA) { - _mesa_print_program(&stfp->Base.Base); - _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); - debug_printf("\n"); - } + if (ST_DEBUG & DEBUG_MESA) { + _mesa_print_program(&stfp->Base.Base); + _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); + debug_printf("\n"); + } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_FRAGMENT, - ureg, - &stfp->Base.Base, - /* inputs */ - fs_num_inputs, - inputMapping, - input_semantic_name, - input_semantic_index, - interpMode, - /* outputs */ - fs_num_outputs, - outputMapping, - fs_output_semantic_name, - fs_output_semantic_index, FALSE ); + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_FRAGMENT, + ureg, + &stfp->Base.Base, + /* inputs */ + fs_num_inputs, + inputMapping, + input_semantic_name, + input_semantic_index, + interpMode, + /* outputs */ + fs_num_outputs, + outputMapping, + fs_output_semantic_name, + fs_output_semantic_index, FALSE ); + + stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); + ureg_destroy( ureg ); + } - stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); - ureg_destroy( ureg ); - stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + /* fill in varient */ + varient->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + varient->key = *key; if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); debug_printf("\n"); } + + return varient; } + +/** + * Translate fragment program if needed. + */ +struct st_fp_varient * +st_get_fp_varient(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_varient_key *key) +{ + struct st_fp_varient *fpv; + + /* Search for existing varient */ + for (fpv = stfp->varients; fpv; fpv = fpv->next) { + if (memcmp(&fpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!fpv) { + /* create new */ + fpv = st_translate_fragment_program(st, stfp, key); + if (fpv) { + /* insert into list */ + fpv->next = stfp->varients; + stfp->varients = fpv; + } + } + + return fpv; +} + + + void st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp) @@ -807,6 +899,21 @@ destroy_program_variants(struct st_context *st, struct gl_program *program) { struct st_fragment_program *stfp = (struct st_fragment_program *) program; + struct st_fp_varient *fpv, **prev = &stfp->varients; + + for (fpv = stfp->varients; fpv; ) { + struct st_fp_varient *next = fpv->next; + if (fpv->key.st == st) { + /* unlink from list */ + *prev = next; + /* destroy this variant */ + delete_fp_varient(st, fpv); + } + else { + prev = &fpv; + } + fpv = next; + } } break; default: diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 10362ed93b..642a256527 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -40,6 +40,34 @@ #include "st_context.h" +/** Fragment program variant key */ +struct st_fp_varient_key +{ + struct st_context *st; /**< variants are per-context */ + GLboolean bitmap; /**< glBitmap varient? */ +}; + + +/** + * Variant of a fragment program. + */ +struct st_fp_varient +{ + /** Parameters which generated this version of fragment program */ + struct st_fp_varient_key key; + + /** Driver's compiled shader */ + void *driver_shader; + + /** For glBitmap variants */ + struct gl_program_parameter_list *parameters; + uint bitmap_sampler; + + /** next in linked list */ + struct st_fp_varient *next; +}; + + /** * Derived from Mesa gl_fragment_program: */ @@ -49,7 +77,11 @@ struct st_fragment_program GLuint serialNo; struct pipe_shader_state tgsi; +#if 0 void *driver_shader; +#else + struct st_fp_varient *varients; +#endif /** Program prefixed with glBitmap prologue */ struct st_fragment_program *bitmap_program; @@ -199,9 +231,16 @@ st_reference_fragprog(struct st_context *st, } -extern void +extern struct st_fp_varient * st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *fp); + struct st_fragment_program *fp, + const struct st_fp_varient_key *key); + +extern struct st_fp_varient * +st_get_fp_varient(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_varient_key *key); + extern void st_translate_geometry_program(struct st_context *st, @@ -224,6 +263,10 @@ st_vp_release_varients( struct st_context *st, struct st_vertex_program *stvp ); extern void +st_fp_release_varients( struct st_context *st, + struct st_fragment_program *stfp ); + +extern void st_print_shaders(struct gl_context *ctx); extern void |