Use program serial numbers to avoid re-generating fragment programs for glDrawPixels.

This commit is contained in:
Brian 2007-10-30 16:13:37 -06:00
parent ee70c02b62
commit d6a739f6b0
5 changed files with 58 additions and 28 deletions

View file

@ -42,6 +42,7 @@
#include "shader/prog_print.h"
#include "st_context.h"
#include "st_program.h"
@ -79,8 +80,6 @@ is_identity(const GLfloat m[16])
static void
make_state_key(GLcontext *ctx, struct state_key *key)
{
/*GLuint i, j;*/
memset(key, 0, sizeof(*key));
if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
@ -189,6 +188,8 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
inst[ic].SrcReg[0].Index = FRAG_RESULT_COLR;
ic++;
/* XXX reimplement in terms of MUL/MAD (see t_vp_build.c) */
/* DP4 result.color.x, tmp0, matrow0; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
@ -268,6 +269,9 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
/**
* Update st->pixel_xfer.program in response to new pixel-transfer state.
*/
static void
update_pixel_transfer(struct st_context *st)
{
@ -277,14 +281,14 @@ update_pixel_transfer(struct st_context *st)
make_state_key(st->ctx, &key);
fp = (struct gl_fragment_program *)
_mesa_search_program_cache(st->pixel_transfer_cache, &key, sizeof(key));
_mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
if (!fp) {
fp = get_pixel_transfer_program(st->ctx, &key);
_mesa_program_cache_insert(st->ctx, st->pixel_transfer_cache,
_mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
&key, sizeof(key), &fp->Base);
}
st->pixel_transfer_program = fp;
st->pixel_xfer.program = (struct st_fragment_program *) fp;
}

View file

@ -182,30 +182,48 @@ make_drawpix_fragment_shader(struct st_context *st)
{
GLcontext *ctx = st->ctx;
struct st_fragment_program *stfp;
struct gl_program *p;
/*
* XXX Use st_program's serial numbers to determine when the
* user-provided program and pixel-transfer program to avoid
* needless combining/translation here.
*/
if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
&& st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
/* the pixel tranfer program has not changed and the user-defined
* shader has not changed, so re-use the combined program.
*/
stfp = st->pixel_xfer.combined_prog;
}
else {
/* Concatenate the pixel transfer program with the current user-
* defined shader.
*/
stfp = (struct st_fragment_program *)
_mesa_combine_programs(ctx,
&st->pixel_xfer.program->Base.Base,
&st->fp->Base.Base);
p = _mesa_combine_programs(ctx,
&st->pixel_transfer_program->Base,
&ctx->FragmentProgram._Current->Base);
#if 0
_mesa_print_program(p);
printf("InputsRead: 0x%x\n", p->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
_mesa_print_parameter_list(p->Parameters);
{
struct gl_program *p = &stfp->Base.Base;
_mesa_print_program(p);
printf("InputsRead: 0x%x\n", p->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
_mesa_print_parameter_list(p->Parameters);
}
#endif
stfp = (struct st_fragment_program *) p;
st_translate_fragment_program(st, stfp, NULL,
stfp->tokens, ST_MAX_SHADER_TOKENS);
/* translate to TGSI tokens */
st_translate_fragment_program(st, stfp, NULL,
stfp->tokens, ST_MAX_SHADER_TOKENS);
/* save new program, update serial numbers */
st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
st->pixel_xfer.user_prog_sn = st->fp->serialNo;
st->pixel_xfer.combined_prog_sn = stfp->serialNo;
st->pixel_xfer.combined_prog = stfp;
}
st_upload_constants( st, p->Parameters, PIPE_SHADER_FRAGMENT );
/* Ideally we'd have updated the pipe constants during the normal
* st/atom mechanism. But we can't since this is specific to glDrawPixels.
*/
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
return stfp;
}

View file

@ -44,6 +44,8 @@
#include "st_atom_shader.h"
static GLuint SerialNo = 1;
/**
* Called via ctx->Driver.BindProgram() to bind an ARB vertex or
@ -91,7 +93,7 @@ static struct gl_program *st_new_program( GLcontext *ctx,
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
prog->serialNo = 1;
prog->serialNo = SerialNo++;
return _mesa_init_vertex_program( ctx,
&prog->Base,
@ -103,7 +105,7 @@ static struct gl_program *st_new_program( GLcontext *ctx,
case GL_FRAGMENT_PROGRAM_NV: {
struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
prog->serialNo = 1;
prog->serialNo = SerialNo++;
return _mesa_init_fragment_program( ctx,
&prog->Base,

View file

@ -92,7 +92,7 @@ struct st_context *st_create_context( GLcontext *ctx,
st->haveFramebufferRegions = GL_TRUE;
st->pixel_transfer_cache = _mesa_new_program_cache();
st->pixel_xfer.cache = _mesa_new_program_cache();
#if 0
st_init_cb_clear( st );
@ -126,7 +126,7 @@ void st_destroy_context( struct st_context *st )
#endif
cso_cache_delete( st->cache );
_mesa_delete_program_cache(st->ctx, st->pixel_transfer_cache);
_mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
st->pipe->destroy( st->pipe );
FREE( st );

View file

@ -133,8 +133,14 @@ struct st_context
struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */
struct gl_fragment_program *pixel_transfer_program;
struct gl_program_cache *pixel_transfer_cache;
struct {
struct gl_program_cache *cache;
struct st_fragment_program *program; /**< cur pixel transfer prog */
GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
GLuint user_prog_sn; /**< user fragment program serial no. */
struct st_fragment_program *combined_prog;
GLuint combined_prog_sn;
} pixel_xfer;
/**
* Buffer object which stores the ctx->Current.Attrib[] values.