r300: Allow compiler to add constants in a cleaner way
authorNicolai Hähnle <nhaehnle@gmail.com>
Fri, 24 Jul 2009 20:41:14 +0000 (22:41 +0200)
committerNicolai Hähnle <nhaehnle@gmail.com>
Mon, 27 Jul 2009 18:32:07 +0000 (20:32 +0200)
Adding constants is used in a number of non-native instruction
rewrites, and it required us to keep copies of modified gl_programs
around. This is a first step towards ending this.

Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
16 files changed:
src/mesa/drivers/dri/r300/compiler/Makefile
src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/radeon_code.c [new file with mode: 0644]
src/mesa/drivers/dri/r300/compiler/radeon_code.h
src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
src/mesa/drivers/dri/r300/compiler/radeon_program.c
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
src/mesa/drivers/dri/r300/r300_shader.c
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/r300_vertprog.c

index 4e2ff50c69db2143a0940c872cc7af7f18edba4e..dd04b81a2f305c8a53939e3e85324eba6c653b46 100644 (file)
@@ -6,6 +6,7 @@ include $(TOP)/configs/current
 LIBNAME = r300compiler
 
 C_SOURCES = \
+               radeon_code.c \
                radeon_compiler.c \
                radeon_nqssadce.c \
                radeon_program.c \
index f2472d6ce1ca2e90016a96dee58fb4bae0464b57..674d1f8cd35a023b43583113643e8d268fe8d774 100644 (file)
        } while(0)
 
 
-static GLboolean emit_const(void* data, GLuint file, GLuint index, GLuint *hwindex)
-{
-       PROG_CODE;
-
-       for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
-               if (code->constant[*hwindex].File == file &&
-                   code->constant[*hwindex].Index == index)
-                       break;
-       }
-
-       if (*hwindex >= code->const_nr) {
-               if (*hwindex >= R300_PFS_NUM_CONST_REGS) {
-                       error("Out of hw constants!\n");
-                       return GL_FALSE;
-               }
-
-               code->const_nr++;
-               code->constant[*hwindex].File = file;
-               code->constant[*hwindex].Index = index;
-       }
-
-       return GL_TRUE;
-}
-
-
 /**
  * Mark a temporary register as used.
  */
@@ -315,7 +290,6 @@ static GLboolean emit_tex(void* data, struct radeon_pair_texture_instruction* in
 
 
 static const struct radeon_pair_handler pair_handler = {
-       .EmitConst = &emit_const,
        .EmitPaired = &emit_alu,
        .EmitTex = &emit_tex,
        .BeginTexBlock = &begin_tex,
index 406961bea94deec62bbab286efd3e4172bf02b39..7ac57d0d499640704a6d23e20b7e320783d54b88 100644 (file)
@@ -303,6 +303,8 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
                r300BuildFragmentProgramHwCode(c);
        }
 
+       rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
+
        if (c->Base.Debug) {
                if (c->is_r500) {
                        r500FragmentProgramDump(c->code);
index cdcfa1d27ecf5a4ffe0ad828ff29dbc3646ca546..c9d0996d44742b21e0721e732358cbeef3bc41e4 100644 (file)
@@ -834,6 +834,8 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
 
        translate_vertex_program(compiler);
 
+       rc_constants_copy(&compiler->code->constants, &compiler->Base.Program.Constants);
+
        compiler->code->InputsRead = compiler->Base.Program.InputsRead;
        compiler->code->OutputsWritten = compiler->Base.Program.OutputsWritten;
 }
index e8d0e77b68c5e74ac28c163594e620d7f3eb8a47..6d2158dbfc3f8f84a19d076cc5b98431af156f5f 100644 (file)
@@ -376,15 +376,6 @@ void r500FragmentProgramDump(struct rX00_fragment_program_code *c)
   uint32_t inst0;
   char *str = NULL;
 
-  if (code->const_nr) {
-    fprintf(stderr, "--------\nConstants:\n");
-    for (n = 0; n < code->const_nr; n++) {
-      fprintf(stderr, "Constant %d: %i[%i]\n", n,
-        code->constant[n].File, code->constant[n].Index);
-    }
-    fprintf(stderr, "--------\n");
-  }
-
   for (n = 0; n < code->inst_end+1; n++) {
     inst0 = inst = code->inst[n].inst0;
     fprintf(stderr,"%d\t0:CMN_INST   0x%08x:", n, inst);
index 5b0b306b9cf2cbae0982190dc96795364fade1e4..21d6b9bba71f11e6f06c831929b4accf883f6e95 100644 (file)
        } while(0)
 
 
-/**
- * Callback to register hardware constants.
- */
-static GLboolean emit_const(void *data, GLuint file, GLuint idx, GLuint *hwindex)
-{
-       PROG_CODE;
-
-       for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
-               if (code->constant[*hwindex].File == file &&
-                   code->constant[*hwindex].Index == idx)
-                       break;
-       }
-
-       if (*hwindex >= code->const_nr) {
-               if (*hwindex >= R500_PFS_NUM_CONST_REGS) {
-                       error("Out of hw constants!\n");
-                       return GL_FALSE;
-               }
-
-               code->const_nr++;
-               code->constant[*hwindex].File = file;
-               code->constant[*hwindex].Index = idx;
-       }
-
-       return GL_TRUE;
-}
-
 static GLuint translate_rgb_op(struct r300_fragment_program_compiler *c, GLuint opcode)
 {
        switch(opcode) {
@@ -295,7 +268,6 @@ static GLboolean emit_tex(void *data, struct radeon_pair_texture_instruction *in
 }
 
 static const struct radeon_pair_handler pair_handler = {
-       .EmitConst = emit_const,
        .EmitPaired = emit_paired,
        .EmitTex = emit_tex,
        .MaxHwTemps = 128
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.c b/src/mesa/drivers/dri/r300/compiler/radeon_code.c
new file mode 100644 (file)
index 0000000..b94e534
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009 Nicolai Haehnle.
+ *
+ * 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.
+ *
+ */
+
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+#include "radeon_code.h"
+
+void rc_constants_init(struct rc_constant_list * c)
+{
+       memset(c, 0, sizeof(*c));
+}
+
+/**
+ * Copy a constants structure, assuming that the destination structure
+ * is not initialized.
+ */
+void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src)
+{
+       dst->Constants = malloc(sizeof(struct rc_constant) * src->Count);
+       memcpy(dst->Constants, src->Constants, sizeof(struct rc_constant) * src->Count);
+       dst->Count = src->Count;
+       dst->_Reserved = src->Count;
+}
+
+void rc_constants_destroy(struct rc_constant_list * c)
+{
+       free(c->Constants);
+       memset(c, 0, sizeof(*c));
+}
+
+unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant)
+{
+       unsigned index = c->Count;
+
+       if (c->Count >= c->_Reserved) {
+               struct rc_constant * newlist;
+
+               c->_Reserved = c->_Reserved * 2;
+               if (!c->_Reserved)
+                       c->_Reserved = 16;
+
+               newlist = malloc(sizeof(struct rc_constant) * c->_Reserved);
+               memcpy(newlist, c->Constants, sizeof(struct rc_constant) * c->Count);
+
+               free(c->Constants);
+               c->Constants = newlist;
+       }
+
+       c->Constants[index] = *constant;
+       c->Count++;
+
+       return index;
+}
index e89e7bc17b2dd51957e0151e9a1da75f0c230e84..3e6eb97b177c5ee3801c690bba7760687795a44c 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef RADEON_CODE_H
 #define RADEON_CODE_H
 
-
 #define R300_PFS_MAX_ALU_INST     64
 #define R300_PFS_MAX_TEX_INST     32
 #define R300_PFS_MAX_TEX_INDIRECT 4
 #define STATE_R300_TEXRECT_FACTOR (STATE_INTERNAL_DRIVER+1)
 
 
+enum {
+       /**
+        * External constants are constants whose meaning is unknown to this
+        * compiler. For example, a Mesa gl_program's constants are turned
+        * into external constants.
+        */
+       RC_CONSTANT_EXTERNAL = 0,
+
+       RC_CONSTANT_IMMEDIATE,
+
+       /**
+        * Constant referring to state that is known by this compiler,
+        * i.e. *not* arbitrary Mesa (or other) state.
+        */
+       RC_CONSTANT_STATE
+};
+
+struct rc_constant {
+       unsigned Type:2; /**< RC_CONSTANT_xxx */
+       union {
+               unsigned External;
+               float Immediate[4];
+               unsigned State[4];
+       } u;
+};
+
+struct rc_constant_list {
+       struct rc_constant * Constants;
+       unsigned Count;
+
+       unsigned _Reserved;
+};
+
+void rc_constants_init(struct rc_constant_list * c);
+void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src);
+void rc_constants_destroy(struct rc_constant_list * c);
+unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant);
+
 /**
  * Stores state that influences the compilation of a fragment program.
  */
@@ -98,13 +135,6 @@ struct r300_fragment_program_code {
        int cur_node;
        int first_node_has_tex;
 
-       /**
-        * Remember which program register a given hardware constant
-        * belongs to.
-        */
-       struct prog_src_register constant[R300_PFS_NUM_CONST_REGS];
-       int const_nr;
-
        int max_temp_idx;
 };
 
@@ -122,13 +152,6 @@ struct r500_fragment_program_code {
        int inst_offset;
        int inst_end;
 
-       /**
-        * Remember which program register a given hardware constant
-        * belongs to.
-        */
-       struct prog_src_register constant[R500_PFS_NUM_CONST_REGS];
-       int const_nr;
-
        int max_temp_idx;
 };
 
@@ -140,6 +163,8 @@ struct rX00_fragment_program_code {
 
        GLboolean writes_depth;
 
+       struct rc_constant_list constants;
+
        /* attribute that we are sending the WPOS in */
        gl_frag_attrib wpos_attr;
        /* attribute that we are sending the fog coordinate in */
@@ -168,6 +193,8 @@ struct r300_vertex_program_code {
        int inputs[VERT_ATTRIB_MAX];
        int outputs[VERT_RESULT_MAX];
 
+       struct rc_constant_list constants;
+
        GLbitfield InputsRead;
        GLbitfield OutputsWritten;
 };
index 7b8322c201db3fd7d3171f5f0cf80250a3cd5bf5..684961021a1729ff94e17b7d725b7604bbb34d92 100644 (file)
@@ -37,6 +37,7 @@ void rc_init(struct radeon_compiler * c)
 
 void rc_destroy(struct radeon_compiler * c)
 {
+       rc_constants_destroy(&c->Program.Constants);
        memory_pool_destroy(&c->Pool);
        free(c->ErrorMsg);
 }
index abe2c185258de39f86279585bbeb85620c8626fe..6630db627957e46861624d6c966a653db1d27344 100644 (file)
@@ -46,6 +46,8 @@ struct rc_program {
        GLbitfield InputsRead;
        GLbitfield OutputsWritten;
        GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
+
+       struct rc_constant_list Constants;
 };
 
 struct radeon_compiler {
index 5f35f56a2395439e80369c815ee2d78a14dade01..50a0ce8743c8652bb3bacb672dee60e9d014632c 100644 (file)
@@ -28,6 +28,7 @@
 #include "radeon_program.h"
 
 #include "radeon_compiler.h"
+#include "shader/prog_parameter.h"
 #include "shader/prog_print.h"
 
 
@@ -190,6 +191,7 @@ void rc_remove_instruction(struct rc_instruction * inst)
 void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * program)
 {
        struct prog_instruction *source;
+       unsigned int i;
 
        for(source = program->Instructions; source->Opcode != OPCODE_END; ++source) {
                struct rc_instruction * dest = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
@@ -199,6 +201,15 @@ void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * progr
        c->Program.ShadowSamplers = program->ShadowSamplers;
        c->Program.InputsRead = program->InputsRead;
        c->Program.OutputsWritten = program->OutputsWritten;
+
+       for(i = 0; i < program->Parameters->NumParameters; ++i) {
+               struct rc_constant constant;
+
+               constant.Type = RC_CONSTANT_EXTERNAL;
+               constant.u.External = i;
+
+               rc_constants_add(&c->Program.Constants, &constant);
+       }
 }
 
 
index ca63b906964afc334b91ace97cab03a19af721e2..57a364c78b6d6734629b113ec073e176d04929a0 100644 (file)
@@ -640,7 +640,7 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
                index = get_hw_reg(s, src.File, src.Index);
        } else {
                constant = 1;
-               s->Compiler->Error |= !s->Handler->EmitConst(s->UserData, src.File, src.Index, &index);
+               index = src.Index;
        }
 
        for(i = 0; i < 3; ++i) {
index 46196fb1c87f2fe09f180acaa7254fe02372a001..9d4d7dd3c93a0ef277c4e3465b99862b53517a99 100644 (file)
@@ -109,13 +109,6 @@ struct radeon_pair_texture_instruction {
  *
  */
 struct radeon_pair_handler {
-       /**
-        * Fill in the proper hardware index for the given constant register.
-        *
-        * @return GL_FALSE on error.
-        */
-       GLboolean (*EmitConst)(void*, GLuint file, GLuint index, GLuint *hwindex);
-
        /**
         * Write a paired instruction to the hardware.
         *
index 3704c1015583aca795fc66c8d8b62ad21ef804c9..40b073f2c73e37d9f0842bae1194f040a3ec55e4 100644 (file)
@@ -38,6 +38,7 @@ static void freeFragProgCache(GLcontext *ctx, struct r300_fragment_program_cont
 
        while (fp) {
                tmp = fp->next;
+               rc_constants_destroy(&fp->code.constants);
                _mesa_reference_program(ctx, &fp->Base, NULL);
                _mesa_free(fp);
                fp = tmp;
@@ -50,6 +51,7 @@ static void freeVertProgCache(GLcontext *ctx, struct r300_vertex_program_cont *c
 
        while (vp) {
                tmp = vp->next;
+               rc_constants_destroy(&vp->code.constants);
                _mesa_reference_vertprog(ctx, &vp->Base, NULL);
                _mesa_free(vp);
                vp = tmp;
index e3e8a6fb3df6ad167ff9a7066c8251cbe9cfb736..b8fad4a6e7789db070301fc4a169f3d0b42950da 100644 (file)
@@ -2029,26 +2029,21 @@ void r300UpdateShaders(r300ContextPtr rmesa)
        rmesa->radeon.NewGLState = 0;
 }
 
-static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx,
-       struct prog_src_register srcreg)
+static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx, GLuint index)
 {
        static const GLfloat dummy[4] = { 0, 0, 0, 0 };
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
-       struct gl_program * program = rmesa->selected_fp->Base;
-
-       switch(srcreg.File) {
-       case PROGRAM_LOCAL_PARAM:
-               return program->LocalParams[srcreg.Index];
-       case PROGRAM_ENV_PARAM:
-               return ctx->FragmentProgram.Parameters[srcreg.Index];
-       case PROGRAM_STATE_VAR:
-       case PROGRAM_NAMED_PARAM:
-       case PROGRAM_CONSTANT:
-               return program->Parameters->ParameterValues[srcreg.Index];
-       default:
-               _mesa_problem(ctx, "get_fragmentprogram_constant: Unknown\n");
-               return dummy;
+       struct r300_fragment_program * fp = rmesa->selected_fp;
+       struct rc_constant * rcc = &fp->code.constants.Constants[index];
+
+       switch(rcc->Type) {
+       case RC_CONSTANT_EXTERNAL:
+               return fp->Base->Parameters->ParameterValues[rcc->u.External];
+       case RC_CONSTANT_IMMEDIATE:
+               return rcc->u.Immediate;
        }
+
+       return dummy;
 }
 
 
@@ -2099,9 +2094,9 @@ static void r300SetupPixelShader(GLcontext *ctx)
        }
 
        R300_STATECHANGE(rmesa, fpp);
-       rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_PFS_PARAM_0_X, code->const_nr * 4);
-       for (i = 0; i < code->const_nr; i++) {
-               const GLfloat *constant = get_fragmentprogram_constant(ctx, code->constant[i]);
+       rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_PFS_PARAM_0_X, fp->code.constants.Count * 4);
+       for (i = 0; i < fp->code.constants.Count; i++) {
+               const GLfloat *constant = get_fragmentprogram_constant(ctx, i);
                rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat24(constant[0]);
                rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat24(constant[1]);
                rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat24(constant[2]);
@@ -2161,14 +2156,14 @@ static void r500SetupPixelShader(GLcontext *ctx)
        bump_r500fp_count(rmesa->hw.r500fp.cmd, (code->inst_end + 1) * 6);
 
        R300_STATECHANGE(rmesa, r500fp_const);
-       for (i = 0; i < code->const_nr; i++) {
-               const GLfloat *constant = get_fragmentprogram_constant(ctx, code->constant[i]);
+       for (i = 0; i < fp->code.constants.Count; i++) {
+               const GLfloat *constant = get_fragmentprogram_constant(ctx, i);
                rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat32(constant[0]);
                rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat32(constant[1]);
                rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat32(constant[2]);
                rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = r300PackFloat32(constant[3]);
        }
-       bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, code->const_nr * 4);
+       bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, fp->code.constants.Count * 4);
 }
 
 void r300SetupVAP(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten)
index 91d9d8ae949140f6c999d6dca5b5783c699d9ed8..fd2b9fcaf26296ab2fda8865e5e419dfbe2828d8 100644 (file)
@@ -45,56 +45,53 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_context.h"
 #include "r300_state.h"
 
-
-static int r300VertexProgUpdateParams(GLcontext * ctx, struct gl_vertex_program *vp, float *dst)
+/**
+ * Write parameter array for the given vertex program into dst.
+ * Return the total number of components written.
+ */
+static int r300VertexProgUpdateParams(GLcontext * ctx, struct r300_vertex_program *vp, float *dst)
 {
-       int pi;
-       float *dst_o = dst;
-       struct gl_program_parameter_list *paramList;
+       int i;
 
-       if (vp->IsNVProgram) {
+       if (vp->Base->IsNVProgram) {
                _mesa_load_tracked_matrices(ctx);
-
-               for (pi = 0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) {
-                       *dst++ = ctx->VertexProgram.Parameters[pi][0];
-                       *dst++ = ctx->VertexProgram.Parameters[pi][1];
-                       *dst++ = ctx->VertexProgram.Parameters[pi][2];
-                       *dst++ = ctx->VertexProgram.Parameters[pi][3];
+       } else {
+               if (vp->Base->Base.Parameters) {
+                       _mesa_load_state_parameters(ctx, vp->Base->Base.Parameters);
                }
-               return dst - dst_o;
        }
 
-       if (!vp->Base.Parameters)
-               return 0;
-
-       _mesa_load_state_parameters(ctx, vp->Base.Parameters);
-
-       if (vp->Base.Parameters->NumParameters * 4 >
-           VSF_MAX_FRAGMENT_LENGTH) {
+       if (vp->code.constants.Count * 4 > VSF_MAX_FRAGMENT_LENGTH) {
+               /* Should have checked this earlier... */
                fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
                _mesa_exit(-1);
        }
 
-       paramList = vp->Base.Parameters;
-       for (pi = 0; pi < paramList->NumParameters; pi++) {
-               switch (paramList->Parameters[pi].Type) {
-               case PROGRAM_STATE_VAR:
-               case PROGRAM_NAMED_PARAM:
-                       //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
-               case PROGRAM_CONSTANT:
-                       *dst++ = paramList->ParameterValues[pi][0];
-                       *dst++ = paramList->ParameterValues[pi][1];
-                       *dst++ = paramList->ParameterValues[pi][2];
-                       *dst++ = paramList->ParameterValues[pi][3];
+       for(i = 0; i < vp->code.constants.Count; ++i) {
+               const float * src = 0;
+               const struct rc_constant * constant = &vp->code.constants.Constants[i];
+
+               switch(constant->Type) {
+               case RC_CONSTANT_EXTERNAL:
+                       if (vp->Base->IsNVProgram) {
+                               src = ctx->VertexProgram.Parameters[constant->u.External];
+                       } else {
+                               src = vp->Base->Base.Parameters->ParameterValues[constant->u.External];
+                       }
+                       break;
+
+               case RC_CONSTANT_IMMEDIATE:
+                       src = constant->u.Immediate;
                        break;
-               default:
-                       _mesa_problem(NULL, "Bad param type in %s",
-                                     __FUNCTION__);
                }
 
+               dst[4*i] = src[0];
+               dst[4*i + 1] = src[1];
+               dst[4*i + 2] = src[2];
+               dst[4*i + 3] = src[3];
        }
 
-       return dst - dst_o;
+       return 4 * vp->code.constants.Count;
 }
 
 static struct r300_vertex_program *build_program(GLcontext *ctx,
@@ -113,7 +110,7 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
 
        compiler.code = &vp->code;
        compiler.state = vp->key;
-       compiler.program = vp->Base;
+       compiler.program = &vp->Base->Base;
 
        if (compiler.Base.Debug) {
                fprintf(stderr, "Initial vertex program:\n");
@@ -210,7 +207,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0;
 
        R300_STATECHANGE(rmesa, vpp);
-       param_count = r300VertexProgUpdateParams(ctx, prog->Base, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
+       param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
        bump_vpu_count(rmesa->hw.vpp.cmd, param_count);
        param_count /= 4;