Implement projective texture sampling, 3D textures. Disable some debug output.
[mesa.git] / src / mesa / shader / slang / slang_link2.c
index d3d53942654e7c7e87356a0b7a6a6416cd008c4b..3a5bce009951a9e39acf059fe1849a34d483d61f 100644 (file)
@@ -138,6 +138,7 @@ is_uniform(enum register_file file)
            file == PROGRAM_STATE_VAR ||
            file == PROGRAM_NAMED_PARAM ||
            file == PROGRAM_CONSTANT ||
+           file == PROGRAM_SAMPLER ||
            file == PROGRAM_UNIFORM);
 }
 
@@ -147,15 +148,21 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 {
    GLuint *map, i;
 
+#if 0
+   printf("================ pre link uniforms ===============\n");
+   _mesa_print_parameter_list(shProg->Uniforms);
+#endif
+
    map = (GLuint *) malloc(prog->Parameters->NumParameters * sizeof(GLuint));
    if (!map)
       return GL_FALSE;
 
-   for (i = 0; i < prog->Parameters->NumParameters; i++) {
+   for (i = 0; i < prog->Parameters->NumParameters; /* incr below*/) {
       /* see if this uniform is in the linked uniform list */
       const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
       const GLfloat *pVals = prog->Parameters->ParameterValues[i];
       GLint j;
+      GLint size;
 
       /* sanity check */
       assert(is_uniform(p->Type));
@@ -177,13 +184,16 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 
       if (j >= 0) {
          /* already in list, check size XXX check this */
+#if 0
          assert(p->Size == shProg->Uniforms->Parameters[j].Size);
+#endif
       }
       else {
          /* not already in linked list */
          switch (p->Type) {
          case PROGRAM_ENV_PARAM:
             j = _mesa_add_named_parameter(shProg->Uniforms, p->Name, pVals);
+            break;
          case PROGRAM_CONSTANT:
             j = _mesa_add_named_constant(shProg->Uniforms, p->Name, pVals, p->Size);
             break;
@@ -193,6 +203,9 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
          case PROGRAM_UNIFORM:
             j = _mesa_add_uniform(shProg->Uniforms, p->Name, p->Size);
             break;
+         case PROGRAM_SAMPLER:
+            j = _mesa_add_sampler(shProg->Uniforms, p->Name);
+            break;
          default:
             abort();
          }
@@ -200,11 +213,32 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
       }
       ASSERT(j >= 0);
 
-      map[i] = j;
+      size = p->Size;
+      while (size > 0) {
+         map[i] = j;
+         i++;
+         j++;
+         size -= 4;
+      }
+
    }
 
+#if 0
+   printf("================ post link uniforms ===============\n");
+   _mesa_print_parameter_list(shProg->Uniforms);
+#endif
 
-   /* OK, now scan the program/shader instructions looking for varying vars,
+#if 0
+   {
+      GLuint i;
+      for (i = 0; i < prog->Parameters->NumParameters; i++) {
+         printf("map[%d] = %d\n", i, map[i]);
+      }
+      _mesa_print_parameter_list(shProg->Uniforms);
+   }
+#endif
+
+   /* OK, now scan the program/shader instructions looking for uniform vars,
     * replacing the old index with the new index.
     */
    for (i = 0; i < prog->NumInstructions; i++) {
@@ -220,7 +254,14 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
             inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ];
          }
       }
-      /* XXX update program OutputsWritten, InputsRead */
+
+      if (inst->Opcode == OPCODE_TEX ||
+          inst->Opcode == OPCODE_TXB ||
+          inst->Opcode == OPCODE_TXP) {
+         printf("====== remap sampler from %d to %d\n",
+                inst->Sampler, map[ inst->Sampler ]);
+         inst->Sampler = map[ inst->Sampler ];
+      }
    }
 
    free(map);
@@ -233,7 +274,7 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
  * XXX Temporary
  */
 static void
-slang_resolve_branches(struct gl_program *prog)
+_slang_resolve_branches(struct gl_program *prog)
 {
    struct target {
       const char *Name;
@@ -269,6 +310,63 @@ slang_resolve_branches(struct gl_program *prog)
 }
 
 
+/**
+ * Scan program for texture instructions, lookup sampler/uniform's value
+ * to determine which texture unit to use.
+ * Also, update the program's TexturesUsed[] array.
+ */
+void
+_slang_resolve_samplers(struct gl_shader_program *shProg,
+                        struct gl_program *prog)
+{
+   GLuint i;
+
+   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+      prog->TexturesUsed[i] = 0;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      if (inst->Opcode == OPCODE_TEX ||
+          inst->Opcode == OPCODE_TXB ||
+          inst->Opcode == OPCODE_TXP) {
+         GLint sampleUnit = (GLint) shProg->Uniforms->ParameterValues[inst->Sampler][0];
+         assert(sampleUnit < MAX_TEXTURE_IMAGE_UNITS);
+         inst->TexSrcUnit = sampleUnit;
+
+         prog->TexturesUsed[inst->TexSrcUnit] |= (1 << inst->TexSrcTarget);
+      }
+   }
+}
+
+
+/**
+ * Scan program instructions to update the program's InputsRead and
+ * OutputsWritten fields.
+ */
+static void
+_slang_update_inputs_outputs(struct gl_program *prog)
+{
+   GLuint i, j;
+
+   prog->InputsRead = 0x0;
+   prog->OutputsWritten = 0x0;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      const struct prog_instruction *inst = prog->Instructions + i;
+      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+      for (j = 0; j < numSrc; j++) {
+         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+            prog->InputsRead |= 1 << inst->SrcReg[j].Index;
+         }
+      }
+      if (inst->DstReg.File == PROGRAM_OUTPUT) {
+         prog->OutputsWritten |= 1 << inst->DstReg.Index;
+      }
+   }
+}
+
+
+
 /** cast wrapper */
 static struct gl_vertex_program *
 vertex_program(struct gl_program *prog)
@@ -363,8 +461,14 @@ _slang_link2(GLcontext *ctx,
    shProg->VertexProgram->Base.Parameters = shProg->Uniforms;
    shProg->FragmentProgram->Base.Parameters = shProg->Uniforms;
 
-   slang_resolve_branches(&shProg->VertexProgram->Base);
-   slang_resolve_branches(&shProg->FragmentProgram->Base);
+   _slang_resolve_branches(&shProg->VertexProgram->Base);
+   _slang_resolve_branches(&shProg->FragmentProgram->Base);
+#if 1
+   _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
+   _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
+#endif
+   _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
+   _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
 
 #if 1
    printf("************** original fragment program\n");