/* Get rid of split copies */
nir_optimize(nir);
+ nir_assign_var_locations_scalar_direct_first(nir, &nir->uniforms,
+ &num_direct_uniforms,
+ &nir->num_uniforms);
+ nir_assign_var_locations_scalar(&nir->inputs, &nir->num_inputs);
+ nir_assign_var_locations_scalar(&nir->outputs, &nir->num_outputs);
+
nir_lower_io(nir);
nir_validate_shader(nir);
}
if (nir->num_uniforms > 0) {
- nir_uniforms = fs_reg(UNIFORM, 0);
nir_setup_uniforms(nir);
}
void
fs_visitor::nir_setup_inputs(nir_shader *shader)
{
- struct hash_entry *entry;
- hash_table_foreach(shader->inputs, entry) {
- nir_variable *var = (nir_variable *) entry->data;
- fs_reg varying = offset(nir_inputs, var->data.driver_location);
+ foreach_list_typed(nir_variable, var, node, &shader->inputs) {
+ enum brw_reg_type type = brw_type_for_base_type(var->type);
+ fs_reg input = offset(nir_inputs, var->data.driver_location);
fs_reg reg;
- if (var->data.location == VARYING_SLOT_POS) {
- reg = *emit_fragcoord_interpolation(var->data.pixel_center_integer,
- var->data.origin_upper_left);
- emit_percomp(MOV(varying, reg), 0xF);
- } else {
- emit_general_interpolation(varying, var->name, var->type,
- (glsl_interp_qualifier) var->data.interpolation,
- var->data.location, var->data.centroid,
- var->data.sample);
+ switch (stage) {
+ case MESA_SHADER_VERTEX: {
+ /* Our ATTR file is indexed by VERT_ATTRIB_*, which is the value
+ * stored in nir_variable::location.
+ *
+ * However, NIR's load_input intrinsics use a different index - an
+ * offset into a single contiguous array containing all inputs.
+ * This index corresponds to the nir_variable::driver_location field.
+ *
+ * So, we need to copy from fs_reg(ATTR, var->location) to
+ * offset(nir_inputs, var->data.driver_location).
+ */
+ unsigned components = var->type->without_array()->components();
+ unsigned array_length = var->type->is_array() ? var->type->length : 1;
+ for (unsigned i = 0; i < array_length; i++) {
+ for (unsigned j = 0; j < components; j++) {
+ emit(MOV(retype(offset(input, components * i + j), type),
+ offset(fs_reg(ATTR, var->data.location + i, type), j)));
+ }
+ }
+ break;
+ }
+ case MESA_SHADER_GEOMETRY:
+ case MESA_SHADER_COMPUTE:
+ unreachable("fs_visitor not used for these stages yet.");
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (var->data.location == VARYING_SLOT_POS) {
+ reg = *emit_fragcoord_interpolation(var->data.pixel_center_integer,
+ var->data.origin_upper_left);
+ emit_percomp(MOV(input, reg), 0xF);
+ } else {
+ emit_general_interpolation(input, var->name, var->type,
+ (glsl_interp_qualifier) var->data.interpolation,
+ var->data.location, var->data.centroid,
+ var->data.sample);
+ }
+ break;
}
}
}
{
brw_wm_prog_key *key = (brw_wm_prog_key*) this->key;
- struct hash_entry *entry;
- hash_table_foreach(shader->outputs, entry) {
- nir_variable *var = (nir_variable *) entry->data;
+ foreach_list_typed(nir_variable, var, node, &shader->outputs) {
fs_reg reg = offset(nir_outputs, var->data.driver_location);
- if (var->data.index > 0) {
+ int vector_elements =
+ var->type->is_array() ? var->type->fields.array->vector_elements
+ : var->type->vector_elements;
+
+ if (stage == MESA_SHADER_VERTEX) {
+ for (int i = 0; i < ALIGN(type_size(var->type), 4) / 4; i++) {
+ int output = var->data.location + i;
+ this->outputs[output] = offset(reg, 4 * i);
+ this->output_components[output] = vector_elements;
+ }
+ } else if (var->data.index > 0) {
assert(var->data.location == FRAG_RESULT_DATA0);
assert(var->data.index == 1);
this->dual_src_output = reg;
assert(var->data.location >= FRAG_RESULT_DATA0 &&
var->data.location < FRAG_RESULT_DATA0 + BRW_MAX_DRAW_BUFFERS);
- int vector_elements =
- var->type->is_array() ? var->type->fields.array->vector_elements
- : var->type->vector_elements;
-
/* General color output. */
for (unsigned int i = 0; i < MAX2(1, var->type->length); i++) {
int output = var->data.location - FRAG_RESULT_DATA0 + i;
fs_visitor::nir_setup_uniforms(nir_shader *shader)
{
uniforms = shader->num_uniforms;
- param_size[0] = shader->num_uniforms;
+
+ /* We split the uniform register file in half. The first half is
+ * entirely direct uniforms. The second half is indirect.
+ */
+ param_size[0] = num_direct_uniforms;
+ if (shader->num_uniforms > num_direct_uniforms)
+ param_size[num_direct_uniforms] = shader->num_uniforms - num_direct_uniforms;
if (dispatch_width != 8)
return;
- struct hash_entry *entry;
- hash_table_foreach(shader->uniforms, entry) {
- nir_variable *var = (nir_variable *) entry->data;
-
+ foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
/* UBO's and atomics don't take up space in the uniform file */
if (var->interface_type != NULL || var->type->contains_atomic())
case nir_intrinsic_load_uniform_indirect:
has_indirect = true;
case nir_intrinsic_load_uniform: {
- unsigned index = 0;
+ unsigned index = instr->const_index[0];
+
+ fs_reg uniform_reg;
+ if (index < num_direct_uniforms) {
+ uniform_reg = fs_reg(UNIFORM, 0);
+ } else {
+ uniform_reg = fs_reg(UNIFORM, num_direct_uniforms);
+ index -= num_direct_uniforms;
+ }
+
for (int i = 0; i < instr->const_index[1]; i++) {
for (unsigned j = 0; j < instr->num_components; j++) {
- fs_reg src = offset(retype(nir_uniforms, dest.type),
- instr->const_index[0] + index);
+ fs_reg src = offset(retype(uniform_reg, dest.type), index);
if (has_indirect)
src.reladdr = new(mem_ctx) fs_reg(get_nir_src(instr->src[0]));
index++;