gallium/i915: overhaul of fragment shader compilation, constant/immediate allocation
authorBrian <brian@i915.localnet.net>
Fri, 22 Feb 2008 23:48:05 +0000 (16:48 -0700)
committerBrian <brian@i915.localnet.net>
Fri, 22 Feb 2008 23:48:05 +0000 (16:48 -0700)
Before, fragment shaders were translated to i915 hw code at bind time, rather
than create time.  Now there's an i915_fragment_shader struct with the expected
contents that's created by i915_create_fs_state().  Translation to i915 code
takes place there too.

Immediates are handled correctly now.  During program translation we keep
track of which constant buffer slots are free (i.e. not referenced by the
shader).  Then the TGSI immediates and ancillary immediates (introduced for
SIN/COS/etc) are put into those free slots.

When it's time to upload the constant buffer, use the fp->constant_flags[]
array to determine if we should grab an immediate from the shader, or a
user-defined parameter from the gallium constant buffer.

src/gallium/drivers/i915simple/i915_context.h
src/gallium/drivers/i915simple/i915_fpc.h
src/gallium/drivers/i915simple/i915_fpc_emit.c
src/gallium/drivers/i915simple/i915_fpc_translate.c
src/gallium/drivers/i915simple/i915_state.c
src/gallium/drivers/i915simple/i915_state_derived.c
src/gallium/drivers/i915simple/i915_state_emit.c

index 2d876925b2c1cd3730fda129f4aef95ec29e4731..5cc38cdc8517561fcd4f1ffac8493f961dfd8ed0 100644 (file)
 #define I915_MAX_CONSTANT  32
 
 
+/** See constant_flags[] below */
+#define I915_CONSTFLAG_USER 0x1f
+
+
+/**
+ * Subclass of pipe_shader_state
+ */
+struct i915_fragment_shader
+{
+   struct pipe_shader_state state;
+   uint *program;
+   uint program_len;
+
+   /**
+    * constants introduced during translation.
+    * These are placed at the end of the constant buffer and grow toward
+    * the beginning (eg: slot 31, 30 29, ...)
+    * User-provided constants start at 0.
+    * This allows both types of constants to co-exist (until there's too many)
+    * and doesn't require regenerating/changing the fragment program to
+    * shuffle constants around.
+    */
+   uint num_constants;
+   float constants[I915_MAX_CONSTANT][4];
+
+   /**
+    * Status of each constant
+    * if I915_CONSTFLAG_PARAM, the value must be taken from the corresponding
+    * slot of the user's constant buffer. (set by pipe->set_constant_buffer())
+    * Else, the bitmask indicates which components are occupied by immediates.
+    */
+   ubyte constant_flags[I915_MAX_CONSTANT];
+};
+
 
 struct i915_cache_context;
 
@@ -93,11 +127,6 @@ struct i915_state
    float constants[PIPE_SHADER_TYPES][I915_MAX_CONSTANT][4];
    /** number of constants passed in through a constant buffer */
    uint num_user_constants[PIPE_SHADER_TYPES];
-   /** user constants, plus extra constants from shader translation */
-   uint num_constants[PIPE_SHADER_TYPES];
-
-   uint *program;
-   uint program_len;
 
    /* texture sampler state */
    unsigned sampler[I915_TEX_UNITS][3];
@@ -187,7 +216,8 @@ struct i915_context
    const struct i915_sampler_state         *sampler[PIPE_MAX_SAMPLERS];
    const struct i915_depth_stencil_state   *depth_stencil;
    const struct i915_rasterizer_state      *rasterizer;
-   const struct pipe_shader_state *fs;
+
+   struct i915_fragment_shader *fs;
 
    struct pipe_blend_color blend_color;
    struct pipe_clip_state clip;
index 8c7b68aefb5907cc7f0f596fb1ab32236c21b7a3..250dfe6dbf0b22ab1f68713fa8e65a4aa2f0b979 100644 (file)
  * Program translation state
  */
 struct i915_fp_compile {
-   const struct pipe_shader_state *shader;
+   struct i915_fragment_shader *shader;  /* the shader we're compiling */
 
-   struct vertex_info *vertex_info;
+   boolean used_constants[I915_MAX_CONSTANT];
+
+   /** maps TGSI immediate index to constant slot */
+   uint num_immediates;
+   uint immediates_map[I915_MAX_CONSTANT];
+   float immediates[I915_MAX_CONSTANT][4];
+
+   boolean first_instruction;
 
    uint declarations[I915_PROGRAM_SIZE];
    uint program[I915_PROGRAM_SIZE];
@@ -57,11 +64,6 @@ struct i915_fp_compile {
    uint output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
    uint output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
 
-   /** points into the i915->current.constants array: */
-   float (*constants)[4];
-   uint num_constants;
-   uint constant_flags[I915_MAX_CONSTANT]; /**< status of each constant */
-
    uint *csr;            /**< Cursor, points into program. */
 
    uint *decl;           /**< Cursor, points into declarations. */
@@ -155,7 +157,9 @@ swizzle(int reg, uint x, uint y, uint z, uint w)
 /***********************************************************************
  * Public interface for the compiler
  */
-extern void i915_translate_fragment_program( struct i915_context *i915 );
+extern void
+i915_translate_fragment_program( struct i915_context *i915,
+                                 struct i915_fragment_shader *fs);
 
 
 
@@ -206,8 +210,5 @@ extern void i915_disassemble_program(const uint * program, uint sz);
 extern void
 i915_program_error(struct i915_fp_compile *p, const char *msg, ...);
 
-extern void
-i915_translate_fragment_program(struct i915_context *i915);
-
 
 #endif
index 74924ff0a1d69d7afe42ef5125885621792ff2c8..a59ee2340379c8f48472fcda3c849cff5ac5a87a 100644 (file)
@@ -61,8 +61,6 @@
                           (REG_NR_MASK << UREG_NR_SHIFT))
 
 
-#define I915_CONSTFLAG_PARAM 0x1f
-
 uint
 i915_get_temp(struct i915_fp_compile *p)
 {
@@ -235,6 +233,7 @@ uint i915_emit_texld( struct i915_fp_compile *p,
 uint
 i915_emit_const1f(struct i915_fp_compile * p, float c0)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    unsigned reg, idx;
 
    if (c0 == 0.0)
@@ -243,15 +242,15 @@ i915_emit_const1f(struct i915_fp_compile * p, float c0)
       return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE);
 
    for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
-      if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
+      if (ifs->constant_flags[reg] == I915_CONSTFLAG_USER)
          continue;
       for (idx = 0; idx < 4; idx++) {
-         if (!(p->constant_flags[reg] & (1 << idx)) ||
-             p->constants[reg][idx] == c0) {
-            p->constants[reg][idx] = c0;
-            p->constant_flags[reg] |= 1 << idx;
-            if (reg + 1 > p->num_constants)
-               p->num_constants = reg + 1;
+         if (!(ifs->constant_flags[reg] & (1 << idx)) ||
+             ifs->constants[reg][idx] == c0) {
+            ifs->constants[reg][idx] = c0;
+            ifs->constant_flags[reg] |= 1 << idx;
+            if (reg + 1 > ifs->num_constants)
+               ifs->num_constants = reg + 1;
             return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE);
          }
       }
@@ -264,6 +263,7 @@ i915_emit_const1f(struct i915_fp_compile * p, float c0)
 uint
 i915_emit_const2f(struct i915_fp_compile * p, float c0, float c1)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    unsigned reg, idx;
 
    if (c0 == 0.0)
@@ -277,16 +277,16 @@ i915_emit_const2f(struct i915_fp_compile * p, float c0, float c1)
       return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
 
    for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
-      if (p->constant_flags[reg] == 0xf ||
-          p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
+      if (ifs->constant_flags[reg] == 0xf ||
+          ifs->constant_flags[reg] == I915_CONSTFLAG_USER)
          continue;
       for (idx = 0; idx < 3; idx++) {
-         if (!(p->constant_flags[reg] & (3 << idx))) {
-            p->constants[reg][idx + 0] = c0;
-            p->constants[reg][idx + 1] = c1;
-            p->constant_flags[reg] |= 3 << idx;
-            if (reg + 1 > p->num_constants)
-               p->num_constants = reg + 1;
+         if (!(ifs->constant_flags[reg] & (3 << idx))) {
+            ifs->constants[reg][idx + 0] = c0;
+            ifs->constants[reg][idx + 1] = c1;
+            ifs->constant_flags[reg] |= 3 << idx;
+            if (reg + 1 > ifs->num_constants)
+               ifs->num_constants = reg + 1;
             return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, ONE);
          }
       }
@@ -302,25 +302,26 @@ uint
 i915_emit_const4f(struct i915_fp_compile * p,
                   float c0, float c1, float c2, float c3)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    unsigned reg;
 
    for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
-      if (p->constant_flags[reg] == 0xf &&
-          p->constants[reg][0] == c0 &&
-          p->constants[reg][1] == c1 &&
-          p->constants[reg][2] == c2 &&
-          p->constants[reg][3] == c3) {
+      if (ifs->constant_flags[reg] == 0xf &&
+          ifs->constants[reg][0] == c0 &&
+          ifs->constants[reg][1] == c1 &&
+          ifs->constants[reg][2] == c2 &&
+          ifs->constants[reg][3] == c3) {
          return UREG(REG_TYPE_CONST, reg);
       }
-      else if (p->constant_flags[reg] == 0) {
-
-         p->constants[reg][0] = c0;
-         p->constants[reg][1] = c1;
-         p->constants[reg][2] = c2;
-         p->constants[reg][3] = c3;
-         p->constant_flags[reg] = 0xf;
-         if (reg + 1 > p->num_constants)
-            p->num_constants = reg + 1;
+      else if (ifs->constant_flags[reg] == 0) {
+
+         ifs->constants[reg][0] = c0;
+         ifs->constants[reg][1] = c1;
+         ifs->constants[reg][2] = c2;
+         ifs->constants[reg][3] = c3;
+         ifs->constant_flags[reg] = 0xf;
+         if (reg + 1 > ifs->num_constants)
+            ifs->num_constants = reg + 1;
          return UREG(REG_TYPE_CONST, reg);
       }
    }
@@ -335,41 +336,3 @@ i915_emit_const4fv(struct i915_fp_compile * p, const float * c)
 {
    return i915_emit_const4f(p, c[0], c[1], c[2], c[3]);
 }
-
-
-#if 00000/*UNUSED*/
-/* Reserve a slot in the constant file for a Mesa state parameter.
- * These will later need to be tracked on statechanges, but that is
- * done elsewhere.
- */
-uint
-i915_emit_param4fv(struct i915_fp_compile * p, const float * values)
-{
-   struct i915_fragment_program *fp = p->fp;
-   int i;
-
-   for (i = 0; i < fp->nr_params; i++) {
-      if (fp->param[i].values == values)
-         return UREG(REG_TYPE_CONST, fp->param[i].reg);
-   }
-
-   if (p->constants->nr_constants == I915_MAX_CONSTANT ||
-       fp->nr_params == I915_MAX_CONSTANT) {
-      i915_program_error(p, "i915_emit_param4fv: out of constants\n");
-      return 0;
-   }
-
-   {
-      int reg = p->constants->nr_constants++;
-      int i = fp->nr_params++;
-
-      assert (p->constant_flags[reg] == 0);
-      p->constant_flags[reg] = I915_CONSTFLAG_PARAM;
-
-      fp->param[i].values = values;
-      fp->param[i].reg = reg;
-
-      return UREG(REG_TYPE_CONST, reg);
-   }
-}
-#endif
index 6c1524c768e0c4135f8284543ad0133278a01042..afe7e25dce79c9683e6b0ab22a0d93eb5a02b78c 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "pipe/p_shader_tokens.h"
 #include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_dump.h"
 
 #include "draw/draw_vertex.h"
 
@@ -97,19 +98,19 @@ negate(int reg, int x, int y, int z, int w)
 }
 
 
+/**
+ * In the event of a translation failure, we'll generate a simple color
+ * pass-through program.
+ */
 static void
-i915_use_passthrough_shader(struct i915_context *i915)
+i915_use_passthrough_shader(struct i915_fragment_shader *fs)
 {
-   debug_printf("**** Using i915 pass-through fragment shader\n");
-
-   i915->current.program = (uint *) MALLOC(sizeof(passthrough));
-   if (i915->current.program) {
-      memcpy(i915->current.program, passthrough, sizeof(passthrough));
-      i915->current.program_len = Elements(passthrough);
+   fs->program = (uint *) MALLOC(sizeof(passthrough));
+   if (fs->program) {
+      memcpy(fs->program, passthrough, sizeof(passthrough));
+      fs->program_len = Elements(passthrough);
    }
-
-   i915->current.num_constants[PIPE_SHADER_FRAGMENT] = 0;
-   i915->current.num_user_constants[PIPE_SHADER_FRAGMENT] = 0;
+   fs->num_constants = 0;
 }
 
 
@@ -161,9 +162,6 @@ src_vector(struct i915_fp_compile *p,
        * We also use a texture coordinate to pass wpos when possible.
        */
 
-      /* use vertex format info to map a slot number to a VF attrib */
-      assert(index < p->vertex_info->num_attribs);
-
       sem_name = p->input_semantic_name[index];
       sem_ind = p->input_semantic_index[index];
 
@@ -201,7 +199,8 @@ src_vector(struct i915_fp_compile *p,
       break;
 
    case TGSI_FILE_IMMEDIATE:
-      /* XXX unfinished - need to append immediates onto const buffer */
+      assert(index < p->num_immediates);
+      index = p->immediates_map[index];
       /* fall-through */
    case TGSI_FILE_CONSTANT:
       src = UREG(REG_TYPE_CONST, index);
@@ -896,6 +895,7 @@ static void
 i915_translate_instructions(struct i915_fp_compile *p,
                             const struct tgsi_token *tokens)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    struct tgsi_parse_context parse;
 
    tgsi_parse_init( &parse, tokens );
@@ -928,13 +928,54 @@ i915_translate_instructions(struct i915_fp_compile *p,
             p->output_semantic_name[ind] = sem;
             p->output_semantic_index[ind] = semi;
          }
+         else if (parse.FullToken.FullDeclaration.Declaration.File
+                  == TGSI_FILE_CONSTANT) {
+            uint i;
+            for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+                 i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last;
+                 i++) {
+               assert(ifs->constant_flags[i] == 0x0);
+               ifs->constant_flags[i] = I915_CONSTFLAG_USER;
+               ifs->num_constants = MAX2(ifs->num_constants, i + 1);
+            }
+         }
          break;
 
       case TGSI_TOKEN_TYPE_IMMEDIATE:
-         /* XXX append the immediate to the const buffer... */
+         {
+            const struct tgsi_full_immediate *imm
+               = &parse.FullToken.FullImmediate;
+            const uint pos = p->num_immediates++;
+            uint j;
+            for (j = 0; j < imm->Immediate.Size; j++) {
+               p->immediates[pos][j] = imm->u.ImmediateFloat32[j].Float;
+            }
+         }
          break;
 
       case TGSI_TOKEN_TYPE_INSTRUCTION:
+         if (p->first_instruction) {
+            /* resolve location of immediates */
+            uint i, j;
+            for (i = 0; i < p->num_immediates; i++) {
+               /* find constant slot for this immediate */
+               for (j = 0; j < I915_MAX_CONSTANT; j++) {
+                  if (ifs->constant_flags[j] == 0x0) {
+                     memcpy(ifs->constants[j],
+                            p->immediates[i],
+                            4 * sizeof(float));
+                     /*printf("immediate %d maps to const %d\n", i, j);*/
+                     ifs->constant_flags[j] = 0xf;  /* all four comps used */
+                     p->immediates_map[i] = j;
+                     ifs->num_constants = MAX2(ifs->num_constants, j + 1);
+                     break;
+                  }
+               }
+            }
+
+            p->first_instruction = FALSE;
+         }
+
          i915_translate_instruction(p, &parse.FullToken.FullInstruction);
          break;
 
@@ -950,27 +991,28 @@ i915_translate_instructions(struct i915_fp_compile *p,
 
 static struct i915_fp_compile *
 i915_init_compile(struct i915_context *i915,
-                  const struct pipe_shader_state *fs)
+                  struct i915_fragment_shader *ifs)
 {
    struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
 
-   p->shader = i915->fs;
+   p->shader = ifs;
 
-   p->vertex_info = &i915->current.vertex_info;
-
-   /* new constants found during translation get appended after the
-    * user-provided constants.
+   /* Put new constants at end of const buffer, growing downward.
+    * The problem is we don't know how many user-defined constants might
+    * be specified with pipe->set_constant_buffer().
+    * Should pre-scan the user's program to determine the highest-numbered
+    * constant referenced.
     */
-   p->constants = i915->current.constants[PIPE_SHADER_FRAGMENT];
-   p->num_constants = i915->current.num_user_constants[PIPE_SHADER_FRAGMENT];
+   ifs->num_constants = 0;
+   memset(ifs->constant_flags, 0, sizeof(ifs->constant_flags));
+
+   p->first_instruction = TRUE;
 
    p->nr_tex_indirect = 1;      /* correct? */
    p->nr_tex_insn = 0;
    p->nr_alu_insn = 0;
    p->nr_decl_insn = 0;
 
-   memset(p->constant_flags, 0, sizeof(p->constant_flags));
-
    p->csr = p->program;
    p->decl = p->declarations;
    p->decl_s = 0;
@@ -993,6 +1035,7 @@ i915_init_compile(struct i915_context *i915,
 static void
 i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    unsigned long program_size = (unsigned long) (p->csr - p->program);
    unsigned long decl_size = (unsigned long) (p->decl - p->declarations);
 
@@ -1008,19 +1051,13 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
    if (p->nr_decl_insn > I915_MAX_DECL_INSN)
       i915_program_error(p, "Exceeded max DECL instructions");
 
-   /* free old program, if present */
-   if (i915->current.program) {
-      FREE(i915->current.program);
-      i915->current.program_len = 0;
-   }
-
    if (p->error) {
       p->NumNativeInstructions = 0;
       p->NumNativeAluInstructions = 0;
       p->NumNativeTexInstructions = 0;
       p->NumNativeTexIndirections = 0;
 
-      i915_use_passthrough_shader(i915);
+      i915_use_passthrough_shader(ifs);
    }
    else {
       p->NumNativeInstructions
@@ -1034,24 +1071,20 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
 
       /* Copy compilation results to fragment program struct: 
        */
-      i915->current.program
+      assert(!ifs->program);
+      ifs->program
          = (uint *) MALLOC((program_size + decl_size) * sizeof(uint));
-      if (i915->current.program) {
-         i915->current.program_len = program_size + decl_size;
+      if (ifs->program) {
+         ifs->program_len = program_size + decl_size;
 
-         memcpy(i915->current.program,
+         memcpy(ifs->program,
                 p->declarations, 
                 decl_size * sizeof(uint));
 
-         memcpy(i915->current.program + decl_size, 
+         memcpy(ifs->program + decl_size, 
                 p->program, 
                 program_size * sizeof(uint));
       }
-
-      /* update number of constants */
-      i915->current.num_constants[PIPE_SHADER_FRAGMENT] = p->num_constants;
-      assert(i915->current.num_constants[PIPE_SHADER_FRAGMENT]
-             >= i915->current.num_user_constants[PIPE_SHADER_FRAGMENT]);
    }
 
    /* Release the compilation struct: 
@@ -1085,7 +1118,7 @@ i915_find_wpos_space(struct i915_fp_compile *p)
       i915_program_error(p, "No free texcoord for wpos value");
    }
 #else
-   if (p->shader->input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+   if (p->shader->state.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
       /* frag shader using the fragment position input */
 #if 0
       assert(0);
@@ -1106,7 +1139,7 @@ static void
 i915_fixup_depth_write(struct i915_fp_compile *p)
 {
    /* XXX assuming pos/depth is always in output[0] */
-   if (p->shader->output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+   if (p->shader->state.output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
       const uint depth = UREG(REG_TYPE_OD, 0);
 
       i915_emit_arith(p,
@@ -1121,13 +1154,18 @@ i915_fixup_depth_write(struct i915_fp_compile *p)
 
 
 void
-i915_translate_fragment_program( struct i915_context *i915 )
+i915_translate_fragment_program( struct i915_context *i915,
+                                 struct i915_fragment_shader *fs)
 {
-   struct i915_fp_compile *p = i915_init_compile(i915, i915->fs);
-   const struct tgsi_token *tokens = i915->fs->tokens;
+   struct i915_fp_compile *p = i915_init_compile(i915, fs);
+   const struct tgsi_token *tokens = fs->state.tokens;
 
    i915_find_wpos_space(p);
 
+#if 0
+   tgsi_dump(tokens, 0);
+#endif
+
    i915_translate_instructions(p, tokens);
    i915_fixup_depth_write(p);
 
index e055eed7e025a16bacfa952ecfefdb71ff1d87b9..e4288d4e319c4b671e6b04f6698e12aa96faa3eb 100644 (file)
@@ -38,6 +38,7 @@
 #include "i915_reg.h"
 #include "i915_state.h"
 #include "i915_state_inlines.h"
+#include "i915_fpc.h"
 
 
 /* The i915 (and related graphics cores) do not support GL_CLAMP.  The
@@ -416,26 +417,47 @@ static void i915_set_polygon_stipple( struct pipe_context *pipe,
 }
 
 
-static void * i915_create_fs_state(struct pipe_context *pipe,
-                                   const struct pipe_shader_state *templ)
+
+static void *
+i915_create_fs_state(struct pipe_context *pipe,
+                     const struct pipe_shader_state *templ)
 {
-   return 0;
+   struct i915_context *i915 = i915_context(pipe);
+   struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
+   if (!ifs)
+      return NULL;
+
+   ifs->state = *templ;
+
+   /* The shader's compiled to i915 instructions here */
+   i915_translate_fragment_program(i915, ifs);
+
+   return ifs;
 }
 
-static void i915_bind_fs_state(struct pipe_context *pipe, void *fs)
+static void
+i915_bind_fs_state(struct pipe_context *pipe, void *shader)
 {
    struct i915_context *i915 = i915_context(pipe);
 
-   i915->fs = (struct pipe_shader_state *)fs;
+   i915->fs = (struct i915_fragment_shader*) shader;
 
    i915->dirty |= I915_NEW_FS;
 }
 
-static void i915_delete_fs_state(struct pipe_context *pipe, void *shader)
+static
+void i915_delete_fs_state(struct pipe_context *pipe, void *shader)
 {
-   /*do nothing*/
+   struct i915_fragment_shader *ifs = (struct i915_fragment_shader *) shader;
+
+   if (ifs->program)
+      FREE(ifs->program);
+   ifs->program_len = 0;
+
+   FREE(ifs);
 }
 
+
 static void *
 i915_create_vs_state(struct pipe_context *pipe,
                      const struct pipe_shader_state *templ)
index 4767584fc608eecbf91dfbffd8738be7fbf53749..f654f543cc63e1d17ffc065e2eb02d6e0055dd03 100644 (file)
@@ -43,7 +43,7 @@
  */
 static void calculate_vertex_layout( struct i915_context *i915 )
 {
-   const struct pipe_shader_state *fs = i915->fs;
+   const struct pipe_shader_state *fs = &i915->fs->state;
    const enum interp_mode colorInterp = i915->rasterizer->color_interp;
    struct vertex_info vinfo;
    uint front0 = 0, back0 = 0, front1 = 0, back1 = 0;
@@ -164,7 +164,6 @@ void i915_update_derived( struct i915_context *i915 )
       i915_update_dynamic( i915 );
 
    if (i915->dirty & I915_NEW_FS) {
-      i915_translate_fragment_program(i915);
       i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
    }
 
index 3339287f498b89653ad30630548f2e66690b84bf..6bbaac4e34c3dc999f6c6201142251f4b811935c 100644 (file)
@@ -99,7 +99,11 @@ i915_emit_hardware_state(struct i915_context *i915 )
                              2 + I915_TEX_UNITS*3 + 
                              2 + I915_TEX_UNITS*3 +
                              2 + I915_MAX_CONSTANT*4 + 
+#if 0
                              i915->current.program_len + 
+#else
+                             i915->fs->program_len + 
+#endif
                              6 
                            ) * 3/2; /* plus 50% margin */
    const unsigned relocs = ( I915_TEX_UNITS +
@@ -325,15 +329,34 @@ i915_emit_hardware_state(struct i915_context *i915 )
    /* 2 + I915_MAX_CONSTANT*4 dwords, 0 relocs */
    if (i915->hardware_dirty & I915_HW_PROGRAM)
    {
-      const uint nr = i915->current.num_constants[PIPE_SHADER_FRAGMENT];
-      assert(nr <= I915_MAX_CONSTANT);
-      if (nr > 0) {
-         const uint *c
-            = (const uint *) i915->current.constants[PIPE_SHADER_FRAGMENT];
+      /* Collate the user-defined constants with the fragment shader's
+       * immediates according to the constant_flags[] array.
+       */
+      const uint nr = i915->fs->num_constants;
+      if (nr) {
          uint i;
+
          OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
          OUT_BATCH( (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) );
+
          for (i = 0; i < nr; i++) {
+            const uint *c;
+            if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) {
+               /* grab user-defined constant */
+               c = (uint *) i915->current.constants[PIPE_SHADER_FRAGMENT][i];
+            }
+            else {
+               /* emit program constant */
+               c = (uint *) i915->fs->constants[i];
+            }
+#if 0 /* debug */
+            {
+               float *f = (float *) c;
+               printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3],
+                      (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER
+                       ? "user" : "immediate"));
+            }
+#endif
             OUT_BATCH(*c++);
             OUT_BATCH(*c++);
             OUT_BATCH(*c++);
@@ -348,9 +371,9 @@ i915_emit_hardware_state(struct i915_context *i915 )
    {
       uint i;
       /* we should always have, at least, a pass-through program */
-      assert(i915->current.program_len > 0);
-      for (i = 0; i < i915->current.program_len; i++) {
-         OUT_BATCH(i915->current.program[i]);
+      assert(i915->fs->program_len > 0);
+      for (i = 0; i < i915->fs->program_len; i++) {
+         OUT_BATCH(i915->fs->program[i]);
       }
    }