Module: Mesa Branch: arb_geometry_shader4 Commit: 141b85e9d24f8fbefd8210af6e8fa50882b043b1 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=141b85e9d24f8fbefd8210af6e8fa50882b043b1
Author: Zack Rusin <[email protected]> Date: Sat Sep 5 17:52:33 2009 -0400 gs: lots of improvements to the linking code unfortunately there's still something not quite right --- progs/glsl/convolution.frag | 9 +- progs/glsl/convolutions.c | 19 ++- src/mesa/main/mtypes.h | 12 +- src/mesa/state_tracker/st_atom_shader.c | 302 +++++++++++++++++++++++++++---- src/mesa/state_tracker/st_program.c | 100 ++++++++--- src/mesa/state_tracker/st_program.h | 23 ++- 6 files changed, 389 insertions(+), 76 deletions(-) diff --git a/progs/glsl/convolution.frag b/progs/glsl/convolution.frag index e49b8ac..82c58c1 100644 --- a/progs/glsl/convolution.frag +++ b/progs/glsl/convolution.frag @@ -1,10 +1,12 @@ const int KernelSize = 9; +uniform int KernelCount; //texture offsets uniform vec2 Offset[KernelSize]; //convolution kernel uniform vec4 KernelValue[KernelSize]; +uniform vec4 KernelScale[KernelSize]; uniform sampler2D srcTex; uniform vec4 ScaleFactor; uniform vec4 BaseColor; @@ -13,9 +15,8 @@ void main(void) { int i; vec4 sum = vec4(0.0); - for (i = 0; i < KernelSize; ++i) { - vec4 tmp = texture2D(srcTex, gl_TexCoord[0].st + Offset[i]); - sum += tmp * KernelValue[i]; + for (i = 0; i < KernelCount; ++i) { + sum += KernelValue[i] * KernelScale[i]; } - gl_FragColor = sum * ScaleFactor + BaseColor; + gl_FragColor = sum; } diff --git a/progs/glsl/convolutions.c b/progs/glsl/convolutions.c index c2fb76e..ee330cf 100644 --- a/progs/glsl/convolutions.c +++ b/progs/glsl/convolutions.c @@ -125,9 +125,9 @@ static void fillConvolution(GLint *k, { switch(filter) { case GAUSSIAN_BLUR: - k[0] = 1; k[1] = 2; k[2] = 1; - k[3] = 2; k[4] = 4; k[5] = 2; - k[6] = 1; k[7] = 2; k[8] = 1; + k[0] = 10; k[1] = 20; k[2] = 10; + k[3] = 20; k[4] = 40; k[5] = 20; + k[6] = 10; k[7] = 20; k[8] = 10; *scale = 1./16.; break; @@ -184,6 +184,7 @@ static void setupConvolution() GLint *kernel = (GLint*)malloc(sizeof(GLint) * 9); GLfloat scale; GLfloat *vecKer = (GLfloat*)malloc(sizeof(GLfloat) * 9 * 4); + GLfloat *kerScale = (GLfloat*)malloc(sizeof(GLfloat) * 9 * 4); GLuint loc; GLuint i; GLfloat baseColor[4]; @@ -193,6 +194,14 @@ static void setupConvolution() baseColor[3] = 0; fillConvolution(kernel, &scale, baseColor); + + for (i = 0; i < 9; ++i) { + kerScale[i*4 + 0] = 01.f / kernel[i]; + kerScale[i*4 + 1] = 0; + kerScale[i*4 + 2] = 0; + kerScale[i*4 + 3] = 01.f / kernel[i]; + } + /*vector of 4*/ for (i = 0; i < 9; ++i) { vecKer[i*4 + 0] = kernel[i]; @@ -203,6 +212,10 @@ static void setupConvolution() loc = glGetUniformLocationARB(program, "KernelValue"); glUniform4fv(loc, 9, vecKer); + loc = glGetUniformLocationARB(program, "KernelScale"); + glUniform4fv(loc, 9, kerScale); + loc = glGetUniformLocationARB(program, "KernelCount"); + glUniform1i(loc, 9); loc = glGetUniformLocationARB(program, "ScaleFactor"); glUniform4f(loc, scale, scale, scale, scale); loc = glGetUniformLocationARB(program, "BaseColor"); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 1c6c65e..bb48cd5 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -229,12 +229,12 @@ typedef enum GEOM_ATTRIB_COLOR1 = 2, GEOM_ATTRIB_SECONDARY_COLOR0 = 3, GEOM_ATTRIB_SECONDARY_COLOR1 = 4, - GEOM_ATTRIB_TEX_COORD = 5, - GEOM_ATTRIB_FOG_FRAG_COORD = 6, - GEOM_ATTRIB_POSITION = 7, - GEOM_ATTRIB_POINT_SIZE = 8, - GEOM_ATTRIB_CLIP_VERTEX = 9, - GEOM_ATTRIB_PRIMITIVE_ID = 10, + GEOM_ATTRIB_FOG_FRAG_COORD = 5, + GEOM_ATTRIB_POSITION = 6, + GEOM_ATTRIB_POINT_SIZE = 7, + GEOM_ATTRIB_CLIP_VERTEX = 8, + GEOM_ATTRIB_PRIMITIVE_ID = 9, + GEOM_ATTRIB_TEX_COORD = 10, GEOM_ATTRIB_VAR0 = 16, GEOM_ATTRIB_MAX = (GEOM_ATTRIB_VAR0 + MAX_VARYING) diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index e95ffa0..71cc252 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -64,8 +64,9 @@ struct translated_vertex_program { struct st_vertex_program *master; - /** The fragment shader "signature" this vertex shader is meant for: */ - GLbitfield frag_inputs; + /** The fragment/geometry shader "signature" this vertex + * shader is meant for: */ + GLbitfield linked_inputs; /** Compared against master vertex program's serialNo: */ GLuint serialNo; @@ -81,6 +82,27 @@ struct translated_vertex_program struct translated_vertex_program *next; /**< next in linked list */ }; +struct translated_geometry_program +{ + struct st_geometry_program *master; + + /** The fragment shader "signature" this vertex + * shader is meant for: */ + GLbitfield frag_inputs; + + /** Compared against master vertex program's serialNo: */ + GLuint serialNo; + + /** Maps VERT_RESULT_x to slot */ + GLuint output_to_slot[VERT_RESULT_MAX]; + ubyte output_to_semantic_name[VERT_RESULT_MAX]; + ubyte output_to_semantic_index[VERT_RESULT_MAX]; + + /** Pointer to the translated vertex program */ + struct st_geometry_program *gp; + + struct translated_geometry_program *next; /**< next in linked list */ +}; /** @@ -114,6 +136,74 @@ vp_out_to_fp_in(GLuint vertResult) } } +/** + * Given a geometry program output attribute, return the corresponding + * fragment program input attribute. + * \return -1 for geometry outputs that have no corresponding fragment input + */ +static GLint +gp_out_to_fp_in(GLuint geomResult) +{ + if (geomResult >= GEOM_RESULT_TEX0 && + geomResult < GEOM_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) + return FRAG_ATTRIB_TEX0 + (geomResult - GEOM_RESULT_TEX0); + + if (geomResult >= GEOM_RESULT_VAR0 && + geomResult < GEOM_RESULT_VAR0 + MAX_VARYING - 2) + return FRAG_ATTRIB_VAR0 + (geomResult - GEOM_RESULT_VAR0); + + switch (geomResult) { + case GEOM_RESULT_POS: + return FRAG_ATTRIB_WPOS; + case GEOM_RESULT_COL0: + return FRAG_ATTRIB_COL0; + case GEOM_RESULT_COL1: + return FRAG_ATTRIB_COL1; + case GEOM_RESULT_FOGC: + return FRAG_ATTRIB_FOGC; + default: + /* Back-face colors, primitive id, etc */ + return -1; + } +} + +/** + * Given a vertex program output attribute, return the corresponding + * geometry program input attribute. + * \return -1 for vertex outputs that have no corresponding geometry input + */ +static GLint +vp_out_to_gp_in(GLuint vertResult) +{ + if (vertResult >= VERT_RESULT_TEX0 && + vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) + return GEOM_ATTRIB_TEX_COORD; + + if (vertResult >= VERT_RESULT_VAR0 && + vertResult < VERT_RESULT_VAR0 + MAX_VARYING) + return GEOM_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0); + + switch (vertResult) { + case VERT_RESULT_HPOS: + return GEOM_ATTRIB_POSITION; + case VERT_RESULT_COL0: + return GEOM_ATTRIB_COLOR0; + case VERT_RESULT_COL1: + return GEOM_ATTRIB_COLOR1; + case VERT_RESULT_FOGC: + return GEOM_ATTRIB_FOG_FRAG_COORD; + case VERT_RESULT_PSIZ: + return GEOM_ATTRIB_POINT_SIZE; + case VERT_RESULT_BFC0: + return GEOM_ATTRIB_SECONDARY_COLOR0; + case VERT_RESULT_BFC1: + return GEOM_ATTRIB_SECONDARY_COLOR1; + default: + /* edge flags, etc */ + return -1; + } +} + /** * Find a translated vertex program that corresponds to stvp and @@ -128,11 +218,14 @@ find_translated_vp(struct st_context *st, { static const GLuint UNUSED = ~0; struct translated_vertex_program *xvp; + struct translated_geometry_program *xgp; const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; - GLbitfield geomInputsRead = 0; + GLbitfield geomInputsRead = 0, linkedInputs = fragInputsRead; - if (stgp) + if (stgp) { geomInputsRead = stgp->Base.Base.InputsRead; + linkedInputs = geomInputsRead; + } /* * Translate fragment program if needed. @@ -157,44 +250,187 @@ find_translated_vp(struct st_context *st, st_translate_fragment_program(st, stfp, stfp->input_to_slot); } - if (stgp && !stgp->state.shader.tokens) { - GLuint inAttr, numIn = 0; + /* See if we've got a translated geometry program whose outputs match + * the fragment program's inputs. + * XXX This could be a hash lookup, using InputsRead as the key. + */ + if (stgp) { + for (xgp = stfp->geometry_programs; xgp; xgp = xgp->next) { + if (xgp->master == stgp && xgp->frag_inputs == fragInputsRead) + break; + } + /* No? Allocate translated gp object now */ + if (!xgp) { + xgp = ST_CALLOC_STRUCT(translated_geometry_program); + xgp->frag_inputs = fragInputsRead; + xgp->master = stgp; + + xgp->next = stfp->geometry_programs; + stfp->geometry_programs = xgp; + } - for (inAttr = 0; inAttr < GEOM_ATTRIB_MAX; inAttr++) { - if (geomInputsRead & (1 << inAttr)) { - stgp->input_to_slot[inAttr] = numIn; - numIn++; + if (!stgp->state.shader.tokens) { + GLuint inAttr, numIn = 0; + + for (inAttr = 0; inAttr < GEOM_ATTRIB_MAX; inAttr++) { + if (geomInputsRead & (1 << inAttr)) { + stgp->input_to_slot[inAttr] = numIn; + numIn++; + } + else { + stgp->input_to_slot[inAttr] = UNUSED; + } } - else { - stgp->input_to_slot[inAttr] = UNUSED; + + stgp->num_input_slots = numIn; + assert(stgp->Base.Base.NumInstructions > 1); + + if (xgp->serialNo != stgp->serialNo) { + GLuint outAttr; + const GLbitfield outputsWritten = stgp->Base.Base.OutputsWritten; + GLuint numGpOuts = 0; + GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; + GLbitfield usedGenerics = 0x0; + GLbitfield usedOutputSlots = 0x0; + + /* Compute mapping of geometry program outputs to slots, which depends + * on the fragment program's input->slot mapping. + */ + for (outAttr = 0; outAttr < GEOM_RESULT_MAX; outAttr++) { + /* set defaults: */ + xgp->output_to_slot[outAttr] = UNUSED; + xgp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; + xgp->output_to_semantic_index[outAttr] = 99; + + if (outAttr == GEOM_RESULT_POS) { + /* always put xformed position into slot zero */ + GLuint slot = 0; + xgp->output_to_slot[GEOM_RESULT_POS] = slot; + xgp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; + xgp->output_to_semantic_index[outAttr] = 0; + numGpOuts++; + usedOutputSlots |= (1 << slot); + } + else if (outputsWritten & (1 << outAttr)) { + /* see if the frag prog wants this geom output */ + GLint fpInAttrib = gp_out_to_fp_in(outAttr); + if (fpInAttrib >= 0) { + GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; + if (fpInSlot != ~0) { + /* match this gp output to the fp input */ + GLuint gpOutSlot = stfp->input_map[fpInSlot]; + xgp->output_to_slot[outAttr] = gpOutSlot; + xgp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; + xgp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; + numGpOuts++; + usedOutputSlots |= (1 << gpOutSlot); + } + else { +#if 0 /*debug*/ + printf("GP output %d not used by FP\n", outAttr); +#endif + } + } + else if (outAttr == GEOM_RESULT_PSIZ) + emitPntSize = GL_TRUE; + else if (outAttr == GEOM_RESULT_SCOL0) + emitBFC0 = GL_TRUE; + else if (outAttr == GEOM_RESULT_SCOL1) + emitBFC1 = GL_TRUE; + } +#if 0 /*debug*/ + printf("assign gp output_to_slot[%d] = %d\n", outAttr, + xgp->output_to_slot[outAttr]); +#endif + } + + /* must do these last */ + if (emitPntSize) { + GLuint slot = numGpOuts++; + xgp->output_to_slot[GEOM_RESULT_PSIZ] = slot; + xgp->output_to_semantic_name[GEOM_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; + xgp->output_to_semantic_index[GEOM_RESULT_PSIZ] = 0; + usedOutputSlots |= (1 << slot); + } + if (emitBFC0) { + GLuint slot = numGpOuts++; + xgp->output_to_slot[GEOM_RESULT_SCOL0] = slot; + xgp->output_to_semantic_name[GEOM_RESULT_SCOL0] = TGSI_SEMANTIC_COLOR; + xgp->output_to_semantic_index[GEOM_RESULT_SCOL0] = 0; + usedOutputSlots |= (1 << slot); + } + if (emitBFC1) { + GLuint slot = numGpOuts++; + xgp->output_to_slot[GEOM_RESULT_SCOL1] = slot; + xgp->output_to_semantic_name[GEOM_RESULT_SCOL1] = TGSI_SEMANTIC_COLOR; + xgp->output_to_semantic_index[GEOM_RESULT_SCOL1] = 1; + usedOutputSlots |= (1 << slot); + } + + /* build usedGenerics mask */ + usedGenerics = 0x0; + for (outAttr = 0; outAttr < GEOM_RESULT_MAX; outAttr++) { + if (xgp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { + usedGenerics |= (1 << xgp->output_to_semantic_index[outAttr]); + } + } + + /* For each vertex geometry output that doesn't match up to a fragment + * program input, map the geometry program output to a free slot and + * free generic attribute. + */ + for (outAttr = 0; outAttr < GEOM_RESULT_MAX; outAttr++) { + if (outputsWritten & (1 << outAttr)) { + if (xgp->output_to_slot[outAttr] == UNUSED) { + GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; + GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; + usedGenerics |= (1 << freeGeneric); + usedOutputSlots |= (1 << freeSlot); + xgp->output_to_slot[outAttr] = freeSlot; + xgp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; + xgp->output_to_semantic_index[outAttr] = freeGeneric; + } + } + +#if 0 /*debug*/ + printf("gp output_to_slot[%d] = %d\n", outAttr, + xgp->output_to_slot[outAttr]); +#endif + } } - } - stgp->num_input_slots = numIn; + st_translate_geometry_program(st, stgp, stgp->input_to_slot, + xgp->output_to_slot, + xgp->output_to_semantic_name, + xgp->output_to_semantic_index); - assert(stgp->Base.Base.NumInstructions > 1); + xgp->gp = stgp; - st_translate_geometry_program(st, stgp, stgp->input_to_slot); + /* translated GP is up to date now */ + xgp->serialNo = stgp->serialNo; + } } - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. + * the fragment or geometry program's inputs. * XXX This could be a hash lookup, using InputsRead as the key. */ - for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { - if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { +#define LP_FUNC(FP, GP) ((stgp)?GP:FP) +#define LP(X) ((stgp)?stgp->X:stfp->X) +#define LP_SET(X, Y) do { if (stgp) stgp->X = Y; else stfp->X = Y; } while(0) + + for (xvp = LP(vertex_programs); xvp; xvp = xvp->next) { + if (xvp->master == stvp && xvp->linked_inputs == linkedInputs) break; - } } /* No? Allocate translated vp object now */ if (!xvp) { xvp = ST_CALLOC_STRUCT(translated_vertex_program); - xvp->frag_inputs = fragInputsRead; + xvp->linked_inputs = linkedInputs; xvp->master = stvp; - xvp->next = stfp->vertex_programs; - stfp->vertex_programs = xvp; + xvp->next = LP(vertex_programs); + LP_SET(vertex_programs, xvp); } /* See if we need to translate vertex program to TGSI form */ @@ -226,21 +462,21 @@ find_translated_vp(struct st_context *st, } else if (outputsWritten & (1 << outAttr)) { /* see if the frag prog wants this vert output */ - GLint fpInAttrib = vp_out_to_fp_in(outAttr); - if (fpInAttrib >= 0) { - GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; - if (fpInSlot != ~0) { - /* match this vp output to the fp input */ - GLuint vpOutSlot = stfp->input_map[fpInSlot]; + GLint lpInAttrib = LP_FUNC(vp_out_to_fp_in(outAttr), vp_out_to_gp_in(outAttr)); + if (lpInAttrib >= 0) { + GLuint lpInSlot = LP(input_to_slot[lpInAttrib]); + if (lpInSlot != ~0) { + /* match this vp output to the lp input */ + GLuint vpOutSlot = LP(input_map[lpInSlot]); xvp->output_to_slot[outAttr] = vpOutSlot; - xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; - xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; + xvp->output_to_semantic_name[outAttr] = LP(input_semantic_name[lpInSlot]); + xvp->output_to_semantic_index[outAttr] = LP(input_semantic_index[lpInSlot]); numVpOuts++; usedOutputSlots |= (1 << vpOutSlot); } else { #if 0 /*debug*/ - printf("VP output %d not used by FP\n", outAttr); + printf("VP output %d not used by LP\n", outAttr); #endif } } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 5b646ba..f93a832 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -581,15 +581,16 @@ st_translate_fragment_program(struct st_context *st, void st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, - const GLuint inputMapping[]) + const GLuint inputMapping[], + const GLuint outputMapping[], + const ubyte *outputSemanticName, + const ubyte *outputSemanticIndex) { struct pipe_context *pipe = st->pipe; struct tgsi_token *tokens; - GLuint *outputMapping; GLuint defaultInputMapping[GEOM_ATTRIB_MAX]; GLuint defaultOutputMapping[GEOM_RESULT_MAX]; struct pipe_geometry_shader_state gs; - GLuint interpMode[16]; /* XXX size? */ GLuint attr; const GLbitfield inputsRead = stgp->Base.Base.InputsRead; GLuint vslot = 0; @@ -631,60 +632,69 @@ st_translate_geometry_program(struct st_context *st, if (inputsRead & (1 << attr)) { const GLuint slot = gs_num_inputs; - defaultInputMapping[attr] = slot; + gs_num_inputs++; - stgp->input_map[slot] = vslot++; + defaultInputMapping[attr] = slot; - gs_num_inputs++; + stgp->input_map[slot] = vslot; + stgp->input_to_index[attr] = vslot; + stgp->index_to_input[vslot] = attr; + ++vslot; switch (attr) { case GEOM_ATTRIB_VERTICES: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_VERTICES; stgp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case GEOM_ATTRIB_PRIMITIVE_ID: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; stgp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case GEOM_ATTRIB_POSITION: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stgp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case GEOM_ATTRIB_COLOR0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case GEOM_ATTRIB_COLOR1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 1; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case GEOM_ATTRIB_FOG_FRAG_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stgp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case GEOM_ATTRIB_TEX_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case GEOM_ATTRIB_VAR0: /* fall-through */ default: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; } input_flags[slot] = stgp->Base.Base.InputFlags[attr]; } } +#if 1 + if (outputMapping && outputSemanticName) { + printf("GEOM_RESULT written out_slot semantic_name semantic_index\n"); + for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { + printf(" %-2d %c %3d %2d %2d\n", + attr, + ((stgp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '), + outputMapping[attr], + outputSemanticName[attr], + outputSemanticIndex[attr]); + } + } +#endif + /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; @@ -706,10 +716,15 @@ st_translate_geometry_program(struct st_context *st, * Use the generic semantic indexes from there, instead of * guessing below. */ - - slot = gs_num_outputs; - gs_num_outputs++; - defaultOutputMapping[attr] = slot; + if (outputMapping) { + slot = outputMapping[attr]; + assert(slot != ~0); + } + else { + slot = gs_num_outputs; + gs_num_outputs++; + defaultOutputMapping[attr] = slot; + } switch (attr) { case GEOM_RESULT_POS: @@ -753,18 +768,59 @@ st_translate_geometry_program(struct st_context *st, case GEOM_RESULT_VAR0: /* fall-through */ default: - /* use default semantic info */ - gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - gs_output_semantic_index[slot] = num_generic++; + assert(slot < Elements(gs_output_semantic_name)); + if (outputSemanticName) { + /* use provided semantic into */ + assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); + gs_output_semantic_name[slot] = outputSemanticName[attr]; + gs_output_semantic_index[slot] = outputSemanticIndex[attr]; + } + else { + /* use default semantic info */ + gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + gs_output_semantic_index[slot] = num_generic++; + } } + assert(slot < Elements(output_flags)); output_flags[slot] = stgp->Base.Base.OutputFlags[attr]; } } assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); - outputMapping = defaultOutputMapping; + if (outputMapping) { + /* find max output slot referenced to compute gs_num_outputs */ + GLuint maxSlot = 0; + for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { + if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) + maxSlot = outputMapping[attr]; + } + gs_num_outputs = maxSlot + 1; + } + else { + outputMapping = defaultOutputMapping; + } + +#if 1 /* debug */ + { + GLuint i; + printf("outputMapping? %d\n", outputMapping ? 1 : 0); + if (outputMapping) { + printf("attr -> slot\n"); + for (i = 0; i < 16; i++) { + printf(" %2d %3d\n", i, outputMapping[i]); + } + } + printf("slot sem_name sem_index\n"); + for (i = 0; i < gs_num_outputs; i++) { + printf(" %2d %d %d\n", + i, + gs_output_semantic_name[i], + gs_output_semantic_index[i]); + } + } +#endif /* free old shader state, if any */ if (stgp->state.shader.tokens) { diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 2f986ea..595733d 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -42,6 +42,7 @@ struct cso_fragment_shader; struct cso_vertex_shader; struct translated_vertex_program; +struct translated_geometry_program; /** @@ -55,7 +56,7 @@ struct st_fragment_program GLuint input_to_slot[FRAG_ATTRIB_MAX]; /**< Maps FRAG_ATTRIB_x to slot */ GLuint num_input_slots; - /** map FP input back to VP output */ + /** map FP input back to VP/GP output */ GLuint input_map[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; @@ -70,6 +71,7 @@ struct st_fragment_program * outputs match this fragment program's inputs. */ struct translated_vertex_program *vertex_programs; + struct translated_geometry_program *geometry_programs; /** Program prefixed with glBitmap prologue */ struct st_fragment_program *bitmap_program; @@ -110,9 +112,12 @@ struct st_geometry_program struct gl_geometry_program Base; /**< The Mesa geometry program */ GLuint serialNo; - /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ + /** map GP input back to VP output */ + GLuint input_map[PIPE_MAX_SHADER_INPUTS]; + + /** maps a Mesa GEOM_ATTRIB_x to a packed TGSI input index */ GLuint input_to_index[GEOM_ATTRIB_MAX]; - /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */ + /** maps a TGSI input index back to a Mesa GEOM_ATTRIB_x */ GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; GLuint num_inputs; @@ -120,12 +125,10 @@ struct st_geometry_program GLuint input_to_slot[GEOM_ATTRIB_MAX]; /**< Maps GEOM_ATTRIB_x to slot */ GLuint num_input_slots; - /** map FP input back to VP output */ - GLuint input_map[PIPE_MAX_SHADER_INPUTS]; - ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + struct translated_vertex_program *vertex_programs; struct pipe_geometry_shader_state state; void *driver_shader; @@ -192,10 +195,14 @@ st_translate_fragment_program(struct st_context *st, struct st_fragment_program *fp, const GLuint inputMapping[]); + extern void st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *fp, - const GLuint inputMapping[]); + struct st_geometry_program *stgp, + const GLuint inputMapping[], + const GLuint outputMapping[], + const ubyte *outputSemanticName, + const ubyte *outputSemanticIndex); extern void st_translate_vertex_program(struct st_context *st, _______________________________________________ mesa-commit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-commit
