diff options
author | Ben Skeggs <[email protected]> | 2007-01-21 09:31:00 +1100 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2007-01-21 09:31:00 +1100 |
commit | 029b81742ad474245e18e0b629d669afe588111c (patch) | |
tree | 2c3ec5dcd93234665077d2af024e6f392e249892 | |
parent | ee3d0617f923cd4bcc8bfdc1ce878648480c2679 (diff) |
nouveau: kill off shader pass1.
It sucks, and we have someone who can do a much better job than I can starting
work on it soon. alloc_temp/free_temp is left in pass2 to workaround fragprog
temps/outputs overlapping, but this all belongs in the optimiser.
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader_1.c | 304 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader_2.c | 16 |
3 files changed, 1 insertions, 323 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index dfa53cad957..4b94625286f 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -56,10 +56,6 @@ typedef struct _nouveauShader { int hw_index_cnt; } params[NVS_MAX_CONSTS]; - struct { - int last_use; - } temps[NVS_MAX_TEMPS]; - /* Pass-private data */ void *pass_rec; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c index 5de9017f580..90c57d38078 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c @@ -1,316 +1,12 @@ -/* - * Copyright (C) 2006 Ben Skeggs. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/* - * Authors: - * Ben Skeggs <[email protected]> - */ - #include "glheader.h" #include "macros.h" #include "enums.h" #include "nouveau_shader.h" -#define PASS1_OK 0 -#define PASS1_KILL 1 -#define PASS1_FAIL 2 - -struct pass1_rec { - unsigned int temp[NVS_MAX_TEMPS]; - unsigned int result[NVS_MAX_ATTRIBS]; - unsigned int address[NVS_MAX_ADDRESS]; - unsigned int cc[2]; -}; - -static void -pass1_remove_fragment(nvsPtr nvs, nvsFragmentList *item) -{ - if (item->prev) item->prev->next = item->next; - if (item->next) item->next->prev = item->prev; - if (nvs->list_head == item) nvs->list_head = item->next; - if (nvs->list_tail == item) nvs->list_tail = item->prev; - - nvs->inst_count--; -} - -static int -pass1_result_needed(struct pass1_rec *rec, nvsInstruction *inst) -{ - if (inst->cond_update && rec->cc[inst->cond_reg]) - return 1; - /* Only write components that are read later */ - if (inst->dest.file == NVS_FILE_TEMP) - return (inst->mask & rec->temp[inst->dest.index]); - if (inst->dest.file == NVS_FILE_ADDRESS) - return (inst->mask & rec->address[inst->dest.index]); - /* No point writing result components that are written later */ - if (inst->dest.file == NVS_FILE_RESULT) - return (inst->mask & ~rec->result[inst->dest.index]); - assert(0); -} - -static void -pass1_track_result(struct pass1_rec *rec, nvsInstruction *inst) -{ - if (inst->cond_test) - rec->cc[inst->cond_reg] = 1; - if (inst->dest.file == NVS_FILE_TEMP) { - inst->mask &= rec->temp[inst->dest.index]; - } else if (inst->dest.file == NVS_FILE_RESULT) { - inst->mask &= ~rec->result[inst->dest.index]; - rec->result[inst->dest.index] |= inst->mask; - } else if (inst->dest.file == NVS_FILE_ADDRESS) { - inst->mask &= rec->address[inst->dest.index]; - } -} - -static void -pass1_track_source(nouveauShader *nvs, nvsInstruction *inst, int pos, - unsigned int read) -{ - struct pass1_rec *rec = nvs->pass_rec; - nvsRegister *src = &inst->src[pos]; - unsigned int really_read = 0; - int i,sc; - - /* Account for swizzling */ - for (i=0; i<4; i++) - if (read & (1<<i)) really_read |= (1 << src->swizzle[i]); - - /* Track register reads */ - if (src->file == NVS_FILE_TEMP) { - if (nvs->temps[src->index].last_use == -1) - nvs->temps[src->index].last_use = inst->header.position; - rec->temp [src->index] |= really_read; - } else if (src->indexed) { - rec->address[src->addr_reg] |= (1<<src->addr_comp); - } - - /* Modify swizzle to only access read components */ - /* Find a component that is used.. */ - for (sc=0;sc<4;sc++) - if (really_read & (1<<sc)) - break; - /* Now set all unused components to that value */ - for (i=0;i<4;i++) - if (!(read & (1<<i))) src->swizzle[i] = sc; -} - -static int -pass1_check_instruction(nouveauShader *nvs, nvsInstruction *inst) -{ - struct pass1_rec *rec = nvs->pass_rec; - unsigned int read0, read1, read2; - - if (inst->op != NVS_OP_KIL) { - if (!pass1_result_needed(rec, inst)) - return PASS1_KILL; - } - pass1_track_result(rec, inst); - - read0 = read1 = read2 = 0; - - switch (inst->op) { - case NVS_OP_FLR: - case NVS_OP_FRC: - case NVS_OP_MOV: - case NVS_OP_SSG: - case NVS_OP_ARL: - read0 = inst->mask; - break; - case NVS_OP_ADD: - case NVS_OP_MAX: - case NVS_OP_MIN: - case NVS_OP_MUL: - case NVS_OP_SEQ: - case NVS_OP_SFL: - case NVS_OP_SGE: - case NVS_OP_SGT: - case NVS_OP_SLE: - case NVS_OP_SLT: - case NVS_OP_SNE: - case NVS_OP_STR: - case NVS_OP_SUB: - read0 = inst->mask; - read1 = inst->mask; - break; - case NVS_OP_CMP: - case NVS_OP_LRP: - case NVS_OP_MAD: - read0 = inst->mask; - read1 = inst->mask; - read2 = inst->mask; - break; - case NVS_OP_XPD: - if (inst->mask & SMASK_X) read0 |= SMASK_Y|SMASK_Z; - if (inst->mask & SMASK_Y) read0 |= SMASK_X|SMASK_Z; - if (inst->mask & SMASK_Z) read0 |= SMASK_X|SMASK_Y; - read1 = read0; - break; - case NVS_OP_COS: - case NVS_OP_EX2: - case NVS_OP_EXP: - case NVS_OP_LG2: - case NVS_OP_LOG: - case NVS_OP_RCC: - case NVS_OP_RCP: - case NVS_OP_RSQ: - case NVS_OP_SCS: - case NVS_OP_SIN: - read0 = SMASK_X; - break; - case NVS_OP_POW: - read0 = SMASK_X; - read1 = SMASK_X; - break; - case NVS_OP_DIV: - read0 = inst->mask; - read1 = SMASK_X; - break; - case NVS_OP_DP2: - read0 = SMASK_X|SMASK_Y; - read1 = SMASK_X|SMASK_Y; - break; - case NVS_OP_DP3: - case NVS_OP_RFL: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - read1 = SMASK_X|SMASK_Y|SMASK_Z; - break; - case NVS_OP_DP4: - read0 = SMASK_ALL; - read1 = SMASK_ALL; - break; - case NVS_OP_DPH: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - read1 = SMASK_ALL; - break; - case NVS_OP_DST: - if (inst->mask & SMASK_Y) read0 = read1 = SMASK_Y; - if (inst->mask & SMASK_Z) read0 |= SMASK_Z; - if (inst->mask & SMASK_W) read1 |= SMASK_W; - break; - case NVS_OP_NRM: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - break; - case NVS_OP_PK2H: - case NVS_OP_PK2US: - read0 = SMASK_X|SMASK_Y; - break; - case NVS_OP_DDX: - case NVS_OP_DDY: - case NVS_OP_UP2H: - case NVS_OP_UP2US: - case NVS_OP_PK4B: - case NVS_OP_PK4UB: - case NVS_OP_UP4B: - case NVS_OP_UP4UB: - read0 = SMASK_ALL; - break; - case NVS_OP_X2D: - read1 = SMASK_X|SMASK_Y; - if (inst->mask & (SMASK_X|SMASK_Z)) { - read0 |= SMASK_X; - read2 |= SMASK_X|SMASK_Y; - } - if (inst->mask & (SMASK_Y|SMASK_W)) { - read0 |= SMASK_Y; - read2 |= SMASK_Z|SMASK_W; - } - break; - case NVS_OP_LIT: - read0 |= SMASK_X|SMASK_Y|SMASK_W; - break; - case NVS_OP_TEX: - case NVS_OP_TXP: - case NVS_OP_TXL: - case NVS_OP_TXB: - read0 = SMASK_ALL; - break; - case NVS_OP_TXD: - read0 = SMASK_ALL; - read1 = SMASK_ALL; - read2 = SMASK_ALL; - break; - case NVS_OP_KIL: - break; - default: - fprintf(stderr, "Unknown sop=%d", inst->op); - return PASS1_FAIL; - } - - /* Any values that are written by this inst can't have been read further up */ - if (inst->dest.file == NVS_FILE_TEMP) - rec->temp[inst->dest.index] &= ~inst->mask; - - if (read0) pass1_track_source(nvs, inst, 0, read0); - if (read1) pass1_track_source(nvs, inst, 1, read1); - if (read2) pass1_track_source(nvs, inst, 2, read2); - - return PASS1_OK; -} - -/* Some basic dead code elimination - * - Remove unused instructions - * - Don't write unused register components - * - Modify swizzles to not reference unneeded components. - */ GLboolean nouveau_shader_pass1(nvsPtr nvs) { - nvsFragmentList *list = nvs->list_tail; - int i; - - for (i=0; i<NVS_MAX_TEMPS; i++) - nvs->temps[i].last_use = -1; - - nvs->pass_rec = calloc(1, sizeof(struct pass1_rec)); - - while (list) { - assert(list->fragment->type == NVS_INSTRUCTION); - - switch(pass1_check_instruction(nvs, (nvsInstruction *)list->fragment)) { - case PASS1_OK: - break; - case PASS1_KILL: - pass1_remove_fragment(nvs, list); - break; - case PASS1_FAIL: - default: - free(nvs->pass_rec); - nvs->pass_rec = NULL; - return GL_FALSE; - } - - list = list->prev; - } - - free(nvs->pass_rec); - nvs->pass_rec = NULL; return GL_TRUE; } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c index 2177413b66e..0476b05f583 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c @@ -68,29 +68,15 @@ pass2_alloc_hw_temp(nvsPtr nvs) return -1; } -static void -pass2_free_hw_temp(nvsPtr nvs, int reg) -{ - struct pass2_rec *rec = nvs->pass_rec; - rec->hw_temps[reg] = 0; -} - static nvsRegister pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg) { struct pass2_rec *rec = nvs->pass_rec; if (reg.file == NVS_FILE_TEMP) { - int hwidx; - if (rec->temps[reg.index] == -1) rec->temps[reg.index] = pass2_alloc_hw_temp(nvs); - hwidx = rec->temps[reg.index]; - - if (nvs->temps[reg.index].last_use <= inst->header.position) - pass2_free_hw_temp(nvs, hwidx); - - reg.index = hwidx; + reg.index = rec->temps[reg.index]; } return reg; |