glsl: make sure we replace all output reads with temporaries
authorZack Rusin <zack@tungstengraphics.com>
Thu, 12 Jun 2008 22:53:52 +0000 (18:53 -0400)
committerZack Rusin <zack@tungstengraphics.com>
Thu, 12 Jun 2008 23:39:20 +0000 (19:39 -0400)
test in if.glsl

src/mesa/shader/programopt.c
src/mesa/shader/programopt.h
src/mesa/shader/slang/slang_compile.c

index 7d560c74a5430d78f03599ee0a62cfb6f000b9ed..da4e3fcfcfc88a21a88e5c61b16d62935e256f12 100644 (file)
@@ -367,20 +367,22 @@ _mesa_count_texture_instructions(struct gl_program *prog)
 
 
 /**
- * Scan/rewrite program to remove reads of varying (output) registers.
+ * Scan/rewrite program to remove reads of custom (output) registers.
+ * The passed type has to be either PROGRAM_VARYING or PROGRAM_OUTPUT.
  * In GLSL vertex shaders, varying vars can be read and written.
  * Normally, vertex varying vars are implemented as output registers.
  * On some hardware, trying to read an output register causes trouble.
  * So, rewrite the program to use a temporary register in this case.
  */
 void
-_mesa_remove_varying_reads(struct gl_program *prog)
+_mesa_remove_output_reads(struct gl_program *prog, enum register_file type)
 {
    GLuint i;
    GLint outputMap[VERT_RESULT_MAX];
    GLuint numVaryingReads = 0;
 
    assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+   assert(type == PROGRAM_UNIFORM || type == PROGRAM_OUTPUT);
 
    for (i = 0; i < VERT_RESULT_MAX; i++)
       outputMap[i] = -1;
@@ -391,7 +393,7 @@ _mesa_remove_varying_reads(struct gl_program *prog)
       const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
       GLuint j;
       for (j = 0; j < numSrc; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_VARYING) {
+         if (inst->SrcReg[j].File == type) {
             /* replace the read with a temp reg */
             const GLuint var = inst->SrcReg[j].Index;
             if (outputMap[var] == -1) {
@@ -414,7 +416,7 @@ _mesa_remove_varying_reads(struct gl_program *prog)
       const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
       GLuint j;
       for (j = 0; j < numSrc; j++) {
-         if (inst->DstReg.File == PROGRAM_VARYING &&
+         if (inst->DstReg.File == type &&
              outputMap[inst->DstReg.Index] >= 0) {
             /* change inst to write to the temp reg, instead of the varying */
             inst->DstReg.File = PROGRAM_TEMPORARY;
@@ -447,7 +449,7 @@ _mesa_remove_varying_reads(struct gl_program *prog)
          if (outputMap[var] >= 0) {
             /* MOV VAR[var], TEMP[tmp]; */
             inst->Opcode = OPCODE_MOV;
-            inst->DstReg.File = PROGRAM_VARYING;
+            inst->DstReg.File = type;
             inst->DstReg.Index = var;
             inst->SrcReg[0].File = PROGRAM_TEMPORARY;
             inst->SrcReg[0].Index = outputMap[var];
index 47ff2f0c7be118ed3b18f25120cdb1e5c681e731..11572e64f5a26f8889aa063e956d6afe1a96dfac 100644 (file)
@@ -40,6 +40,6 @@ extern void
 _mesa_count_texture_instructions(struct gl_program *prog);
 
 extern void
-_mesa_remove_varying_reads(struct gl_program *prog);
+_mesa_remove_output_reads(struct gl_program *prog, enum register_file type);
 
 #endif /* PROGRAMOPT_H */
index f2e8aab8b0cdd63545c4b6a76f0c2a529bbb608a..cdea1c5128771435f1e9d9cf0c62b274314c3364 100644 (file)
@@ -2212,7 +2212,8 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
       printf("Pre-remove output reads:\n");
       _mesa_print_program(shader->Programs[0]);
 #endif
-      _mesa_remove_varying_reads(shader->Programs[0]);
+      _mesa_remove_output_reads(shader->Programs[0], PROGRAM_VARYING);
+      _mesa_remove_output_reads(shader->Programs[0], PROGRAM_OUTPUT);
 #if 0
       printf("Post-remove output reads:\n");
       _mesa_print_program(shader->Programs[0]);