i965/vs: Start adding support for uniforms

There's no clever packing here, no pull constants, and no array support.
This commit is contained in:
Eric Anholt 2011-05-04 12:50:16 -07:00
parent af3c9803d8
commit a070d5f363
9 changed files with 257 additions and 49 deletions

View file

@ -248,6 +248,7 @@ enum param_conversion {
PARAM_CONVERT_F2I,
PARAM_CONVERT_F2U,
PARAM_CONVERT_F2B,
PARAM_CONVERT_ZERO,
};
/* Data about a particular attempt to compile a program. Note that
@ -317,6 +318,13 @@ struct brw_vs_prog_data {
/* Used for calculating urb partitions:
*/
GLuint urb_entry_size;
const float *param[MAX_UNIFORMS * 4]; /* should be: BRW_MAX_CURBE */
enum param_conversion param_convert[MAX_UNIFORMS * 4];
const float *pull_param[MAX_UNIFORMS * 4];
enum param_conversion pull_param_convert[MAX_UNIFORMS * 4];
bool uses_new_param_layout;
};
@ -898,7 +906,7 @@ brw_fragment_program_const(const struct gl_fragment_program *p)
}
static inline
float convert_param(enum param_conversion conversion, float param)
float convert_param(enum param_conversion conversion, const float *param)
{
union {
float f;
@ -908,21 +916,23 @@ float convert_param(enum param_conversion conversion, float param)
switch (conversion) {
case PARAM_NO_CONVERT:
return param;
return *param;
case PARAM_CONVERT_F2I:
fi.i = param;
fi.i = *param;
return fi.f;
case PARAM_CONVERT_F2U:
fi.u = param;
fi.u = *param;
return fi.f;
case PARAM_CONVERT_F2B:
if (param != 0.0)
if (*param != 0.0)
fi.i = 1;
else
fi.i = 0;
return fi.f;
case PARAM_CONVERT_ZERO:
return 0.0;
default:
return param;
return *param;
}
}

View file

@ -203,7 +203,7 @@ static void prepare_constant_buffer(struct brw_context *brw)
/* copy float constants */
for (i = 0; i < brw->wm.prog_data->nr_params; i++) {
buf[offset + i] = convert_param(brw->wm.prog_data->param_convert[i],
*brw->wm.prog_data->param[i]);
brw->wm.prog_data->param[i]);
}
}
@ -244,15 +244,22 @@ static void prepare_constant_buffer(struct brw_context *brw)
GLuint offset = brw->curbe.vs_start * 16;
GLuint nr = brw->vs.prog_data->nr_params / 4;
/* 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));
if (brw->vs.prog_data->uses_new_param_layout) {
for (i = 0; i < brw->vs.prog_data->nr_params; i++) {
buf[offset + i] = convert_param(brw->vs.prog_data->param_convert[i],
brw->vs.prog_data->param[i]);
}
} else {
/* 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));
}
}
}
}

View file

@ -356,6 +356,8 @@ public:
* for the ir->location's used.
*/
dst_reg output_reg[VERT_RESULT_MAX];
int uniform_size[MAX_UNIFORMS];
int uniforms;
struct hash_table *variable_ht;
@ -363,7 +365,10 @@ public:
void fail(const char *msg, ...);
int virtual_grf_alloc(int size);
int setup_uniform_values(int loc, const glsl_type *type);
void setup_builtin_uniform_values(ir_variable *ir);
int setup_attributes(int payload_reg);
int setup_uniforms(int payload_reg);
void setup_payload();
void reg_allocate_trivial();
void reg_allocate();

View file

@ -67,20 +67,12 @@ vec4_visitor::setup_attributes(int payload_reg)
prog_data->urb_read_length = (nr_attributes + 1) / 2;
return nr_attributes;
return payload_reg + nr_attributes;
}
void
vec4_visitor::setup_payload(void)
int
vec4_visitor::setup_uniforms(int reg)
{
int reg = 0;
/* r0 is always reserved, as it contains the payload with the URB
* handles that are passed on to the URB write at the end of the
* thread.
*/
reg++;
/* User clip planes from curbe:
*/
if (c->key.nr_userclip) {
@ -99,14 +91,49 @@ vec4_visitor::setup_payload(void)
}
}
/* FINISHME: push constants */
c->prog_data.curb_read_length = reg - 1;
c->prog_data.nr_params = 0;
/* XXX 0 causes a bug elsewhere... */
if (intel->gen < 6 && c->prog_data.nr_params == 0)
c->prog_data.nr_params = 4;
/* The pre-gen6 VS requires that some push constants get loaded no
* matter what, or the GPU would hang.
*/
if (this->uniforms == 0) {
this->uniform_size[this->uniforms] = 1;
reg += setup_attributes(reg);
for (unsigned int i = 0; i < 4; i++) {
unsigned int slot = this->uniforms * 4 + i;
c->prog_data.param[slot] = NULL;
c->prog_data.param_convert[slot] = PARAM_CONVERT_ZERO;
}
this->uniforms++;
} else {
reg += ALIGN(uniforms, 2) / 2;
}
/* for now, we are not doing any elimination of unused slots, nor
* are we packing our uniforms.
*/
c->prog_data.nr_params = this->uniforms * 4;
c->prog_data.curb_read_length = reg - 1;
c->prog_data.uses_new_param_layout = true;
return reg;
}
void
vec4_visitor::setup_payload(void)
{
int reg = 0;
/* The payload always contains important data in g0, which contains
* the URB handles that are passed on to the URB write at the end
* of the thread. So, we always start push constants at g1.
*/
reg++;
reg = setup_uniforms(reg);
reg = setup_attributes(reg);
this->first_non_payload_grf = reg;
}
@ -174,6 +201,18 @@ vec4_instruction::get_src(int i)
}
break;
case UNIFORM:
brw_reg = stride(brw_vec4_grf(1 + (src[i].reg + src[i].reg_offset) / 2,
((src[i].reg + src[i].reg_offset) % 2) * 4),
0, 4, 1);
brw_reg = retype(brw_reg, src[i].type);
brw_reg.dw1.bits.swizzle = src[i].swizzle;
if (src[i].abs)
brw_reg = brw_abs(brw_reg);
if (src[i].negate)
brw_reg = negate(brw_reg);
break;
case HW_REG:
brw_reg = src[i].fixed_hw_reg;
break;

View file

@ -22,7 +22,10 @@
*/
#include "brw_vec4.h"
extern "C" {
#include "main/macros.h"
#include "program/prog_parameter.h"
}
namespace brw {
@ -306,6 +309,130 @@ dst_reg::dst_reg(class vec4_visitor *v, const struct glsl_type *type)
this->type = brw_type_for_base_type(type);
}
/* Our support for uniforms is piggy-backed on the struct
* gl_fragment_program, because that's where the values actually
* get stored, rather than in some global gl_shader_program uniform
* store.
*/
int
vec4_visitor::setup_uniform_values(int loc, const glsl_type *type)
{
unsigned int offset = 0;
float *values = &this->vp->Base.Parameters->ParameterValues[loc][0].f;
if (type->is_matrix()) {
const glsl_type *column = glsl_type::get_instance(GLSL_TYPE_FLOAT,
type->vector_elements,
1);
for (unsigned int i = 0; i < type->matrix_columns; i++) {
offset += setup_uniform_values(loc + offset, column);
}
return offset;
}
switch (type->base_type) {
case GLSL_TYPE_FLOAT:
case GLSL_TYPE_UINT:
case GLSL_TYPE_INT:
case GLSL_TYPE_BOOL:
for (unsigned int i = 0; i < type->vector_elements; i++) {
int slot = this->uniforms * 4 + i;
switch (type->base_type) {
case GLSL_TYPE_FLOAT:
c->prog_data.param_convert[slot] = PARAM_NO_CONVERT;
break;
case GLSL_TYPE_UINT:
c->prog_data.param_convert[slot] = PARAM_CONVERT_F2U;
break;
case GLSL_TYPE_INT:
c->prog_data.param_convert[slot] = PARAM_CONVERT_F2I;
break;
case GLSL_TYPE_BOOL:
c->prog_data.param_convert[slot] = PARAM_CONVERT_F2B;
break;
default:
assert(!"not reached");
c->prog_data.param_convert[slot] = PARAM_NO_CONVERT;
break;
}
c->prog_data.param[slot] = &values[i];
}
for (unsigned int i = type->vector_elements; i < 4; i++) {
c->prog_data.param_convert[this->uniforms * 4 + i] =
PARAM_CONVERT_ZERO;
c->prog_data.param[this->uniforms * 4 + i] = NULL;
}
this->uniform_size[this->uniforms] = type->vector_elements;
this->uniforms++;
return 1;
case GLSL_TYPE_STRUCT:
for (unsigned int i = 0; i < type->length; i++) {
offset += setup_uniform_values(loc + offset,
type->fields.structure[i].type);
}
return offset;
case GLSL_TYPE_ARRAY:
for (unsigned int i = 0; i < type->length; i++) {
offset += setup_uniform_values(loc + offset, type->fields.array);
}
return offset;
case GLSL_TYPE_SAMPLER:
/* The sampler takes up a slot, but we don't use any values from it. */
return 1;
default:
assert(!"not reached");
return 0;
}
}
/* Our support for builtin uniforms is even scarier than non-builtin.
* It sits on top of the PROG_STATE_VAR parameters that are
* automatically updated from GL context state.
*/
void
vec4_visitor::setup_builtin_uniform_values(ir_variable *ir)
{
const ir_state_slot *const slots = ir->state_slots;
assert(ir->state_slots != NULL);
for (unsigned int i = 0; i < ir->num_state_slots; i++) {
/* This state reference has already been setup by ir_to_mesa,
* but we'll get the same index back here. We can reference
* ParameterValues directly, since unlike brw_fs.cpp, we never
* add new state references during compile.
*/
int index = _mesa_add_state_reference(this->vp->Base.Parameters,
(gl_state_index *)slots[i].tokens);
float *values = &this->vp->Base.Parameters->ParameterValues[index][0].f;
this->uniform_size[this->uniforms] = 0;
/* Add each of the unique swizzled channels of the element.
* This will end up matching the size of the glsl_type of this field.
*/
int last_swiz = -1;
for (unsigned int j = 0; j < 4; j++) {
int swiz = GET_SWZ(slots[i].swizzle, j);
if (swiz == last_swiz)
break;
last_swiz = swiz;
c->prog_data.param[this->uniforms * 4 + j] = &values[swiz];
c->prog_data.param_convert[this->uniforms * 4 + j] = PARAM_NO_CONVERT;
this->uniform_size[this->uniforms]++;
}
this->uniforms++;
}
}
dst_reg *
vec4_visitor::variable_storage(ir_variable *var)
{
@ -496,13 +623,10 @@ vec4_visitor::visit(ir_variable *ir)
switch (ir->mode) {
case ir_var_in:
reg = new(mem_ctx) dst_reg(ATTR, ir->location);
reg->type = brw_type_for_base_type(ir->type);
hash_table_insert(this->variable_ht, reg, ir);
break;
case ir_var_out:
reg = new(mem_ctx) dst_reg(this, ir->type);
hash_table_insert(this->variable_ht, reg, ir);
for (int i = 0; i < type_size(ir->type); i++) {
output_reg[ir->location + i] = *reg;
@ -512,14 +636,21 @@ vec4_visitor::visit(ir_variable *ir)
case ir_var_temporary:
reg = new(mem_ctx) dst_reg(this, ir->type);
hash_table_insert(this->variable_ht, reg, ir);
break;
case ir_var_uniform:
/* FINISHME: uniforms */
reg = new(this->mem_ctx) dst_reg(UNIFORM, this->uniforms);
if (!strncmp(ir->name, "gl_", 3)) {
setup_builtin_uniform_values(ir);
} else {
setup_uniform_values(ir->location, ir->type);
}
break;
}
reg->type = brw_type_for_base_type(ir->type);
hash_table_insert(this->variable_ht, reg, ir);
}
void
@ -1606,6 +1737,7 @@ vec4_visitor::vec4_visitor(struct brw_vs_compile *c,
this->current_annotation = NULL;
this->c = c;
this->vp = brw->vertex_program; /* FINISHME: change for precompile */
this->prog_data = &c->prog_data;
this->variable_ht = hash_table_ctor(0,
@ -1615,6 +1747,12 @@ vec4_visitor::vec4_visitor(struct brw_vs_compile *c,
this->virtual_grf_sizes = NULL;
this->virtual_grf_count = 0;
this->virtual_grf_array_size = 0;
this->uniforms = 0;
this->variable_ht = hash_table_ctor(0,
hash_table_pointer_hash,
hash_table_pointer_compare);
}
vec4_visitor::~vec4_visitor()

View file

@ -342,7 +342,7 @@ prepare_wm_pull_constants(struct brw_context *brw)
constants = brw->wm.const_bo->virtual;
for (i = 0; i < brw->wm.prog_data->nr_pull_params; i++) {
constants[i] = convert_param(brw->wm.prog_data->pull_param_convert[i],
*brw->wm.prog_data->pull_param[i]);
brw->wm.prog_data->pull_param[i]);
}
drm_intel_gem_bo_unmap_gtt(brw->wm.const_bo);

View file

@ -81,12 +81,21 @@ gen6_prepare_vs_push_constants(struct brw_context *brw)
params_uploaded++;
}
for (i = 0; i < vp->program.Base.Parameters->NumParameters; i++) {
if (brw->vs.constant_map[i] != -1) {
memcpy(param + brw->vs.constant_map[i] * 4,
vp->program.Base.Parameters->ParameterValues[i],
4 * sizeof(float));
params_uploaded++;
if (brw->vs.prog_data->uses_new_param_layout) {
for (i = 0; i < brw->vs.prog_data->nr_params; i++) {
*param = convert_param(brw->vs.prog_data->param_convert[i],
brw->vs.prog_data->param[i]);
param++;
}
params_uploaded += brw->vs.prog_data->nr_params / 4;
} else {
for (i = 0; i < vp->program.Base.Parameters->NumParameters; i++) {
if (brw->vs.constant_map[i] != -1) {
memcpy(param + brw->vs.constant_map[i] * 4,
vp->program.Base.Parameters->ParameterValues[i],
4 * sizeof(float));
params_uploaded++;
}
}
}

View file

@ -61,7 +61,7 @@ gen6_prepare_wm_push_constants(struct brw_context *brw)
for (i = 0; i < brw->wm.prog_data->nr_params; i++) {
constants[i] = convert_param(brw->wm.prog_data->param_convert[i],
*brw->wm.prog_data->param[i]);
brw->wm.prog_data->param[i]);
}
if (0) {

View file

@ -58,7 +58,7 @@ gen7_prepare_wm_constants(struct brw_context *brw)
for (i = 0; i < brw->wm.prog_data->nr_params; i++) {
constants[i] = convert_param(brw->wm.prog_data->param_convert[i],
*brw->wm.prog_data->param[i]);
brw->wm.prog_data->param[i]);
}
if (0) {