struct {
struct brw_vs_prog_data *prog_data;
+ int8_t *constant_map; /* variable array following prog_data */
dri_bo *prog_bo;
dri_bo *state_bo;
*/
_mesa_load_state_parameters(ctx, vp->program.Base.Parameters);
- /* XXX just use a memcpy here */
- for (i = 0; i < nr; i++) {
- const GLfloat *value = vp->program.Base.Parameters->ParameterValues[i];
- buf[offset + i * 4 + 0] = value[0];
- buf[offset + i * 4 + 1] = value[1];
- buf[offset + i * 4 + 2] = value[2];
- buf[offset + i * 4 + 3] = value[3];
+ if (vp->use_const_buffer) {
+ /* Load the subset of push constants that will get used when
+ * we also have a pull constant buffer.
+ */
+ for (i = 0; i < vp->program.Base.Parameters->NumParameters; i++) {
+ if (brw->vs.constant_map[i] != -1) {
+ assert(brw->vs.constant_map[i] <= nr);
+ memcpy(buf + offset + brw->vs.constant_map[i] * 4,
+ vp->program.Base.Parameters->ParameterValues[i],
+ 4 * sizeof(float));
+ }
+ }
+ } else {
+ for (i = 0; i < nr; i++) {
+ memcpy(buf + offset + i * 4,
+ vp->program.Base.Parameters->ParameterValues[i],
+ 4 * sizeof(float));
+ }
}
}
#include "brw_util.h"
#include "brw_state.h"
#include "shader/prog_print.h"
+#include "shader/prog_parameter.h"
struct brw_vertex_program *vp,
struct brw_vs_prog_key *key )
{
+ GLcontext *ctx = &brw->intel.ctx;
GLuint program_size;
const GLuint *program;
struct brw_vs_compile c;
+ int aux_size;
memset(&c, 0, sizeof(c));
memcpy(&c.key, key, sizeof(*key));
*/
program = brw_get_program(&c.func, &program_size);
+ /* We upload from &c.prog_data including the constant_map assuming
+ * they're packed together. It would be nice to have a
+ * compile-time assert macro here.
+ */
+ assert(c.constant_map == (int8_t *)&c.prog_data +
+ sizeof(c.prog_data));
+ assert(ctx->Const.VertexProgram.MaxNativeParameters ==
+ ARRAY_SIZE(c.constant_map));
+
+ aux_size = sizeof(c.prog_data);
+ if (c.vp->use_const_buffer)
+ aux_size += c.vp->program.Base.Parameters->NumParameters;
+
dri_bo_unreference(brw->vs.prog_bo);
brw->vs.prog_bo = brw_upload_cache_with_auxdata(&brw->cache, BRW_VS_PROG,
&c.key, sizeof(c.key),
NULL, 0,
program, program_size,
&c.prog_data,
- sizeof(c.prog_data),
+ aux_size,
&brw->vs.prog_data);
}
&brw->vs.prog_data);
if (brw->vs.prog_bo == NULL)
do_vs_prog(brw, vp, &key);
+ brw->vs.constant_map = ((int8_t *)brw->vs.prog_data +
+ sizeof(*brw->vs.prog_data));
}
struct brw_compile func;
struct brw_vs_prog_key key;
struct brw_vs_prog_data prog_data;
+ int8_t constant_map[1024];
struct brw_vertex_program *vp;
/* Vertex program parameters from curbe:
*/
if (c->vp->use_const_buffer) {
- /* get constants from a real constant buffer */
- c->prog_data.curb_read_length = 0;
- c->prog_data.nr_params = 4; /* XXX 0 causes a bug elsewhere... */
+ int max_constant = BRW_MAX_GRF - 20 - c->vp->program.Base.NumTemporaries;
+ int constant = 0;
+
+ /* We've got more constants than we can load with the push
+ * mechanism. This is often correlated with reladdr loads where
+ * we should probably be using a pull mechanism anyway to avoid
+ * excessive reading. However, the pull mechanism is slow in
+ * general. So, we try to allocate as many non-reladdr-loaded
+ * constants through the push buffer as we can before giving up.
+ */
+ memset(c->constant_map, -1, c->vp->program.Base.Parameters->NumParameters);
+ for (i = 0;
+ i < c->vp->program.Base.NumInstructions && constant < max_constant;
+ i++) {
+ struct prog_instruction *inst = &c->vp->program.Base.Instructions[i];
+ int arg;
+
+ for (arg = 0; arg < 3 && constant < max_constant; arg++) {
+ if ((inst->SrcReg[arg].File != PROGRAM_STATE_VAR &&
+ inst->SrcReg[arg].File != PROGRAM_CONSTANT &&
+ inst->SrcReg[arg].File != PROGRAM_UNIFORM &&
+ inst->SrcReg[arg].File != PROGRAM_ENV_PARAM &&
+ inst->SrcReg[arg].File != PROGRAM_LOCAL_PARAM) ||
+ inst->SrcReg[arg].RelAddr)
+ continue;
+
+ if (c->constant_map[inst->SrcReg[arg].Index] == -1) {
+ c->constant_map[inst->SrcReg[arg].Index] = constant++;
+ }
+ }
+ }
+
+ for (i = 0; i < constant; i++) {
+ c->regs[PROGRAM_STATE_VAR][i] = stride( brw_vec4_grf(reg+i/2,
+ (i%2) * 4),
+ 0, 4, 1);
+ }
+ reg += (constant + 1) / 2;
+ c->prog_data.curb_read_length = reg - 1;
+ /* XXX 0 causes a bug elsewhere... */
+ c->prog_data.nr_params = MAX2(constant * 4, 4);
}
else {
/* use a section of the GRF for constants */
case PROGRAM_ENV_PARAM:
case PROGRAM_LOCAL_PARAM:
if (c->vp->use_const_buffer) {
- if (relAddr)
+ if (!relAddr && c->constant_map[index] != -1) {
+ assert(c->regs[PROGRAM_STATE_VAR][c->constant_map[index]].nr != 0);
+ return c->regs[PROGRAM_STATE_VAR][c->constant_map[index]];
+ } else if (relAddr)
return get_reladdr_constant(c, inst, argIndex);
else
return get_constant(c, inst, argIndex);