diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader.c | 9 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader.h | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader_0.c | 145 |
3 files changed, 110 insertions, 47 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/src/mesa/drivers/dri/nouveau/nouveau_shader.c index cdb79fca1e6..c78b72bd113 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.c @@ -126,15 +126,16 @@ nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs) /* Update state parameters */ plist = nvs->mesa.vp.Base.Parameters; _mesa_load_state_parameters(ctx, plist); - for (i=0; i<plist->NumParameters; i++) { + for (i=0; i<nvs->param_high; i++) { + if (!nvs->params[i].in_use) + continue; + if (!nvs->on_hardware) { /* if we've been kicked off the hardware there's no guarantee our * consts are still there.. reupload them all */ nvs->func->UpdateConst(ctx, nvs, i); - } else if (plist->Parameters[i].Type == PROGRAM_STATE_VAR) { - if (!nvs->params[i].source_val) /* this is a workaround when consts aren't alloc'd from id=0.. */ - continue; + } else if (nvs->params[i].source_val) { /* update any changed state parameters */ if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val)) nvs->func->UpdateConst(ctx, nvs, i); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index e2515c1c79a..68007dd1eac 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -58,6 +58,8 @@ typedef struct _nouveauShader { int vp_attrib_map[NVS_MAX_ATTRIBS]; struct { + GLboolean in_use; + GLfloat *source_val; /* NULL if invariant */ float val[4]; /* Hardware-specific tracking, currently only nv30_fragprog @@ -66,6 +68,7 @@ typedef struct _nouveauShader { int *hw_index; int hw_index_cnt; } params[NVS_MAX_CONSTS]; + int param_high; /* Pass-private data */ void *pass_rec; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c index 9f32cd8c118..fb6e0b05c3a 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c @@ -113,6 +113,10 @@ static nvsCond _tx_mesa_condmask[] = { struct pass0_rec { int nvs_ipos; int next_temp; + + int mesa_const_base; + int mesa_const_last; + int swzconst_done; int swzconst_id; nvsRegister const_half; @@ -308,8 +312,8 @@ pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg, static void pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) { + struct pass0_rec *rec = nvs->pass_rec; struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; - struct gl_program_parameter_list *p = mesa->Parameters; int i; *reg = nvr_unused; @@ -332,34 +336,16 @@ pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) NVS_FR_UNKNOWN; } break; - /* All const types seem to get shoved into here, not really sure why */ case PROGRAM_STATE_VAR: - switch (p->Parameters[src->Index].Type) { - case PROGRAM_NAMED_PARAM: - case PROGRAM_CONSTANT: - nvs->params[src->Index].source_val = NULL; - COPY_4V(nvs->params[src->Index].val, - p->ParameterValues[src->Index]); - break; - case PROGRAM_STATE_VAR: - nvs->params[src->Index].source_val = - p->ParameterValues[src->Index]; - break; - default: - fprintf(stderr, "Unknown parameter type %d\n", - p->Parameters[src->Index].Type); - assert(0); - break; + case PROGRAM_NAMED_PARAM: + case PROGRAM_CONSTANT: + reg->file = NVS_FILE_CONST; + reg->index = src->Index + rec->mesa_const_base; + reg->indexed = src->RelAddr; + if (reg->indexed) { + reg->addr_reg = 0; + reg->addr_comp = NVS_SWZ_X; } - - if (src->RelAddr) { - reg->indexed = 1; - reg->addr_reg = 0; - reg->addr_comp = NVS_SWZ_X; - } else - reg->indexed = 0; - reg->file = NVS_FILE_CONST; - reg->index = src->Index; break; case PROGRAM_TEMPORARY: reg->file = NVS_FILE_TEMP; @@ -568,7 +554,6 @@ pass0_emulate_instruction(nouveauShader *nvs, nvsFunc *shader = nvs->func; nvsRegister src[3], dest, temp; nvsInstruction *nvsinst; - struct pass0_rec *rec = nvs->pass_rec; unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); int i, sat; @@ -825,6 +810,73 @@ pass0_build_attrib_map(nouveauShader *nvs, struct gl_vertex_program *vp) } } +static void +pass0_prealloc_mesa_consts(nouveauShader *nvs) +{ + struct pass0_rec *rec = nvs->pass_rec; + struct gl_program *prog = &nvs->mesa.vp.Base; + struct prog_instruction *inst = prog->Instructions; + struct gl_program_parameter_list *plist = prog->Parameters; + int i; + + /*XXX: not a good idea, params->hw_index is malloc'd */ + memset(nvs->params, 0x00, sizeof(nvs->params)); + + /* When doing relative addressing on constants, the hardware needs us + * to fill the "const id" field with a positive value. Determine the + * most negative index that is used so that all accesses to a + * mesa-provided constant can be rebased to a positive index. + */ + while (inst->Opcode != OPCODE_END) { + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) { + struct prog_src_register *src = &inst->SrcReg[i]; + + switch (src->File) { + case PROGRAM_STATE_VAR: + case PROGRAM_CONSTANT: + case PROGRAM_NAMED_PARAM: + if (src->RelAddr && src->Index < 0) { + int base = src->Index * -1; + if (rec->mesa_const_base < base) + rec->mesa_const_base = base; + } + break; + default: + break; + } + } + + inst++; + } + + /* Init all const tracking/alloc info from the parameter list, rather + * than doing it as we translate the program. Otherwise we can't get + * at the correct constant info when relative addressing is being used. + */ + rec->mesa_const_last = plist->NumParameters + rec->mesa_const_base; + nvs->param_high = rec->mesa_const_last; + for (i=0; i<plist->NumParameters; i++) { + int hw = rec->mesa_const_base + i; + + switch (plist->Parameters[i].Type) { + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + nvs->params[hw].in_use = GL_TRUE; + nvs->params[hw].source_val = plist->ParameterValues[i]; + COPY_4V(nvs->params[hw].val, plist->ParameterValues[i]); + break; + case PROGRAM_CONSTANT: + nvs->params[hw].in_use = GL_TRUE; + nvs->params[hw].source_val = NULL; + COPY_4V(nvs->params[hw].val, plist->ParameterValues[i]); + break; + default: + assert(0); + break; + } + } +} + GLboolean nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) { @@ -835,12 +887,28 @@ nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) struct pass0_rec *rec; int ret = GL_FALSE; + rec = CALLOC_STRUCT(pass0_rec); + if (!rec) + return GL_FALSE; + + rec->next_temp = prog->NumTemporaries; + nvs->pass_rec = rec; + + nvs->program_tree = (nvsFragmentHeader*) + pass0_create_subroutine(nvs, "program body"); + if (!nvs->program_tree) { + FREE(rec); + return GL_FALSE; + } + switch (prog->Target) { case GL_VERTEX_PROGRAM_ARB: nvs->func = &nmesa->VPfunc; if (vp->IsPositionInvariant) _mesa_insert_mvp_code(ctx, vp); + pass0_prealloc_mesa_consts(nvs); + #if 0 if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED) pass0_insert_ff_clip_planes(); @@ -853,29 +921,20 @@ nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) if (fp->FogOption != GL_NONE) _mesa_append_fog_code(ctx, fp); + pass0_prealloc_mesa_consts(nvs); break; default: fprintf(stderr, "Unknown program type %d", prog->Target); + FREE(rec); + /* DESTROY TREE!! */ return GL_FALSE; } nvs->func->card_priv = &nvs->card_priv; - rec = CALLOC_STRUCT(pass0_rec); - if (rec) { - rec->next_temp = prog->NumTemporaries; - nvs->pass_rec = rec; - - nvs->program_tree = (nvsFragmentHeader*) - pass0_create_subroutine(nvs, "program body"); - if (nvs->program_tree) { - ret = pass0_translate_instructions(nvs, - 0, 0, - nvs->program_tree); - /*XXX: if (!ret) DESTROY TREE!!! */ - } - FREE(rec); - } + ret = pass0_translate_instructions(nvs, 0, 0, nvs->program_tree); + /*XXX: if (!ret) DESTROY TREE!!! */ + FREE(rec); return ret; } |