Merge commit 'origin/st-shader-varients'

Conflicts:
	src/mesa/state_tracker/st_atom_shader.c
	src/mesa/state_tracker/st_program.c
This commit is contained in:
Roland Scheidegger 2009-11-26 01:15:25 +01:00
commit 4dcdf3b9c6
14 changed files with 331 additions and 655 deletions

View File

@ -46,7 +46,8 @@ static const struct st_tracked_state *atoms[] =
&st_update_clip, &st_update_clip,
&st_finalize_textures, &st_finalize_textures,
&st_update_shader, &st_update_fp,
&st_update_vp,
&st_update_rasterizer, &st_update_rasterizer,
&st_update_polygon_stipple, &st_update_polygon_stipple,

View File

@ -47,7 +47,8 @@ void st_validate_state( struct st_context *st );
extern const struct st_tracked_state st_update_framebuffer; extern const struct st_tracked_state st_update_framebuffer;
extern const struct st_tracked_state st_update_clip; extern const struct st_tracked_state st_update_clip;
extern const struct st_tracked_state st_update_depth_stencil_alpha; extern const struct st_tracked_state st_update_depth_stencil_alpha;
extern const struct st_tracked_state st_update_shader; extern const struct st_tracked_state st_update_fp;
extern const struct st_tracked_state st_update_vp;
extern const struct st_tracked_state st_update_rasterizer; extern const struct st_tracked_state st_update_rasterizer;
extern const struct st_tracked_state st_update_polygon_stipple; extern const struct st_tracked_state st_update_polygon_stipple;
extern const struct st_tracked_state st_update_viewport; extern const struct st_tracked_state st_update_viewport;

View File

@ -56,82 +56,18 @@
#include "st_mesa_to_tgsi.h" #include "st_mesa_to_tgsi.h"
/**
* This represents a vertex program, especially translated to match
* the inputs of a particular fragment shader.
/*
* Translate fragment program if needed.
*/ */
struct translated_vertex_program static void
translate_fp(struct st_context *st,
struct st_fragment_program *stfp)
{ {
struct st_vertex_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_vertex_program *vp;
struct translated_vertex_program *next; /**< next in linked list */
};
/**
* Given a vertex program output attribute, return the corresponding
* fragment program input attribute.
* \return -1 for vertex outputs that have no corresponding fragment input
*/
static GLint
vp_out_to_fp_in(GLuint vertResult)
{
if (vertResult >= VERT_RESULT_TEX0 &&
vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
if (vertResult >= VERT_RESULT_VAR0 &&
vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
switch (vertResult) {
case VERT_RESULT_HPOS:
return FRAG_ATTRIB_WPOS;
case VERT_RESULT_COL0:
return FRAG_ATTRIB_COL0;
case VERT_RESULT_COL1:
return FRAG_ATTRIB_COL1;
case VERT_RESULT_FOGC:
return FRAG_ATTRIB_FOGC;
default:
/* Back-face colors, edge flags, etc */
return -1;
}
}
/**
* Find a translated vertex program that corresponds to stvp and
* has outputs matched to stfp's inputs.
* This performs vertex and fragment translation (to TGSI) when needed.
*/
static struct translated_vertex_program *
find_translated_vp(struct st_context *st,
struct st_vertex_program *stvp,
struct st_fragment_program *stfp)
{
static const GLuint UNUSED = ~0;
struct translated_vertex_program *xvp;
const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
/*
* Translate fragment program if needed.
*/
if (!stfp->state.tokens) { if (!stfp->state.tokens) {
GLuint inAttr, numIn = 0; GLuint inAttr, numIn = 0;
@ -141,7 +77,7 @@ find_translated_vp(struct st_context *st,
numIn++; numIn++;
} }
else { else {
stfp->input_to_slot[inAttr] = UNUSED; stfp->input_to_slot[inAttr] = -1;
} }
} }
@ -151,170 +87,63 @@ find_translated_vp(struct st_context *st,
st_translate_fragment_program(st, stfp, stfp->input_to_slot); st_translate_fragment_program(st, stfp, stfp->input_to_slot);
} }
}
/**
* Find a translated vertex program that corresponds to stvp and
* has outputs matched to stfp's inputs.
* This performs vertex and fragment translation (to TGSI) when needed.
*/
static struct st_vp_varient *
find_translated_vp(struct st_context *st,
struct st_vertex_program *stvp )
{
struct st_vp_varient *vpv;
struct st_vp_varient_key key;
/* Nothing in our key yet. This will change:
*/
memset(&key, 0, sizeof key);
key.dummy = 0;
/* Do we need to throw away old translations after a change in the
* GL program string?
*/
if (stvp->serialNo != stvp->lastSerialNo) {
/* These may have changed if the program string changed.
*/
st_prepare_vertex_program( st, stvp );
/* We are now up-to-date:
*/
stvp->lastSerialNo = stvp->serialNo;
}
/* See if we've got a translated vertex program whose outputs match /* See if we've got a translated vertex program whose outputs match
* the fragment program's inputs. * the fragment program's inputs.
* XXX This could be a hash lookup, using InputsRead as the key.
*/ */
for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { for (vpv = stvp->varients; vpv; vpv = vpv->next) {
if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { if (memcmp(&vpv->key, &key, sizeof key) == 0) {
break; break;
} }
} }
/* No? Allocate translated vp object now */ /* No? Perform new translation here. */
if (!xvp) { if (!vpv) {
xvp = ST_CALLOC_STRUCT(translated_vertex_program); vpv = st_translate_vertex_program(st, stvp, &key);
xvp->frag_inputs = fragInputsRead; if (!vpv)
xvp->master = stvp; return NULL;
xvp->next = stfp->vertex_programs; vpv->next = stvp->varients;
stfp->vertex_programs = xvp; stvp->varients = vpv;
} }
/* See if we need to translate vertex program to TGSI form */ return vpv;
if (xvp->serialNo != stvp->serialNo) {
GLuint outAttr;
const GLbitfield64 outputsWritten = stvp->Base.Base.OutputsWritten;
GLuint numVpOuts = 0;
GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
GLbitfield usedGenerics = 0x0;
GLbitfield usedOutputSlots = 0x0;
/* Compute mapping of vertex program outputs to slots, which depends
* on the fragment program's input->slot mapping.
*/
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
/* set defaults: */
xvp->output_to_slot[outAttr] = UNUSED;
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
xvp->output_to_semantic_index[outAttr] = 99;
if (outAttr == VERT_RESULT_HPOS) {
/* always put xformed position into slot zero */
GLuint slot = 0;
xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
xvp->output_to_semantic_index[outAttr] = 0;
numVpOuts++;
usedOutputSlots |= (1 << slot);
}
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];
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];
numVpOuts++;
usedOutputSlots |= (1 << vpOutSlot);
}
else {
#if 0 /*debug*/
printf("VP output %d not used by FP\n", outAttr);
#endif
}
}
else if (outAttr == VERT_RESULT_PSIZ)
emitPntSize = GL_TRUE;
else if (outAttr == VERT_RESULT_BFC0)
emitBFC0 = GL_TRUE;
else if (outAttr == VERT_RESULT_BFC1)
emitBFC1 = GL_TRUE;
}
#if 0 /*debug*/
printf("assign vp output_to_slot[%d] = %d\n", outAttr,
xvp->output_to_slot[outAttr]);
#endif
}
/* must do these last */
if (emitPntSize) {
GLuint slot = numVpOuts++;
xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
usedOutputSlots |= (1 << slot);
}
if (emitBFC0) {
GLuint slot = numVpOuts++;
xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
usedOutputSlots |= (1 << slot);
}
if (emitBFC1) {
GLuint slot = numVpOuts++;
xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
usedOutputSlots |= (1 << slot);
}
/* build usedGenerics mask */
usedGenerics = 0x0;
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
}
}
/* For each vertex program output that doesn't match up to a fragment
* program input, map the vertex program output to a free slot and
* free generic attribute.
*/
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (outputsWritten & (1 << outAttr)) {
if (xvp->output_to_slot[outAttr] == UNUSED) {
GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
usedGenerics |= (1 << freeGeneric);
usedOutputSlots |= (1 << freeSlot);
xvp->output_to_slot[outAttr] = freeSlot;
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
xvp->output_to_semantic_index[outAttr] = freeGeneric;
}
}
#if 0 /*debug*/
printf("vp output_to_slot[%d] = %d\n", outAttr,
xvp->output_to_slot[outAttr]);
#endif
}
assert(stvp->Base.Base.NumInstructions > 1);
st_translate_vertex_program(st, stvp, xvp->output_to_slot,
xvp->output_to_semantic_name,
xvp->output_to_semantic_index);
xvp->vp = stvp;
/* translated VP is up to date now */
xvp->serialNo = stvp->serialNo;
}
return xvp;
} }
void
st_free_translated_vertex_programs(struct st_context *st,
struct translated_vertex_program *xvp)
{
struct translated_vertex_program *next;
while (xvp) {
next = xvp->next;
_mesa_free(xvp);
xvp = next;
}
}
static void * static void *
@ -328,32 +157,19 @@ get_passthrough_fs(struct st_context *st)
return st->passthrough_fs; return st->passthrough_fs;
} }
static void static void
update_linkage( struct st_context *st ) update_fp( struct st_context *st )
{ {
struct st_vertex_program *stvp;
struct st_fragment_program *stfp; struct st_fragment_program *stfp;
struct translated_vertex_program *xvp;
/* find active shader and params -- Should be covered by
* ST_NEW_VERTEX_PROGRAM
*/
assert(st->ctx->VertexProgram._Current);
stvp = st_vertex_program(st->ctx->VertexProgram._Current);
assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
assert(st->ctx->FragmentProgram._Current); assert(st->ctx->FragmentProgram._Current);
stfp = st_fragment_program(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
xvp = find_translated_vp(st, stvp, stfp); translate_fp(st, stfp);
st_reference_vertprog(st, &st->vp, stvp);
st_reference_fragprog(st, &st->fp, stfp); st_reference_fragprog(st, &st->fp, stfp);
cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
if (st->missing_textures) { if (st->missing_textures) {
/* use a pass-through frag shader that uses no textures */ /* use a pass-through frag shader that uses no textures */
void *fs = get_passthrough_fs(st); void *fs = get_passthrough_fs(st);
@ -362,16 +178,48 @@ update_linkage( struct st_context *st )
else { else {
cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
} }
}
st->vertex_result_to_slot = xvp->output_to_slot; const struct st_tracked_state st_update_fp = {
"st_update_fp", /* name */
{ /* dirty */
0, /* mesa */
ST_NEW_FRAGMENT_PROGRAM /* st */
},
update_fp /* update */
};
static void
update_vp( struct st_context *st )
{
struct st_vertex_program *stvp;
/* find active shader and params -- Should be covered by
* ST_NEW_VERTEX_PROGRAM
*/
assert(st->ctx->VertexProgram._Current);
stvp = st_vertex_program(st->ctx->VertexProgram._Current);
assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
st->vp_varient = find_translated_vp(st, stvp);
st_reference_vertprog(st, &st->vp, stvp);
cso_set_vertex_shader_handle(st->cso_context,
st->vp_varient->driver_shader);
st->vertex_result_to_slot = stvp->result_to_output;
} }
const struct st_tracked_state st_update_shader = { const struct st_tracked_state st_update_vp = {
"st_update_shader", /* name */ "st_update_vp", /* name */
{ /* dirty */ { /* dirty */
0, /* mesa */ 0, /* mesa */
ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */ ST_NEW_VERTEX_PROGRAM /* st */
}, },
update_linkage /* update */ update_vp /* update */
}; };

View File

@ -169,11 +169,6 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
stfp = (struct st_fragment_program *) p; stfp = (struct st_fragment_program *) p;
stfp->Base.UsesKill = GL_TRUE; stfp->Base.UsesKill = GL_TRUE;
/* No need to send this incomplete program down to hardware:
*
* st_translate_fragment_program(ctx->st, stfp, NULL);
*/
return stfp; return stfp;
} }

View File

@ -60,6 +60,7 @@
#include "pipe/p_context.h" #include "pipe/p_context.h"
#include "pipe/p_defines.h" #include "pipe/p_defines.h"
#include "pipe/p_inlines.h" #include "pipe/p_inlines.h"
#include "tgsi/tgsi_ureg.h"
#include "util/u_tile.h" #include "util/u_tile.h"
#include "util/u_draw_quad.h" #include "util/u_draw_quad.h"
#include "util/u_math.h" #include "util/u_math.h"
@ -236,78 +237,41 @@ make_fragment_shader_z(struct st_context *st)
* Create a simple vertex shader that just passes through the * Create a simple vertex shader that just passes through the
* vertex position and texcoord (and optionally, color). * vertex position and texcoord (and optionally, color).
*/ */
static struct st_vertex_program * static void *
st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) st_make_passthrough_vertex_shader(struct st_context *st,
GLboolean passColor)
{ {
GLcontext *ctx = st->ctx; if (!st->drawpix.vert_shaders[passColor]) {
struct st_vertex_program *stvp; struct ureg_program *ureg =
struct gl_program *p; ureg_create( TGSI_PROCESSOR_VERTEX );
GLuint ic = 0;
if (st->drawpix.vert_shaders[passColor]) if (ureg == NULL)
return st->drawpix.vert_shaders[passColor]; return NULL;
/* /* MOV result.pos, vertex.pos; */
* Create shader now ureg_MOV(ureg,
*/ ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); ureg_DECL_vs_input( ureg, 0 ));
if (!p)
return NULL; /* MOV result.texcoord0, vertex.texcoord0; */
ureg_MOV(ureg,
ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ),
ureg_DECL_vs_input( ureg, 1 ));
if (passColor) {
/* MOV result.color0, vertex.color0; */
ureg_MOV(ureg,
ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
ureg_DECL_vs_input( ureg, 2 ));
}
if (passColor) ureg_END( ureg );
p->NumInstructions = 4;
else st->drawpix.vert_shaders[passColor] =
p->NumInstructions = 3; ureg_create_shader_and_destroy( ureg, st->pipe );
p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
if (!p->Instructions) {
ctx->Driver.DeleteProgram(ctx, p);
return NULL;
}
_mesa_init_instructions(p->Instructions, p->NumInstructions);
/* MOV result.pos, vertex.pos; */
p->Instructions[0].Opcode = OPCODE_MOV;
p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
/* MOV result.texcoord0, vertex.texcoord0; */
p->Instructions[1].Opcode = OPCODE_MOV;
p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
ic = 2;
if (passColor) {
/* MOV result.color0, vertex.color0; */
p->Instructions[ic].Opcode = OPCODE_MOV;
p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
ic++;
} }
/* END; */ return st->drawpix.vert_shaders[passColor];
p->Instructions[ic].Opcode = OPCODE_END;
ic++;
assert(ic == p->NumInstructions);
p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
(1 << VERT_RESULT_HPOS));
if (passColor) {
p->InputsRead |= VERT_BIT_COLOR0;
p->OutputsWritten |= (1 << VERT_RESULT_COL0);
}
stvp = (struct st_vertex_program *) p;
st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
st->drawpix.vert_shaders[passColor] = stvp;
return stvp;
} }
@ -539,8 +503,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
GLfloat zoomX, GLfloat zoomY, GLfloat zoomX, GLfloat zoomY,
struct pipe_texture *pt, struct pipe_texture *pt,
struct st_vertex_program *stvp, void *driver_vp,
struct st_fragment_program *stfp, void *driver_fp,
const GLfloat *color, const GLfloat *color,
GLboolean invertTex) GLboolean invertTex)
{ {
@ -575,10 +539,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
} }
/* fragment shader state: TEX lookup program */ /* fragment shader state: TEX lookup program */
cso_set_fragment_shader_handle(cso, stfp->driver_shader); cso_set_fragment_shader_handle(cso, driver_fp);
/* vertex shader state: position + texcoord pass-through */ /* vertex shader state: position + texcoord pass-through */
cso_set_vertex_shader_handle(cso, stvp->driver_shader); cso_set_vertex_shader_handle(cso, driver_vp);
/* texture sampling state: */ /* texture sampling state: */
@ -806,7 +770,7 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
{ {
struct st_fragment_program *stfp; struct st_fragment_program *stfp;
struct st_vertex_program *stvp; void *driver_vp;
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
struct pipe_surface *ps; struct pipe_surface *ps;
const GLfloat *color; const GLfloat *color;
@ -826,13 +790,13 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
if (format == GL_DEPTH_COMPONENT) { if (format == GL_DEPTH_COMPONENT) {
ps = st->state.framebuffer.zsbuf; ps = st->state.framebuffer.zsbuf;
stfp = make_fragment_shader_z(st); stfp = make_fragment_shader_z(st);
stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);
color = ctx->Current.RasterColor; color = ctx->Current.RasterColor;
} }
else { else {
ps = st->state.framebuffer.cbufs[0]; ps = st->state.framebuffer.cbufs[0];
stfp = combined_drawpix_fragment_program(ctx); stfp = combined_drawpix_fragment_program(ctx);
stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);
color = NULL; color = NULL;
} }
@ -843,7 +807,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
if (pt) { if (pt) {
draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
pt, stvp, stfp, color, GL_FALSE); pt,
driver_vp,
stfp->driver_shader,
color, GL_FALSE);
pipe_texture_reference(&pt, NULL); pipe_texture_reference(&pt, NULL);
} }
} }
@ -960,7 +927,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen; struct pipe_screen *screen = pipe->screen;
struct st_renderbuffer *rbRead; struct st_renderbuffer *rbRead;
struct st_vertex_program *stvp; void *driver_vp;
struct st_fragment_program *stfp; struct st_fragment_program *stfp;
struct pipe_texture *pt; struct pipe_texture *pt;
GLfloat *color; GLfloat *color;
@ -1009,14 +976,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
rbRead = st_get_color_read_renderbuffer(ctx); rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL; color = NULL;
stfp = combined_drawpix_fragment_program(ctx); stfp = combined_drawpix_fragment_program(ctx);
stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);
} }
else { else {
assert(type == GL_DEPTH); assert(type == GL_DEPTH);
rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
stfp = make_fragment_shader_z(st); stfp = make_fragment_shader_z(st);
stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);
} }
srcFormat = rbRead->texture->format; srcFormat = rbRead->texture->format;
@ -1148,7 +1115,10 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
/* draw textured quad */ /* draw textured quad */
draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
pt, stvp, stfp, color, GL_TRUE); pt,
driver_vp,
stfp->driver_shader,
color, GL_TRUE);
pipe_texture_reference(&pt, NULL); pipe_texture_reference(&pt, NULL);
} }

View File

@ -138,24 +138,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)
case GL_VERTEX_PROGRAM_ARB: case GL_VERTEX_PROGRAM_ARB:
{ {
struct st_vertex_program *stvp = (struct st_vertex_program *) prog; struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
st_vp_release_varients( st, stvp );
if (stvp->driver_shader) {
cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
stvp->driver_shader = NULL;
}
if (stvp->draw_shader) {
#if FEATURE_feedback || FEATURE_drawpix
/* this would only have been allocated for the RasterPos path */
draw_delete_vertex_shader(st->draw, stvp->draw_shader);
stvp->draw_shader = NULL;
#endif
}
if (stvp->state.tokens) {
st_free_tokens(stvp->state.tokens);
stvp->state.tokens = NULL;
}
} }
break; break;
case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_ARB:
@ -177,8 +160,6 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)
_mesa_reference_program(ctx, &prg, NULL); _mesa_reference_program(ctx, &prg, NULL);
stfp->bitmap_program = NULL; stfp->bitmap_program = NULL;
} }
st_free_translated_vertex_programs(st, stfp->vertex_programs);
} }
break; break;
default: default:
@ -219,8 +200,6 @@ static void st_program_string_notify( GLcontext *ctx,
stfp->state.tokens = NULL; stfp->state.tokens = NULL;
} }
stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
if (st->fp == stfp) if (st->fp == stfp)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
} }
@ -229,25 +208,7 @@ static void st_program_string_notify( GLcontext *ctx,
stvp->serialNo++; stvp->serialNo++;
if (stvp->driver_shader) { st_vp_release_varients( st, stvp );
cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
stvp->driver_shader = NULL;
}
if (stvp->draw_shader) {
#if FEATURE_feedback || FEATURE_drawpix
/* this would only have been allocated for the RasterPos path */
draw_delete_vertex_shader(st->draw, stvp->draw_shader);
stvp->draw_shader = NULL;
#endif
}
if (stvp->state.tokens) {
st_free_tokens(stvp->state.tokens);
stvp->state.tokens = NULL;
}
stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
if (st->vp == stvp) if (st->vp == stvp)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM; st->dirty.st |= ST_NEW_VERTEX_PROGRAM;

View File

@ -127,6 +127,8 @@ struct st_context
struct st_vertex_program *vp; /**< Currently bound vertex program */ struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */ struct st_fragment_program *fp; /**< Currently bound fragment program */
struct st_vp_varient *vp_varient;
struct gl_texture_object *default_texture; struct gl_texture_object *default_texture;
struct { struct {

View File

@ -86,7 +86,8 @@ st_print_current(void)
} }
#endif #endif
tgsi_dump( st->vp->state.tokens, 0 ); if (st->vp->varients)
tgsi_dump( st->vp->varients[0].state.tokens, 0 );
if (st->vp->Base.Base.Parameters) if (st->vp->Base.Base.Parameters)
_mesa_print_parameter_list(st->vp->Base.Base.Parameters); _mesa_print_parameter_list(st->vp->Base.Base.Parameters);

View File

@ -573,7 +573,7 @@ st_draw_vbo(GLcontext *ctx,
/* must get these after state validation! */ /* must get these after state validation! */
vp = ctx->st->vp; vp = ctx->st->vp;
vs = &ctx->st->vp->state; vs = &ctx->st->vp_varient->state;
#if 0 #if 0
if (MESA_VERBOSE & VERBOSE_GLSL) { if (MESA_VERBOSE & VERBOSE_GLSL) {

View File

@ -120,10 +120,10 @@ st_feedback_draw_vbo(GLcontext *ctx,
/* must get these after state validation! */ /* must get these after state validation! */
vp = ctx->st->vp; vp = ctx->st->vp;
vs = &st->vp->state; vs = &st->vp_varient->state;
if (!st->vp->draw_shader) { if (!st->vp_varient->draw_shader) {
st->vp->draw_shader = draw_create_vertex_shader(draw, vs); st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs);
} }
/* /*
@ -136,7 +136,7 @@ st_feedback_draw_vbo(GLcontext *ctx,
draw_set_viewport_state(draw, &st->state.viewport); draw_set_viewport_state(draw, &st->state.viewport);
draw_set_clip_state(draw, &st->state.clip); draw_set_clip_state(draw, &st->state.clip);
draw_set_rasterizer_state(draw, &st->state.rasterizer); draw_set_rasterizer_state(draw, &st->state.rasterizer);
draw_bind_vertex_shader(draw, st->vp->draw_shader); draw_bind_vertex_shader(draw, st->vp_varient->draw_shader);
set_feedback_vertex_format(ctx); set_feedback_vertex_format(ctx);
/* loop over TGSI shader inputs to determine vertex buffer /* loop over TGSI shader inputs to determine vertex buffer

View File

@ -704,12 +704,10 @@ st_translate_mesa_program(
const ubyte inputSemanticName[], const ubyte inputSemanticName[],
const ubyte inputSemanticIndex[], const ubyte inputSemanticIndex[],
const GLuint interpMode[], const GLuint interpMode[],
const GLbitfield inputFlags[],
GLuint numOutputs, GLuint numOutputs,
const GLuint outputMapping[], const GLuint outputMapping[],
const ubyte outputSemanticName[], const ubyte outputSemanticName[],
const ubyte outputSemanticIndex[], const ubyte outputSemanticIndex[] )
const GLbitfield outputFlags[] )
{ {
struct st_translate translate, *t; struct st_translate translate, *t;
struct ureg_program *ureg; struct ureg_program *ureg;

View File

@ -49,12 +49,10 @@ st_translate_mesa_program(
const ubyte inputSemanticName[], const ubyte inputSemanticName[],
const ubyte inputSemanticIndex[], const ubyte inputSemanticIndex[],
const GLuint interpMode[], const GLuint interpMode[],
const GLbitfield inputFlags[],
GLuint numOutputs, GLuint numOutputs,
const GLuint outputMapping[], const GLuint outputMapping[],
const ubyte outputSemanticName[], const ubyte outputSemanticName[],
const ubyte outputSemanticIndex[], const ubyte outputSemanticIndex[] );
const GLbitfield outputFlags[] );
void void
st_free_tokens(const struct tgsi_token *tokens); st_free_tokens(const struct tgsi_token *tokens);

View File

@ -49,6 +49,36 @@
#include "st_mesa_to_tgsi.h" #include "st_mesa_to_tgsi.h"
#include "cso_cache/cso_context.h" #include "cso_cache/cso_context.h"
/* Clean out any old compilations:
*/
void
st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp )
{
struct st_vp_varient *vpv;
for (vpv = stvp->varients; vpv; ) {
struct st_vp_varient *next = vpv->next;
if (vpv->driver_shader)
cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
if (vpv->draw_shader)
draw_delete_vertex_shader( st->draw, vpv->draw_shader );
if (vpv->state.tokens)
st_free_tokens(vpv->state.tokens);
FREE( vpv );
vpv = next;
}
stvp->varients = NULL;
}
/** /**
* Translate a Mesa vertex shader into a TGSI shader. * Translate a Mesa vertex shader into a TGSI shader.
@ -58,31 +88,13 @@
* \return pointer to cached pipe_shader object. * \return pointer to cached pipe_shader object.
*/ */
void void
st_translate_vertex_program(struct st_context *st, st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *stvp, struct st_vertex_program *stvp)
const GLuint outputMapping[],
const ubyte *outputSemanticName,
const ubyte *outputSemanticIndex)
{ {
struct pipe_context *pipe = st->pipe; GLuint attr;
GLuint defaultOutputMapping[VERT_RESULT_MAX];
GLuint attr, i;
GLuint num_generic = 0;
ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; stvp->num_inputs = 0;
ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; stvp->num_outputs = 0;
uint vs_num_inputs = 0;
ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
uint vs_num_outputs = 0;
GLbitfield input_flags[MAX_PROGRAM_INPUTS];
GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
/*memset(&vs, 0, sizeof(vs));*/
memset(input_flags, 0, sizeof(input_flags));
memset(output_flags, 0, sizeof(output_flags));
if (stvp->Base.IsPositionInvariant) if (stvp->Base.IsPositionInvariant)
_mesa_insert_mvp_code(st->ctx, &stvp->Base); _mesa_insert_mvp_code(st->ctx, &stvp->Base);
@ -93,162 +105,56 @@ st_translate_vertex_program(struct st_context *st,
*/ */
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if (stvp->Base.Base.InputsRead & (1 << attr)) { if (stvp->Base.Base.InputsRead & (1 << attr)) {
const GLuint slot = vs_num_inputs; stvp->input_to_index[attr] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = attr;
vs_num_inputs++; stvp->num_inputs++;
stvp->input_to_index[attr] = slot;
stvp->index_to_input[slot] = attr;
switch (attr) {
case VERT_ATTRIB_POS:
vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
vs_input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_WEIGHT:
/* fall-through */
case VERT_ATTRIB_NORMAL:
/* just label as a generic */
vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
vs_input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_COLOR0:
vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
vs_input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_COLOR1:
vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
vs_input_semantic_index[slot] = 1;
break;
case VERT_ATTRIB_FOG:
vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
vs_input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_POINT_SIZE:
vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
vs_input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_TEX0:
case VERT_ATTRIB_TEX1:
case VERT_ATTRIB_TEX2:
case VERT_ATTRIB_TEX3:
case VERT_ATTRIB_TEX4:
case VERT_ATTRIB_TEX5:
case VERT_ATTRIB_TEX6:
case VERT_ATTRIB_TEX7:
assert(slot < Elements(vs_input_semantic_name));
vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
vs_input_semantic_index[slot] = num_generic++;
break;
case VERT_ATTRIB_GENERIC0:
case VERT_ATTRIB_GENERIC1:
case VERT_ATTRIB_GENERIC2:
case VERT_ATTRIB_GENERIC3:
case VERT_ATTRIB_GENERIC4:
case VERT_ATTRIB_GENERIC5:
case VERT_ATTRIB_GENERIC6:
case VERT_ATTRIB_GENERIC7:
case VERT_ATTRIB_GENERIC8:
case VERT_ATTRIB_GENERIC9:
case VERT_ATTRIB_GENERIC10:
case VERT_ATTRIB_GENERIC11:
case VERT_ATTRIB_GENERIC12:
case VERT_ATTRIB_GENERIC13:
case VERT_ATTRIB_GENERIC14:
case VERT_ATTRIB_GENERIC15:
assert(attr < VERT_ATTRIB_MAX);
assert(slot < Elements(vs_input_semantic_name));
vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
vs_input_semantic_index[slot] = num_generic++;
break;
default:
assert(0);
}
input_flags[slot] = stvp->Base.Base.InputFlags[attr];
} }
} }
#if 0 /* Compute mapping of vertex program outputs to slots.
if (outputMapping && outputSemanticName) {
printf("VERT_RESULT written out_slot semantic_name semantic_index\n");
for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
printf(" %-2d %c %3d %2d %2d\n",
attr,
((stvp->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++) {
assert(i < Elements(vs_output_semantic_name));
vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
vs_output_semantic_index[i] = 0;
output_flags[i] = 0x0;
}
num_generic = 0;
/*
* Determine number of outputs, the (default) output register
* mapping and the semantic information for each output.
*/ */
for (attr = 0; attr < VERT_RESULT_MAX; attr++) { for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
if (stvp->Base.Base.OutputsWritten & (1 << attr)) { if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) {
GLuint slot; stvp->result_to_output[attr] = ~0;
}
else {
unsigned slot = stvp->num_outputs++;
/* XXX stvp->result_to_output[attr] = slot;
* Pass in the fragment program's input's semantic info.
* Use the generic semantic indexes from there, instead of
* guessing below.
*/
if (outputMapping) {
slot = outputMapping[attr];
assert(slot != ~0);
}
else {
slot = vs_num_outputs;
vs_num_outputs++;
defaultOutputMapping[attr] = slot;
}
switch (attr) { switch (attr) {
case VERT_RESULT_HPOS: case VERT_RESULT_HPOS:
assert(slot == 0); stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stvp->output_semantic_index[slot] = 0;
vs_output_semantic_index[slot] = 0;
break; break;
case VERT_RESULT_COL0: case VERT_RESULT_COL0:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
vs_output_semantic_index[slot] = 0; stvp->output_semantic_index[slot] = 0;
break; break;
case VERT_RESULT_COL1: case VERT_RESULT_COL1:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
vs_output_semantic_index[slot] = 1; stvp->output_semantic_index[slot] = 1;
break; break;
case VERT_RESULT_BFC0: case VERT_RESULT_BFC0:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
vs_output_semantic_index[slot] = 0; stvp->output_semantic_index[slot] = 0;
break; break;
case VERT_RESULT_BFC1: case VERT_RESULT_BFC1:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
vs_output_semantic_index[slot] = 1; stvp->output_semantic_index[slot] = 1;
break; break;
case VERT_RESULT_FOGC: case VERT_RESULT_FOGC:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
vs_output_semantic_index[slot] = 0; stvp->output_semantic_index[slot] = 0;
break; break;
case VERT_RESULT_PSIZ: case VERT_RESULT_PSIZ:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
vs_output_semantic_index[slot] = 0; stvp->output_semantic_index[slot] = 0;
break; break;
case VERT_RESULT_EDGE: case VERT_RESULT_EDGE:
assert(0); assert(0);
break; break;
case VERT_RESULT_TEX0: case VERT_RESULT_TEX0:
case VERT_RESULT_TEX1: case VERT_RESULT_TEX1:
case VERT_RESULT_TEX2: case VERT_RESULT_TEX2:
@ -257,92 +163,50 @@ st_translate_vertex_program(struct st_context *st,
case VERT_RESULT_TEX5: case VERT_RESULT_TEX5:
case VERT_RESULT_TEX6: case VERT_RESULT_TEX6:
case VERT_RESULT_TEX7: case VERT_RESULT_TEX7:
/* fall-through */ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
break;
case VERT_RESULT_VAR0: case VERT_RESULT_VAR0:
/* fall-through */
default: default:
assert(slot < Elements(vs_output_semantic_name)); assert(attr < VERT_RESULT_MAX);
if (outputSemanticName) { stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
/* use provided semantic into */ stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); FRAG_ATTRIB_TEX0 +
vs_output_semantic_name[slot] = outputSemanticName[attr]; attr -
vs_output_semantic_index[slot] = outputSemanticIndex[attr]; VERT_RESULT_VAR0);
} break;
else {
/* use default semantic info */
vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
vs_output_semantic_index[slot] = num_generic++;
}
}
assert(slot < Elements(output_flags));
output_flags[slot] = stvp->Base.Base.OutputFlags[attr];
}
}
if (outputMapping) {
/* find max output slot referenced to compute vs_num_outputs */
GLuint maxSlot = 0;
for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
maxSlot = outputMapping[attr];
}
vs_num_outputs = maxSlot + 1;
}
else {
outputMapping = defaultOutputMapping;
}
#if 0 /* 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 < vs_num_outputs; i++) {
printf(" %2d %d %d\n",
i,
vs_output_semantic_name[i],
vs_output_semantic_index[i]);
}
} }
#endif }
/* free old shader state, if any */
if (stvp->state.tokens) {
st_free_tokens(stvp->state.tokens);
stvp->state.tokens = NULL;
}
if (stvp->driver_shader) {
cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
stvp->driver_shader = NULL;
}
stvp->state.tokens = struct st_vp_varient *
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key)
{
struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
struct pipe_context *pipe = st->pipe;
vpv->state.tokens =
st_translate_mesa_program(st->ctx, st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_VERTEX, TGSI_PROCESSOR_VERTEX,
&stvp->Base.Base, &stvp->Base.Base,
/* inputs */ /* inputs */
vs_num_inputs, stvp->num_inputs,
stvp->input_to_index, stvp->input_to_index,
vs_input_semantic_name, NULL, /* input semantic name */
vs_input_semantic_index, NULL, /* input semantic index */
NULL, NULL,
input_flags,
/* outputs */ /* outputs */
vs_num_outputs, stvp->num_outputs,
outputMapping, stvp->result_to_output,
vs_output_semantic_name, stvp->output_semantic_name,
vs_output_semantic_index, stvp->output_semantic_index );
output_flags );
stvp->num_inputs = vs_num_inputs; vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
stvp->driver_shader = pipe->create_vs_state(pipe, &stvp->state);
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
_mesa_print_program(&stvp->Base.Base); _mesa_print_program(&stvp->Base.Base);
@ -350,9 +214,11 @@ st_translate_vertex_program(struct st_context *st,
} }
if (ST_DEBUG & DEBUG_TGSI) { if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump( stvp->state.tokens, 0 ); tgsi_dump( vpv->state.tokens, 0 );
debug_printf("\n"); debug_printf("\n");
} }
return vpv;
} }
@ -375,7 +241,6 @@ st_translate_fragment_program(struct st_context *st,
GLuint attr; GLuint attr;
const GLbitfield inputsRead = stfp->Base.Base.InputsRead; const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
GLuint vslot = 0; GLuint vslot = 0;
GLuint num_generic = 0;
uint fs_num_inputs = 0; uint fs_num_inputs = 0;
@ -383,13 +248,6 @@ st_translate_fragment_program(struct st_context *st,
ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
uint fs_num_outputs = 0; uint fs_num_outputs = 0;
GLbitfield input_flags[MAX_PROGRAM_INPUTS];
GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
/*memset(&fs, 0, sizeof(fs));*/
memset(input_flags, 0, sizeof(input_flags));
memset(output_flags, 0, sizeof(output_flags));
/* which vertex output goes to the first fragment input: */ /* which vertex output goes to the first fragment input: */
if (inputsRead & FRAG_BIT_WPOS) if (inputsRead & FRAG_BIT_WPOS)
vslot = 0; vslot = 0;
@ -432,14 +290,25 @@ st_translate_fragment_program(struct st_context *st,
break; break;
case FRAG_ATTRIB_FACE: case FRAG_ATTRIB_FACE:
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
stfp->input_semantic_index[slot] = num_generic++; stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
break; break;
case FRAG_ATTRIB_PNTC:
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; /* In most cases, there is nothing special about these
stfp->input_semantic_index[slot] = num_generic++; * inputs, so adopt a convention to use the generic
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; * semantic name and the mesa FRAG_ATTRIB_ number as the
break; * 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_TEX0: case FRAG_ATTRIB_TEX0:
case FRAG_ATTRIB_TEX1: case FRAG_ATTRIB_TEX1:
case FRAG_ATTRIB_TEX2: case FRAG_ATTRIB_TEX2:
@ -448,19 +317,18 @@ st_translate_fragment_program(struct st_context *st,
case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX5:
case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX6:
case FRAG_ATTRIB_TEX7: case FRAG_ATTRIB_TEX7:
case FRAG_ATTRIB_PNTC:
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);
stfp->input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break; break;
case FRAG_ATTRIB_VAR0:
/* fall-through */
default:
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
} }
input_flags[slot] = stfp->Base.Base.InputFlags[attr];
} }
} }
@ -498,8 +366,6 @@ st_translate_fragment_program(struct st_context *st,
break; break;
} }
output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
fs_num_outputs++; fs_num_outputs++;
} }
} }
@ -518,13 +384,11 @@ st_translate_fragment_program(struct st_context *st,
stfp->input_semantic_name, stfp->input_semantic_name,
stfp->input_semantic_index, stfp->input_semantic_index,
interpMode, interpMode,
input_flags,
/* outputs */ /* outputs */
fs_num_outputs, fs_num_outputs,
outputMapping, outputMapping,
fs_output_semantic_name, fs_output_semantic_name,
fs_output_semantic_index, fs_output_semantic_index );
output_flags );
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state); stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state);

View File

@ -64,41 +64,70 @@ struct st_fragment_program
struct pipe_shader_state state; struct pipe_shader_state state;
void *driver_shader; void *driver_shader;
GLuint param_state;
/** List of vertex programs which have been translated such that their
* outputs match this fragment program's inputs.
*/
struct translated_vertex_program *vertex_programs;
/** Program prefixed with glBitmap prologue */ /** Program prefixed with glBitmap prologue */
struct st_fragment_program *bitmap_program; struct st_fragment_program *bitmap_program;
uint bitmap_sampler; uint bitmap_sampler;
}; };
struct st_vp_varient_key
{
char dummy; /* currently unused */
};
/**
* This represents a vertex program, especially translated to match
* the inputs of a particular fragment shader.
*/
struct st_vp_varient
{
/* Parameters which generated this translated version of a vertex
* shader:
*/
struct st_vp_varient_key key;
/** TGSI tokens -- why?
*/
struct pipe_shader_state state;
/** Driver's compiled shader */
void *driver_shader;
/** For using our private draw module (glRasterPos) */
struct draw_vertex_shader *draw_shader;
/** Next in linked list */
struct st_vp_varient *next;
};
/** /**
* Derived from Mesa gl_fragment_program: * Derived from Mesa gl_fragment_program:
*/ */
struct st_vertex_program struct st_vertex_program
{ {
struct gl_vertex_program Base; /**< The Mesa vertex program */ struct gl_vertex_program Base; /**< The Mesa vertex program */
GLuint serialNo; GLuint serialNo, lastSerialNo;
/** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
GLuint input_to_index[VERT_ATTRIB_MAX]; GLuint input_to_index[VERT_ATTRIB_MAX];
/** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */ /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */
GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
GLuint num_inputs; GLuint num_inputs;
struct pipe_shader_state state; /** Maps VERT_RESULT_x to slot */
void *driver_shader; GLuint result_to_output[VERT_RESULT_MAX];
ubyte output_semantic_name[VERT_RESULT_MAX];
ubyte output_semantic_index[VERT_RESULT_MAX];
GLuint num_outputs;
/** For using our private draw module (glRasterPos) */ /** List of translated varients of this vertex program.
struct draw_vertex_shader *draw_shader; */
struct st_vp_varient *varients;
GLuint param_state;
}; };
@ -143,13 +172,21 @@ st_translate_fragment_program(struct st_context *st,
const GLuint inputMapping[]); const GLuint inputMapping[]);
/* Called after program string change, discard all previous
* compilation results.
*/
extern void extern void
st_translate_vertex_program(struct st_context *st, st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *vp, struct st_vertex_program *stvp);
const GLuint vert_output_to_slot[],
const ubyte *fs_input_semantic_name,
const ubyte *fs_input_semantic_index);
extern struct st_vp_varient *
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key);
void
st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp );
extern void extern void
st_print_shaders(GLcontext *ctx); st_print_shaders(GLcontext *ctx);