nouveau: kill off shader pass1.
authorBen Skeggs <darktama@iinet.net.au>
Sat, 20 Jan 2007 22:31:00 +0000 (09:31 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Sat, 20 Jan 2007 22:31:00 +0000 (09:31 +1100)
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.

src/mesa/drivers/dri/nouveau/nouveau_shader.h
src/mesa/drivers/dri/nouveau/nouveau_shader_1.c
src/mesa/drivers/dri/nouveau/nouveau_shader_2.c

index dfa53cad95742ed277f592303975852d9419d4d0..4b94625286f6ebda3ebabe960d54793e74eb9298 100644 (file)
@@ -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;
 
index 5de9017f5801b1ee29c98f603d8984a69e88d6da..90c57d3807801100fd2eac91d2c6ca4d272e064f 100644 (file)
-/*
- * 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 <darktama@iinet.net.au>
- */
-
 #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;
 }
index 2177413b66e8d46fc3a6edfbd9dfac40a0cc3df7..0476b05f583ef2a2c4c1683aa34545b95ebd24cf 100644 (file)
@@ -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;