Several fp and vp tweaks:

- Renumber VERT_RESULT_* values so that they match the
	  numbers of the corresponding FRAG_ATTRIB_ values.

        - Add ctx->VertexProgram._Current and FragmentProgram._Current
	  values which point to either the current client-supplied
	  program if enabled, or otherwise to the current mesa-internal
	  program.  Thus this program is always the correct one for
	  the current state, providing that the mesa flags to turn on
	  automatic generation are enabled.

	- Add callbacks to ctx->Driver.BindProgram() in texenvprogram.c
	  and t_vp_build.c so that the driver knows when the generated
	  program changes.  This is cleaner than trying to code all the
	  possible _NEW_* flags into the driver, and more precise as well.

	- Add a UsesKill flag to identify fragment programs with that
	  instruction, as these can require special treatment.

	- Move the FRAG_OUTPUT values to mtypes.h, near to similar defn's.
This commit is contained in:
Keith Whitwell
2005-11-01 17:25:49 +00:00
parent 6aa6d440d9
commit c3626a91ce
7 changed files with 156 additions and 100 deletions

View File

@@ -195,18 +195,18 @@ enum
#define VERT_RESULT_HPOS 0 #define VERT_RESULT_HPOS 0
#define VERT_RESULT_COL0 1 #define VERT_RESULT_COL0 1
#define VERT_RESULT_COL1 2 #define VERT_RESULT_COL1 2
#define VERT_RESULT_BFC0 3 #define VERT_RESULT_FOGC 3
#define VERT_RESULT_BFC1 4 #define VERT_RESULT_TEX0 4
#define VERT_RESULT_FOGC 5 #define VERT_RESULT_TEX1 5
#define VERT_RESULT_PSIZ 6 #define VERT_RESULT_TEX2 6
#define VERT_RESULT_TEX0 7 #define VERT_RESULT_TEX3 7
#define VERT_RESULT_TEX1 8 #define VERT_RESULT_TEX4 8
#define VERT_RESULT_TEX2 9 #define VERT_RESULT_TEX5 9
#define VERT_RESULT_TEX3 10 #define VERT_RESULT_TEX6 10
#define VERT_RESULT_TEX4 11 #define VERT_RESULT_TEX7 11
#define VERT_RESULT_TEX5 12 #define VERT_RESULT_PSIZ 12
#define VERT_RESULT_TEX6 13 #define VERT_RESULT_BFC0 13
#define VERT_RESULT_TEX7 14 #define VERT_RESULT_BFC1 14
#define VERT_RESULT_MAX 15 #define VERT_RESULT_MAX 15
@@ -226,7 +226,9 @@ enum
FRAG_ATTRIB_TEX4 = 8, FRAG_ATTRIB_TEX4 = 8,
FRAG_ATTRIB_TEX5 = 9, FRAG_ATTRIB_TEX5 = 9,
FRAG_ATTRIB_TEX6 = 10, FRAG_ATTRIB_TEX6 = 10,
FRAG_ATTRIB_TEX7 = 11 FRAG_ATTRIB_TEX7 = 11,
FRAG_ATTRIB_MAX = 12
}; };
/* /*
@@ -257,6 +259,14 @@ enum
/*@}*/ /*@}*/
/* Fragment program results
*/
#define FRAG_OUTPUT_COLR 0
#define FRAG_OUTPUT_COLH 1
#define FRAG_OUTPUT_DEPR 2
#define FRAG_OUTPUT_MAX 3
/** /**
* Indexes for all renderbuffers * Indexes for all renderbuffers
*/ */
@@ -1791,6 +1801,7 @@ struct fragment_program
GLuint NumNativeTexIndirections; GLuint NumNativeTexIndirections;
GLenum FogOption; GLenum FogOption;
struct program_parameter_list *Parameters; /**< array [NumParameters] */ struct program_parameter_list *Parameters; /**< array [NumParameters] */
GLboolean UsesKill;
#ifdef USE_TCC #ifdef USE_TCC
char c_str[4096]; /* experimental... */ char c_str[4096]; /* experimental... */
@@ -1835,6 +1846,9 @@ struct gl_vertex_program_state
GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_NV */ GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_NV */
GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_NV */ GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_NV */
struct vertex_program *Current; /**< ptr to currently bound program */ struct vertex_program *Current; /**< ptr to currently bound program */
struct vertex_program *_Current; /**< ptr to currently bound
program, including internal
(t_vp_build.c) programs */
GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4]; GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4]; GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
@@ -1865,7 +1879,8 @@ struct gl_fragment_program_state
GLboolean _Enabled; /* Really enabled? */ GLboolean _Enabled; /* Really enabled? */
GLboolean _Active; /* Really really enabled? */ GLboolean _Active; /* Really really enabled? */
struct fragment_program *Current; /* ptr to currently bound program */ struct fragment_program *Current; /* ptr to currently bound program */
struct fragment_program *_Current; /* ptr to currently active program */ struct fragment_program *_Current; /* ptr to currently active program
(including internal programs) */
struct fp_machine Machine; /* machine state */ struct fp_machine Machine; /* machine state */
GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /* Env params */ GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /* Env params */

View File

@@ -1130,10 +1130,9 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
{ {
struct state_key *key; struct state_key *key;
GLuint hash; GLuint hash;
struct fragment_program *prev = ctx->FragmentProgram._Current;
if (ctx->FragmentProgram._Enabled) if (!ctx->FragmentProgram._Enabled) {
return;
key = make_state_key(ctx); key = make_state_key(ctx);
hash = hash_key(key); hash = hash_key(key);
@@ -1142,7 +1141,7 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key)); search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key));
if (!ctx->_TexEnvProgram) { if (!ctx->_TexEnvProgram) {
if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash); if (1) _mesa_printf("Building new texenv proggy for key %x\n", hash);
ctx->FragmentProgram._Current = ctx->_TexEnvProgram = ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
(struct fragment_program *) (struct fragment_program *)
@@ -1153,9 +1152,19 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram); cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
} else { } else {
FREE(key); FREE(key);
if (0) _mesa_printf("Found existing texenv program for key %x\n", hash); if (1) _mesa_printf("Found existing texenv program for key %x\n", hash);
}
}
else {
ctx->FragmentProgram._Current = ctx->FragmentProgram.Current;
} }
/* Tell the driver about the change. Could define a new target for
* this?
*/
if (ctx->FragmentProgram._Current != prev)
ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct program *)
ctx->FragmentProgram._Current);
} }
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx ) void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )

View File

@@ -3013,6 +3013,7 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
break; break;
case OP_TEX_KIL: case OP_TEX_KIL:
Program->UsesKill = 1;
if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
return 1; return 1;
fp->Opcode = FP_OPCODE_KIL; fp->Opcode = FP_OPCODE_KIL;
@@ -4014,6 +4015,8 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
program->NumTexInstructions = program->NumTexInstructions =
program->NumTexIndirections = 0; program->NumTexIndirections = 0;
program->UsesKill = 0;
program->FPInstructions = NULL; program->FPInstructions = NULL;
program->VPInstructions = NULL; program->VPInstructions = NULL;

View File

@@ -65,6 +65,8 @@ struct arb_program
GLuint NumAluInstructions; GLuint NumAluInstructions;
GLuint NumTexInstructions; GLuint NumTexInstructions;
GLuint NumTexIndirections; GLuint NumTexIndirections;
GLboolean UsesKill;
}; };

View File

@@ -37,15 +37,6 @@
#include "mtypes.h" #include "mtypes.h"
/**
* Fragment program output registers.
* Note: when we fully suppport GL_ARB_draw_buffers we'll have more than
* one output color.
*/
#define FRAG_OUTPUT_COLR 0 /* fragment color */
#define FRAG_OUTPUT_COLH 1 /* fragment color, half precision (NV) */
#define FRAG_OUTPUT_DEPR 2 /* depth/Z */
/* condition codes */ /* condition codes */
#define COND_GT 1 /* greater than zero */ #define COND_GT 1 /* greater than zero */

View File

@@ -288,8 +288,9 @@ static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
}; };
static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = { static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
"HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ", "HPOS", "COL0", "COL1", "FOGC",
"TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7",
"PSIZ", "BFC0", "BFC1", NULL
}; };
/* NOTE: the order here must match opcodes in nvvertprog.h */ /* NOTE: the order here must match opcodes in nvvertprog.h */

View File

@@ -53,10 +53,10 @@ struct state_key {
unsigned fog_source_is_depth:1; unsigned fog_source_is_depth:1;
unsigned tnl_do_vertex_fog:1; unsigned tnl_do_vertex_fog:1;
unsigned separate_specular:1; unsigned separate_specular:1;
unsigned fog_enabled:1;
unsigned fog_mode:2; unsigned fog_mode:2;
unsigned point_attenuated:1; unsigned point_attenuated:1;
unsigned texture_enabled_global:1; unsigned texture_enabled_global:1;
unsigned fragprog_inputs_read:12;
struct { struct {
unsigned light_enabled:1; unsigned light_enabled:1;
@@ -75,10 +75,10 @@ struct state_key {
#define FOG_LINEAR 0 #define FOG_NONE 0
#define FOG_EXP 1 #define FOG_LINEAR 1
#define FOG_EXP2 2 #define FOG_EXP 2
#define FOG_UNKNOWN 3 #define FOG_EXP2 3
static GLuint translate_fog_mode( GLenum mode ) static GLuint translate_fog_mode( GLenum mode )
{ {
@@ -86,7 +86,7 @@ static GLuint translate_fog_mode( GLenum mode )
case GL_LINEAR: return FOG_LINEAR; case GL_LINEAR: return FOG_LINEAR;
case GL_EXP: return FOG_EXP; case GL_EXP: return FOG_EXP;
case GL_EXP2: return FOG_EXP2; case GL_EXP2: return FOG_EXP2;
default: return FOG_UNKNOWN; default: return FOG_NONE;
} }
} }
@@ -116,9 +116,16 @@ static struct state_key *make_state_key( GLcontext *ctx )
{ {
TNLcontext *tnl = TNL_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb; struct vertex_buffer *VB = &tnl->vb;
struct fragment_program *fp = ctx->FragmentProgram._Current;
struct state_key *key = CALLOC_STRUCT(state_key); struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i; GLuint i;
/* This now relies on texenvprogram.c being active:
*/
assert(fp);
key->fragprog_inputs_read = fp->InputsRead;
key->separate_specular = (ctx->Light.Model.ColorControl == key->separate_specular = (ctx->Light.Model.ColorControl ==
GL_SEPARATE_SPECULAR_COLOR); GL_SEPARATE_SPECULAR_COLOR);
@@ -166,19 +173,14 @@ static struct state_key *make_state_key( GLcontext *ctx )
if (ctx->Transform.RescaleNormals) if (ctx->Transform.RescaleNormals)
key->rescale_normals = 1; key->rescale_normals = 1;
if (ctx->Fog.Enabled) key->fog_mode = translate_fog_mode(fp->FogOption);
key->fog_enabled = 1;
if (key->fog_enabled) {
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
key->fog_source_is_depth = 1; key->fog_source_is_depth = 1;
if (tnl->_DoVertexFog) if (tnl->_DoVertexFog)
key->tnl_do_vertex_fog = 1; key->tnl_do_vertex_fog = 1;
key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
}
if (ctx->Point._Attenuated) if (ctx->Point._Attenuated)
key->point_attenuated = 1; key->point_attenuated = 1;
@@ -332,6 +334,9 @@ static struct ureg get_temp( struct tnl_program *p )
_mesa_exit(1); _mesa_exit(1);
} }
if (bit > p->program->Base.NumTemporaries)
p->program->Base.NumTemporaries = bit;
p->temp_in_use |= 1<<(bit-1); p->temp_in_use |= 1<<(bit-1);
return make_ureg(PROGRAM_TEMPORARY, bit-1); return make_ureg(PROGRAM_TEMPORARY, bit-1);
} }
@@ -710,6 +715,8 @@ static GLuint material_attrib( GLuint side, GLuint property )
side); side);
} }
/* Get a bitmask of which material values vary on a per-vertex basis.
*/
static void set_material_flags( struct tnl_program *p ) static void set_material_flags( struct tnl_program *p )
{ {
p->color_materials = 0; p->color_materials = 0;
@@ -1194,9 +1201,14 @@ static void build_texture_transform( struct tnl_program *p )
GLuint i, j; GLuint i, j;
for (i = 0; i < MAX_TEXTURE_UNITS; i++) { for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
if (p->state->unit[i].texgen_enabled || texmat_enabled) { if (!(p->state->fragprog_inputs_read & (FRAG_BIT_TEX0<<i)))
continue;
if (p->state->unit[i].texgen_enabled ||
p->state->unit[i].texmat_enabled) {
GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
struct ureg out_texgen = undef; struct ureg out_texgen = undef;
@@ -1293,10 +1305,7 @@ static void build_texture_transform( struct tnl_program *p )
release_temps(p); release_temps(p);
} }
else if (p->state->unit[i].texunit_really_enabled) { else {
/* KW: _ReallyEnabled isn't sufficient? Need to know whether
* this texture unit is referenced by the fragment shader.
*/
emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
} }
} }
@@ -1338,15 +1347,23 @@ static void build_tnl_program( struct tnl_program *p )
/* Lighting calculations: /* Lighting calculations:
*/ */
if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
if (p->state->light_global_enabled) if (p->state->light_global_enabled)
build_lighting(p); build_lighting(p);
else else {
if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0); emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
if (p->state->fog_enabled) if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL1);
}
}
if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
p->state->fog_mode != FOG_NONE)
build_fog(p); build_fog(p);
if (p->state->texture_enabled_global) if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
build_texture_transform(p); build_texture_transform(p);
if (p->state->point_attenuated) if (p->state->point_attenuated)
@@ -1470,15 +1487,24 @@ void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
TNLcontext *tnl = TNL_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx);
struct state_key *key; struct state_key *key;
GLuint hash; GLuint hash;
struct vertex_program *prev = ctx->VertexProgram._Current;
if (ctx->VertexProgram._Enabled) if (ctx->VertexProgram._Enabled) {
return;
/* Grab all the relevent state and put it in a single structure: /* Grab all the relevent state and put it in a single structure:
*/ */
key = make_state_key(ctx); key = make_state_key(ctx);
hash = hash_key(key); hash = hash_key(key);
if (tnl->vp_cache == NULL) {
tnl->vp_cache = MALLOC(sizeof(*tnl->vp_cache));
tnl->vp_cache->size = 5;
tnl->vp_cache->n_items = 0;
tnl->vp_cache->items = MALLOC(tnl->vp_cache->size *
sizeof(*tnl->vp_cache->items));
_mesa_memset(tnl->vp_cache->items, 0, tnl->vp_cache->size *
sizeof(*tnl->vp_cache->items));
}
/* Look for an already-prepared program for this state: /* Look for an already-prepared program for this state:
*/ */
ctx->_TnlProgram = (struct vertex_program *) ctx->_TnlProgram = (struct vertex_program *)
@@ -1496,6 +1522,7 @@ void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
create_new_program( key, ctx->_TnlProgram, create_new_program( key, ctx->_TnlProgram,
ctx->Const.VertexProgram.MaxTemps ); ctx->Const.VertexProgram.MaxTemps );
cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram ); cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram );
} }
else { else {
@@ -1503,9 +1530,17 @@ void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
if (0) if (0)
_mesa_printf("Found existing TNL program for key %x\n", hash); _mesa_printf("Found existing TNL program for key %x\n", hash);
} }
}
else {
ctx->VertexProgram._Current = ctx->VertexProgram.Current;
}
/* Need a BindProgram callback for the driver? /* Tell the driver about the change. Could define a new target for
* this?
*/ */
if (ctx->VertexProgram._Current != prev)
ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, (struct program *)
ctx->VertexProgram._Current);
} }