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:
commit
4dcdf3b9c6
|
@ -46,7 +46,8 @@ static const struct st_tracked_state *atoms[] =
|
|||
&st_update_clip,
|
||||
|
||||
&st_finalize_textures,
|
||||
&st_update_shader,
|
||||
&st_update_fp,
|
||||
&st_update_vp,
|
||||
|
||||
&st_update_rasterizer,
|
||||
&st_update_polygon_stipple,
|
||||
|
|
|
@ -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_clip;
|
||||
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_polygon_stipple;
|
||||
extern const struct st_tracked_state st_update_viewport;
|
||||
|
|
|
@ -56,82 +56,18 @@
|
|||
#include "st_mesa_to_tgsi.h"
|
||||
|
||||
|
||||
/**
|
||||
* This represents a vertex program, especially translated to match
|
||||
* the inputs of a particular fragment shader.
|
||||
*/
|
||||
struct translated_vertex_program
|
||||
{
|
||||
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;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Translate fragment program if needed.
|
||||
*/
|
||||
static void
|
||||
translate_fp(struct st_context *st,
|
||||
struct st_fragment_program *stfp)
|
||||
{
|
||||
const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
|
||||
|
||||
if (!stfp->state.tokens) {
|
||||
GLuint inAttr, numIn = 0;
|
||||
|
||||
|
@ -141,7 +77,7 @@ find_translated_vp(struct st_context *st,
|
|||
numIn++;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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) {
|
||||
if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
|
||||
for (vpv = stvp->varients; vpv; vpv = vpv->next) {
|
||||
if (memcmp(&vpv->key, &key, sizeof key) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No? Allocate translated vp object now */
|
||||
if (!xvp) {
|
||||
xvp = ST_CALLOC_STRUCT(translated_vertex_program);
|
||||
xvp->frag_inputs = fragInputsRead;
|
||||
xvp->master = stvp;
|
||||
/* No? Perform new translation here. */
|
||||
if (!vpv) {
|
||||
vpv = st_translate_vertex_program(st, stvp, &key);
|
||||
if (!vpv)
|
||||
return NULL;
|
||||
|
||||
xvp->next = stfp->vertex_programs;
|
||||
stfp->vertex_programs = xvp;
|
||||
vpv->next = stvp->varients;
|
||||
stvp->varients = vpv;
|
||||
}
|
||||
|
||||
/* See if we need to translate vertex program to TGSI form */
|
||||
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;
|
||||
return vpv;
|
||||
}
|
||||
|
||||
|
||||
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 *
|
||||
|
@ -328,32 +157,19 @@ get_passthrough_fs(struct st_context *st)
|
|||
return st->passthrough_fs;
|
||||
}
|
||||
|
||||
|
||||
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 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);
|
||||
stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
|
||||
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);
|
||||
|
||||
cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
|
||||
|
||||
if (st->missing_textures) {
|
||||
/* use a pass-through frag shader that uses no textures */
|
||||
void *fs = get_passthrough_fs(st);
|
||||
|
@ -362,16 +178,48 @@ update_linkage( struct st_context *st )
|
|||
else {
|
||||
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 = {
|
||||
"st_update_shader", /* name */
|
||||
const struct st_tracked_state st_update_vp = {
|
||||
"st_update_vp", /* name */
|
||||
{ /* dirty */
|
||||
0, /* mesa */
|
||||
ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
|
||||
ST_NEW_VERTEX_PROGRAM /* st */
|
||||
},
|
||||
update_linkage /* update */
|
||||
update_vp /* update */
|
||||
};
|
||||
|
|
|
@ -169,11 +169,6 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
|
|||
stfp = (struct st_fragment_program *) p;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "tgsi/tgsi_ureg.h"
|
||||
#include "util/u_tile.h"
|
||||
#include "util/u_draw_quad.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
|
||||
* vertex position and texcoord (and optionally, color).
|
||||
*/
|
||||
static struct st_vertex_program *
|
||||
st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
|
||||
static void *
|
||||
st_make_passthrough_vertex_shader(struct st_context *st,
|
||||
GLboolean passColor)
|
||||
{
|
||||
GLcontext *ctx = st->ctx;
|
||||
struct st_vertex_program *stvp;
|
||||
struct gl_program *p;
|
||||
GLuint ic = 0;
|
||||
if (!st->drawpix.vert_shaders[passColor]) {
|
||||
struct ureg_program *ureg =
|
||||
ureg_create( TGSI_PROCESSOR_VERTEX );
|
||||
|
||||
if (st->drawpix.vert_shaders[passColor])
|
||||
return st->drawpix.vert_shaders[passColor];
|
||||
|
||||
/*
|
||||
* Create shader now
|
||||
*/
|
||||
p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
|
||||
if (!p)
|
||||
if (ureg == NULL)
|
||||
return NULL;
|
||||
|
||||
if (passColor)
|
||||
p->NumInstructions = 4;
|
||||
else
|
||||
p->NumInstructions = 3;
|
||||
|
||||
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;
|
||||
ureg_MOV(ureg,
|
||||
ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
|
||||
ureg_DECL_vs_input( ureg, 0 ));
|
||||
|
||||
/* 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;
|
||||
ureg_MOV(ureg,
|
||||
ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ),
|
||||
ureg_DECL_vs_input( ureg, 1 ));
|
||||
|
||||
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++;
|
||||
ureg_MOV(ureg,
|
||||
ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
|
||||
ureg_DECL_vs_input( ureg, 2 ));
|
||||
}
|
||||
|
||||
/* END; */
|
||||
p->Instructions[ic].Opcode = OPCODE_END;
|
||||
ic++;
|
||||
ureg_END( ureg );
|
||||
|
||||
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);
|
||||
st->drawpix.vert_shaders[passColor] =
|
||||
ureg_create_shader_and_destroy( ureg, st->pipe );
|
||||
}
|
||||
|
||||
stvp = (struct st_vertex_program *) p;
|
||||
st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
|
||||
|
||||
st->drawpix.vert_shaders[passColor] = stvp;
|
||||
|
||||
return stvp;
|
||||
return st->drawpix.vert_shaders[passColor];
|
||||
}
|
||||
|
||||
|
||||
|
@ -539,8 +503,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
|
|||
GLsizei width, GLsizei height,
|
||||
GLfloat zoomX, GLfloat zoomY,
|
||||
struct pipe_texture *pt,
|
||||
struct st_vertex_program *stvp,
|
||||
struct st_fragment_program *stfp,
|
||||
void *driver_vp,
|
||||
void *driver_fp,
|
||||
const GLfloat *color,
|
||||
GLboolean invertTex)
|
||||
{
|
||||
|
@ -575,10 +539,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
cso_set_vertex_shader_handle(cso, stvp->driver_shader);
|
||||
cso_set_vertex_shader_handle(cso, driver_vp);
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct st_fragment_program *stfp;
|
||||
struct st_vertex_program *stvp;
|
||||
void *driver_vp;
|
||||
struct st_context *st = st_context(ctx);
|
||||
struct pipe_surface *ps;
|
||||
const GLfloat *color;
|
||||
|
@ -826,13 +790,13 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
|
|||
if (format == GL_DEPTH_COMPONENT) {
|
||||
ps = st->state.framebuffer.zsbuf;
|
||||
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;
|
||||
}
|
||||
else {
|
||||
ps = st->state.framebuffer.cbufs[0];
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -843,7 +807,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
|
|||
if (pt) {
|
||||
draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -960,7 +927,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
|||
struct pipe_context *pipe = st->pipe;
|
||||
struct pipe_screen *screen = pipe->screen;
|
||||
struct st_renderbuffer *rbRead;
|
||||
struct st_vertex_program *stvp;
|
||||
void *driver_vp;
|
||||
struct st_fragment_program *stfp;
|
||||
struct pipe_texture *pt;
|
||||
GLfloat *color;
|
||||
|
@ -1009,14 +976,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
|||
rbRead = st_get_color_read_renderbuffer(ctx);
|
||||
color = NULL;
|
||||
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 {
|
||||
assert(type == GL_DEPTH);
|
||||
rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
|
||||
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
|
||||
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;
|
||||
|
@ -1148,7 +1115,10 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
|||
/* draw textured quad */
|
||||
draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -138,24 +138,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)
|
|||
case GL_VERTEX_PROGRAM_ARB:
|
||||
{
|
||||
struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
|
||||
|
||||
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;
|
||||
}
|
||||
st_vp_release_varients( st, stvp );
|
||||
}
|
||||
break;
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
|
@ -177,8 +160,6 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)
|
|||
_mesa_reference_program(ctx, &prg, NULL);
|
||||
stfp->bitmap_program = NULL;
|
||||
}
|
||||
|
||||
st_free_translated_vertex_programs(st, stfp->vertex_programs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -219,8 +200,6 @@ static void st_program_string_notify( GLcontext *ctx,
|
|||
stfp->state.tokens = NULL;
|
||||
}
|
||||
|
||||
stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
|
||||
|
||||
if (st->fp == stfp)
|
||||
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
|
||||
}
|
||||
|
@ -229,25 +208,7 @@ static void st_program_string_notify( GLcontext *ctx,
|
|||
|
||||
stvp->serialNo++;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
|
||||
st_vp_release_varients( st, stvp );
|
||||
|
||||
if (st->vp == stvp)
|
||||
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
|
||||
|
|
|
@ -127,6 +127,8 @@ struct st_context
|
|||
struct st_vertex_program *vp; /**< Currently bound vertex program */
|
||||
struct st_fragment_program *fp; /**< Currently bound fragment program */
|
||||
|
||||
struct st_vp_varient *vp_varient;
|
||||
|
||||
struct gl_texture_object *default_texture;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -86,7 +86,8 @@ st_print_current(void)
|
|||
}
|
||||
#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)
|
||||
_mesa_print_parameter_list(st->vp->Base.Base.Parameters);
|
||||
|
||||
|
|
|
@ -573,7 +573,7 @@ st_draw_vbo(GLcontext *ctx,
|
|||
|
||||
/* must get these after state validation! */
|
||||
vp = ctx->st->vp;
|
||||
vs = &ctx->st->vp->state;
|
||||
vs = &ctx->st->vp_varient->state;
|
||||
|
||||
#if 0
|
||||
if (MESA_VERBOSE & VERBOSE_GLSL) {
|
||||
|
|
|
@ -120,10 +120,10 @@ st_feedback_draw_vbo(GLcontext *ctx,
|
|||
|
||||
/* must get these after state validation! */
|
||||
vp = ctx->st->vp;
|
||||
vs = &st->vp->state;
|
||||
vs = &st->vp_varient->state;
|
||||
|
||||
if (!st->vp->draw_shader) {
|
||||
st->vp->draw_shader = draw_create_vertex_shader(draw, vs);
|
||||
if (!st->vp_varient->draw_shader) {
|
||||
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_clip_state(draw, &st->state.clip);
|
||||
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);
|
||||
|
||||
/* loop over TGSI shader inputs to determine vertex buffer
|
||||
|
|
|
@ -704,12 +704,10 @@ st_translate_mesa_program(
|
|||
const ubyte inputSemanticName[],
|
||||
const ubyte inputSemanticIndex[],
|
||||
const GLuint interpMode[],
|
||||
const GLbitfield inputFlags[],
|
||||
GLuint numOutputs,
|
||||
const GLuint outputMapping[],
|
||||
const ubyte outputSemanticName[],
|
||||
const ubyte outputSemanticIndex[],
|
||||
const GLbitfield outputFlags[] )
|
||||
const ubyte outputSemanticIndex[] )
|
||||
{
|
||||
struct st_translate translate, *t;
|
||||
struct ureg_program *ureg;
|
||||
|
|
|
@ -49,12 +49,10 @@ st_translate_mesa_program(
|
|||
const ubyte inputSemanticName[],
|
||||
const ubyte inputSemanticIndex[],
|
||||
const GLuint interpMode[],
|
||||
const GLbitfield inputFlags[],
|
||||
GLuint numOutputs,
|
||||
const GLuint outputMapping[],
|
||||
const ubyte outputSemanticName[],
|
||||
const ubyte outputSemanticIndex[],
|
||||
const GLbitfield outputFlags[] );
|
||||
const ubyte outputSemanticIndex[] );
|
||||
|
||||
void
|
||||
st_free_tokens(const struct tgsi_token *tokens);
|
||||
|
|
|
@ -49,6 +49,36 @@
|
|||
#include "st_mesa_to_tgsi.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.
|
||||
|
@ -58,31 +88,13 @@
|
|||
* \return pointer to cached pipe_shader object.
|
||||
*/
|
||||
void
|
||||
st_translate_vertex_program(struct st_context *st,
|
||||
struct st_vertex_program *stvp,
|
||||
const GLuint outputMapping[],
|
||||
const ubyte *outputSemanticName,
|
||||
const ubyte *outputSemanticIndex)
|
||||
st_prepare_vertex_program(struct st_context *st,
|
||||
struct st_vertex_program *stvp)
|
||||
{
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
GLuint defaultOutputMapping[VERT_RESULT_MAX];
|
||||
GLuint attr, i;
|
||||
GLuint num_generic = 0;
|
||||
GLuint attr;
|
||||
|
||||
ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS];
|
||||
ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS];
|
||||
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));
|
||||
stvp->num_inputs = 0;
|
||||
stvp->num_outputs = 0;
|
||||
|
||||
if (stvp->Base.IsPositionInvariant)
|
||||
_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++) {
|
||||
if (stvp->Base.Base.InputsRead & (1 << attr)) {
|
||||
const GLuint slot = vs_num_inputs;
|
||||
|
||||
vs_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];
|
||||
stvp->input_to_index[attr] = stvp->num_inputs;
|
||||
stvp->index_to_input[stvp->num_inputs] = attr;
|
||||
stvp->num_inputs++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
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.
|
||||
/* Compute mapping of vertex program outputs to slots.
|
||||
*/
|
||||
for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
|
||||
if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
|
||||
GLuint slot;
|
||||
|
||||
/* XXX
|
||||
* 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);
|
||||
if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) {
|
||||
stvp->result_to_output[attr] = ~0;
|
||||
}
|
||||
else {
|
||||
slot = vs_num_outputs;
|
||||
vs_num_outputs++;
|
||||
defaultOutputMapping[attr] = slot;
|
||||
}
|
||||
unsigned slot = stvp->num_outputs++;
|
||||
|
||||
stvp->result_to_output[attr] = slot;
|
||||
|
||||
switch (attr) {
|
||||
case VERT_RESULT_HPOS:
|
||||
assert(slot == 0);
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
|
||||
vs_output_semantic_index[slot] = 0;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
|
||||
stvp->output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VERT_RESULT_COL0:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
vs_output_semantic_index[slot] = 0;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
stvp->output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VERT_RESULT_COL1:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
vs_output_semantic_index[slot] = 1;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
stvp->output_semantic_index[slot] = 1;
|
||||
break;
|
||||
case VERT_RESULT_BFC0:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
vs_output_semantic_index[slot] = 0;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
stvp->output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VERT_RESULT_BFC1:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
vs_output_semantic_index[slot] = 1;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
stvp->output_semantic_index[slot] = 1;
|
||||
break;
|
||||
case VERT_RESULT_FOGC:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
|
||||
vs_output_semantic_index[slot] = 0;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
|
||||
stvp->output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VERT_RESULT_PSIZ:
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
|
||||
vs_output_semantic_index[slot] = 0;
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
|
||||
stvp->output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VERT_RESULT_EDGE:
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case VERT_RESULT_TEX0:
|
||||
case VERT_RESULT_TEX1:
|
||||
case VERT_RESULT_TEX2:
|
||||
|
@ -257,92 +163,50 @@ st_translate_vertex_program(struct st_context *st,
|
|||
case VERT_RESULT_TEX5:
|
||||
case VERT_RESULT_TEX6:
|
||||
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:
|
||||
/* fall-through */
|
||||
default:
|
||||
assert(slot < Elements(vs_output_semantic_name));
|
||||
if (outputSemanticName) {
|
||||
/* use provided semantic into */
|
||||
assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT);
|
||||
vs_output_semantic_name[slot] = outputSemanticName[attr];
|
||||
vs_output_semantic_index[slot] = outputSemanticIndex[attr];
|
||||
}
|
||||
else {
|
||||
/* use default semantic info */
|
||||
vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
vs_output_semantic_index[slot] = num_generic++;
|
||||
assert(attr < VERT_RESULT_MAX);
|
||||
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
|
||||
FRAG_ATTRIB_TEX0 +
|
||||
attr -
|
||||
VERT_RESULT_VAR0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
#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 =
|
||||
vpv->state.tokens =
|
||||
st_translate_mesa_program(st->ctx,
|
||||
TGSI_PROCESSOR_VERTEX,
|
||||
&stvp->Base.Base,
|
||||
/* inputs */
|
||||
vs_num_inputs,
|
||||
stvp->num_inputs,
|
||||
stvp->input_to_index,
|
||||
vs_input_semantic_name,
|
||||
vs_input_semantic_index,
|
||||
NULL, /* input semantic name */
|
||||
NULL, /* input semantic index */
|
||||
NULL,
|
||||
input_flags,
|
||||
/* outputs */
|
||||
vs_num_outputs,
|
||||
outputMapping,
|
||||
vs_output_semantic_name,
|
||||
vs_output_semantic_index,
|
||||
output_flags );
|
||||
stvp->num_outputs,
|
||||
stvp->result_to_output,
|
||||
stvp->output_semantic_name,
|
||||
stvp->output_semantic_index );
|
||||
|
||||
stvp->num_inputs = vs_num_inputs;
|
||||
stvp->driver_shader = pipe->create_vs_state(pipe, &stvp->state);
|
||||
vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
|
||||
|
||||
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
|
||||
_mesa_print_program(&stvp->Base.Base);
|
||||
|
@ -350,9 +214,11 @@ st_translate_vertex_program(struct st_context *st,
|
|||
}
|
||||
|
||||
if (ST_DEBUG & DEBUG_TGSI) {
|
||||
tgsi_dump( stvp->state.tokens, 0 );
|
||||
tgsi_dump( vpv->state.tokens, 0 );
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
return vpv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,7 +241,6 @@ st_translate_fragment_program(struct st_context *st,
|
|||
GLuint attr;
|
||||
const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
|
||||
GLuint vslot = 0;
|
||||
GLuint num_generic = 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];
|
||||
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: */
|
||||
if (inputsRead & FRAG_BIT_WPOS)
|
||||
vslot = 0;
|
||||
|
@ -432,14 +290,25 @@ st_translate_fragment_program(struct st_context *st,
|
|||
break;
|
||||
case FRAG_ATTRIB_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;
|
||||
break;
|
||||
case FRAG_ATTRIB_PNTC:
|
||||
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
stfp->input_semantic_index[slot] = num_generic++;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
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_TEX0:
|
||||
case FRAG_ATTRIB_TEX1:
|
||||
case FRAG_ATTRIB_TEX2:
|
||||
|
@ -448,19 +317,18 @@ st_translate_fragment_program(struct st_context *st,
|
|||
case FRAG_ATTRIB_TEX5:
|
||||
case FRAG_ATTRIB_TEX6:
|
||||
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_index[slot] = num_generic++;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
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;
|
||||
}
|
||||
|
||||
output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
|
||||
|
||||
fs_num_outputs++;
|
||||
}
|
||||
}
|
||||
|
@ -518,13 +384,11 @@ st_translate_fragment_program(struct st_context *st,
|
|||
stfp->input_semantic_name,
|
||||
stfp->input_semantic_index,
|
||||
interpMode,
|
||||
input_flags,
|
||||
/* outputs */
|
||||
fs_num_outputs,
|
||||
outputMapping,
|
||||
fs_output_semantic_name,
|
||||
fs_output_semantic_index,
|
||||
output_flags );
|
||||
fs_output_semantic_index );
|
||||
|
||||
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state);
|
||||
|
||||
|
|
|
@ -64,41 +64,70 @@ struct st_fragment_program
|
|||
struct pipe_shader_state state;
|
||||
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 */
|
||||
struct st_fragment_program *bitmap_program;
|
||||
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:
|
||||
*/
|
||||
struct st_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 */
|
||||
GLuint input_to_index[VERT_ATTRIB_MAX];
|
||||
/** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */
|
||||
GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
|
||||
|
||||
GLuint num_inputs;
|
||||
|
||||
struct pipe_shader_state state;
|
||||
void *driver_shader;
|
||||
/** Maps VERT_RESULT_x to slot */
|
||||
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) */
|
||||
struct draw_vertex_shader *draw_shader;
|
||||
|
||||
GLuint param_state;
|
||||
/** List of translated varients of this vertex program.
|
||||
*/
|
||||
struct st_vp_varient *varients;
|
||||
};
|
||||
|
||||
|
||||
|
@ -143,13 +172,21 @@ st_translate_fragment_program(struct st_context *st,
|
|||
const GLuint inputMapping[]);
|
||||
|
||||
|
||||
/* Called after program string change, discard all previous
|
||||
* compilation results.
|
||||
*/
|
||||
extern void
|
||||
st_translate_vertex_program(struct st_context *st,
|
||||
struct st_vertex_program *vp,
|
||||
const GLuint vert_output_to_slot[],
|
||||
const ubyte *fs_input_semantic_name,
|
||||
const ubyte *fs_input_semantic_index);
|
||||
st_prepare_vertex_program(struct st_context *st,
|
||||
struct st_vertex_program *stvp);
|
||||
|
||||
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
|
||||
st_print_shaders(GLcontext *ctx);
|
||||
|
|
Loading…
Reference in New Issue