Checkpoint: re-org of (global) variable allocation code. More to come...
[mesa.git] / src / mesa / shader / slang / slang_emit.c
index 8b0999dfcc27807b156600a320d79c5bc45113bf..4c952e2e0ae08ef12ef18cb5286bcb70c1ffa918 100644 (file)
@@ -92,6 +92,8 @@ static slang_ir_info IrInfo[] = {
    { IR_NOT, "IR_NOT", 0, 1, 1 },
    { IR_VAR, "IR_VAR", 0, 0, 0 },
    { IR_VAR_DECL, "IR_VAR_DECL", 0, 0, 0 },
+   { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
+   { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 2 },
    { IR_FLOAT, "IR_FLOAT", 0, 0, 0 },
    { IR_FIELD, "IR_FIELD", 0, 0, 0 },
    { IR_NOP, NULL, OPCODE_NOP, 0, 0 }
@@ -182,6 +184,7 @@ storage_string(const slang_ir_storage *st)
       "UNIFORM",
       "WRITE_ONLY",
       "ADDRESS",
+      "SAMPLER",
       "UNDEFINED"
    };
    static char s[100];
@@ -192,6 +195,7 @@ storage_string(const slang_ir_storage *st)
       sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
               st->Index + st->Size - 1);
 #endif
+   assert(st->File < sizeof(files) / sizeof(files[0]));
    sprintf(s, "%s[%d]", files[st->File], st->Index);
    return s;
 }
@@ -247,8 +251,7 @@ _slang_sizeof_type_specifier(const slang_type_specifier *spec)
    case slang_spec_samplerCube:
    case slang_spec_sampler1DShadow:
    case slang_spec_sampler2DShadow:
-      abort();
-      return 0;
+      return 1; /* special case */
    case slang_spec_struct:
       return sizeof_struct(spec->_struct);
    case slang_spec_array:
@@ -261,7 +264,6 @@ _slang_sizeof_type_specifier(const slang_type_specifier *spec)
 }
 
 
-
 static GLuint
 sizeof_type(const slang_fully_specified_type *t)
 {
@@ -269,6 +271,23 @@ sizeof_type(const slang_fully_specified_type *t)
 }
 
 
+static GLboolean
+is_sampler_type(const slang_fully_specified_type *t)
+{
+   switch (t->specifier.type) {
+   case slang_spec_sampler1D:
+   case slang_spec_sampler2D:
+   case slang_spec_sampler3D:
+   case slang_spec_samplerCube:
+   case slang_spec_sampler1DShadow:
+   case slang_spec_sampler2DShadow:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
 #define IND 0
 void
 slang_print_ir(const slang_ir_node *n, int indent)
@@ -370,6 +389,15 @@ alloc_temporary(slang_gen_context *gc, GLint size)
 }
 
 
+static GLint
+alloc_sampler(slang_gen_context *gc)
+{
+   GLint sampler = gc->NumSamplers;
+   gc->NumSamplers++;
+   return sampler;
+}
+
+
 static GLboolean
 is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
 {
@@ -392,87 +420,6 @@ free_temporary(slang_gen_context *gc, GLuint r, GLint size)
 }
 
 
-
-static GLint
-slang_find_input(GLenum target, const char *name, GLint index)
-{
-   struct input_info {
-      const char *Name;
-      GLuint Attrib;
-   };
-   static const struct input_info vertInputs[] = {
-      { "gl_Vertex", VERT_ATTRIB_POS },
-      { "gl_Normal", VERT_ATTRIB_NORMAL },
-      { "gl_Color", VERT_ATTRIB_COLOR0 },
-      { "gl_SecondaryColor", VERT_ATTRIB_COLOR1 },
-      { NULL, 0 }
-   };
-   static const struct input_info fragInputs[] = {
-      { NULL, 0 }
-   };
-   const struct input_info *inputs;
-   GLuint i;
-
-   if (target == GL_VERTEX_PROGRAM_ARB) {
-      inputs = vertInputs;
-   }
-   else {
-      assert(target == GL_FRAGMENT_PROGRAM_ARB);
-      inputs = fragInputs;
-   }
-
-   for (i = 0; inputs[i].Name; i++) {
-      if (strcmp(inputs[i].Name, name) == 0) {
-         /* found */
-         return inputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
-static GLint
-slang_find_output(GLenum target, const char *name, GLint index)
-{
-   struct output_info {
-      const char *Name;
-      GLuint Attrib;
-   };
-   static const struct output_info vertOutputs[] = {
-      { "gl_Position", VERT_RESULT_HPOS },
-      { "gl_FrontColor", VERT_RESULT_COL0 },
-      { "gl_BackColor", VERT_RESULT_BFC0 },
-      { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
-      { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
-      { "gl_TexCoord", VERT_RESULT_TEX0 }, /* XXX indexed */
-      { "gl_FogFragCoord", VERT_RESULT_FOGC },
-      { NULL, 0 }
-   };
-   static const struct output_info fragOutputs[] = {
-      { "gl_FragColor", FRAG_RESULT_COLR },
-      { NULL, 0 }
-   };
-   const struct output_info *outputs;
-   GLuint i;
-
-   if (target == GL_VERTEX_PROGRAM_ARB) {
-      outputs = vertOutputs;
-   }
-   else {
-      assert(target == GL_FRAGMENT_PROGRAM_ARB);
-      outputs = fragOutputs;
-   }
-
-   for (i = 0; outputs[i].Name; i++) {
-      if (strcmp(outputs[i].Name, name) == 0) {
-         /* found */
-         return outputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
 /**
  * Lookup a named constant and allocate storage for the parameter in
  * the given parameter list.
@@ -588,31 +535,6 @@ slang_alloc_uniform(struct gl_program *prog, const char *name, GLuint size)
 }
 
 
-static GLint
-slang_alloc_varying(struct gl_program *prog, const char *name)
-{
-   GLint i = _mesa_add_varying(prog->Varying, name, 4); /* XXX fix size */
-#if 0
-   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-#ifdef OLD_LINK
-      i += VERT_RESULT_VAR0;
-      prog->OutputsWritten |= (1 << i);
-#else
-      prog->OutputsWritten |= (1 << (i + VERT_RESULT_VAR0));
-#endif
-   }
-   else {
-#ifdef OLD_LINK
-      i += FRAG_ATTRIB_VAR0;
-      prog->InputsRead |= (1 << i);
-#else
-      prog->InputsRead |= (1 << (i + FRAG_ATTRIB_VAR0));
-#endif
-   }
-#endif
-   return i;
-}
-
 
 /**
  * Allocate temporary storage for an intermediate result (such as for
@@ -637,9 +559,6 @@ slang_alloc_temp_storage(slang_gen_context *gc, slang_ir_node *n, GLint size)
  *   2. Allocate storage for user-declared variables.
  *   3. Allocate intermediate/unnamed storage for complex expressions.
  *   4. other?
- *
- * If gc or prog is NULL, we may only be able to determine the Store->File
- * but not an Index (register).
  */
 void
 slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
@@ -666,7 +585,16 @@ slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
    if (n->Opcode == IR_VAR_DECL) {
       /* storage declaration */
       assert(n->Var);
-      if (n->Store->Index < 0) { /* XXX assert this? */
+      if (is_sampler_type(&n->Var->type)) {
+         /* i.e. "uniform sampler2D tex;" */
+         n->Store->File = PROGRAM_SAMPLER;
+         n->Store->Size = 1; /* never used */
+         n->Store->Index = alloc_sampler(gc);
+         n->Store->Index = slang_alloc_uniform(prog, (char *) n->Var->a_name, 1);
+         printf("********** Alloc sampler uniform %d\n", n->Store->Index);
+         abort(); /* this is a locally-declared sampler */
+      }
+      else if (n->Store->Index < 0) { /* XXX assert this? */
          assert(gc);
          n->Store->File = PROGRAM_TEMPORARY;
          n->Store->Size = sizeof_type(&n->Var->type);
@@ -682,11 +610,20 @@ slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
       return;
    }
 
-   if (n->Opcode == IR_VAR && n->Store->File == PROGRAM_UNDEFINED) {
+   /*
+   assert(!is_sampler_type(&n->Var->type));
+   */
+   assert(n->Opcode == IR_VAR);
+
+   assert(n->Store->File != PROGRAM_UNDEFINED);
+
+   if (n->Opcode == IR_VAR && (n->Store->File == PROGRAM_UNDEFINED
+                               || n->Store->Index < 0)) {
       /* try to determine the storage for this variable */
       GLint i;
 
       assert(n->Var);
+      assert(n->Store->Size > 0);
 
       if (n->Store->Size < 0) {
          /* determine var/storage size now */
@@ -704,25 +641,10 @@ slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
              n->Var->type.qualifier == slang_qual_const);
 #endif
 
-      i = slang_find_input(prog->Target, (char *) n->Var->a_name, 0);
-      if (i >= 0) {
-         n->Store->File = PROGRAM_INPUT;
-         n->Store->Index = i;
-         assert(n->Store->Size > 0);
-         prog->InputsRead |= (1 << i);
-         return;
-      }
-
-      i = slang_find_output(prog->Target, (char *) n->Var->a_name, 0);
-      if (i >= 0) {
-         n->Store->File = PROGRAM_OUTPUT;
-         n->Store->Index = i;
-         prog->OutputsWritten |= (1 << i);
-         return;
-      }
-
       i = slang_lookup_statevar((char *) n->Var->a_name, 0, prog->Parameters);
       if (i >= 0) {
+         assert(n->Store->File == PROGRAM_STATE_VAR /*||
+                                                      n->Store->File == PROGRAM_UNIFORM*/);
          n->Store->File = PROGRAM_STATE_VAR;
          n->Store->Index = i;
          return;
@@ -730,38 +652,12 @@ slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
 
       i = slang_lookup_constant((char *) n->Var->a_name, 0, prog->Parameters);
       if (i >= 0) {
+         assert(n->Store->File == PROGRAM_CONSTANT);
          n->Store->File = PROGRAM_CONSTANT;
          n->Store->Index = i;
          return;
       }
 
-      /* probably a uniform or varying */
-      if (n->Var->type.qualifier == slang_qual_uniform) {
-         GLint size = n->Store->Size;
-         assert(size > 0);
-         i = slang_alloc_uniform(prog, (char *) n->Var->a_name, size);
-         if (i >= 0) {
-            n->Store->File = PROGRAM_UNIFORM;
-            n->Store->Index = i;
-            return;
-         }
-      }
-      else if (n->Var->type.qualifier == slang_qual_varying) {
-         i = slang_alloc_varying(prog, (char *) n->Var->a_name);
-         if (i >= 0) {
-#ifdef OLD_LINK
-            if (prog->Target == GL_VERTEX_PROGRAM_ARB)
-               n->Store->File = PROGRAM_OUTPUT;
-            else
-               n->Store->File = PROGRAM_INPUT;
-#else
-            n->Store->File = PROGRAM_VARYING;
-#endif
-            n->Store->Index = i;
-            return;
-         }
-      }
-
       if (n->Store->File == PROGRAM_UNDEFINED && n->Store->Index < 0) {
          /* ordinary local var */
          assert(n->Store->Size > 0);
@@ -994,6 +890,39 @@ emit_jump(const char *target, struct gl_program *prog)
 }
 
 
+static struct prog_instruction *
+emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+   struct prog_instruction *inst;
+   if (n->Opcode == IR_TEX) {
+      inst = new_instruction(prog, OPCODE_TEX);
+   }
+   else {
+      assert(n->Opcode == IR_TEXB);
+      inst = new_instruction(prog, OPCODE_TXB);
+   }
+
+   if (!n->Store)
+      slang_alloc_temp_storage(gc, n, 4);
+
+   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+
+   /* Child[1] is the coord */
+   storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
+                      n->Children[1]->Swizzle);
+
+   /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */
+   assert(n->Children[0]->Store);
+   assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
+
+   inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
+   inst->TexSrcTarget = n->Children[0]->Store->Size;
+   inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
+                           * link time, using the sampler uniform's value.
+                           */
+   return inst;
+}
+
 
 static struct prog_instruction *
 emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
@@ -1108,6 +1037,9 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
    case IR_SIN:
    case IR_COS:
       return emit_unop(gc, n, prog);
+   case IR_TEX:
+   case IR_TEXB:
+      return emit_tex(gc, n, prog);
    case IR_NEG:
       return emit_negation(gc, n, prog);
    case IR_LABEL: