}
}
+static void
+emit_compact_fragment_input(struct v3d_compile *c, int attr, nir_variable *var,
+ int array_index)
+{
+ /* Compact variables are scalar arrays where each set of 4 elements
+ * consumes a single location.
+ */
+ int loc_offset = array_index / 4;
+ int chan = var->data.location_frac + array_index % 4;
+ c->inputs[(attr + loc_offset) * 4 + chan] =
+ emit_fragment_varying(c, var, chan, loc_offset);
+}
+
static void
add_output(struct v3d_compile *c,
uint32_t decl_offset,
const nir_variable *const *a = in_a;
const nir_variable *const *b = in_b;
+ if ((*a)->data.driver_location == (*b)->data.driver_location)
+ return (*a)->data.location_frac - (*b)->data.location_frac;
+
return (*a)->data.driver_location - (*b)->data.driver_location;
}
* from the start of the attribute to the number of components we
* declare we need in c->vattr_sizes[].
*/
- nir_foreach_variable(var, &c->s->inputs) {
+ nir_foreach_shader_in_variable(var, c->s) {
/* No VS attribute array support. */
assert(MAX2(glsl_get_length(var->type), 1) == 1);
static bool
program_reads_point_coord(struct v3d_compile *c)
{
- nir_foreach_variable(var, &c->s->inputs) {
+ nir_foreach_shader_in_variable(var, c->s) {
if (util_varying_is_point_coord(var->data.location,
c->fs_key->point_sprite_mask)) {
return true;
nir_variable ***vars)
{
*num_entries = 0;
- nir_foreach_variable(var, &c->s->inputs)
+ nir_foreach_shader_in_variable(var, c->s)
(*num_entries)++;
*vars = ralloc_array(c, nir_variable *, *num_entries);
unsigned i = 0;
- nir_foreach_variable(var, &c->s->inputs)
+ nir_foreach_shader_in_variable(var, c->s)
(*vars)[i++] = var;
/* Sort the variables so that we emit the input setup in
c->fs_key->point_sprite_mask)) {
c->inputs[loc * 4 + 0] = c->point_x;
c->inputs[loc * 4 + 1] = c->point_y;
+ } else if (var->data.compact) {
+ for (int j = 0; j < array_len; j++)
+ emit_compact_fragment_input(c, loc, var, j);
} else {
for (int j = 0; j < array_len; j++)
emit_fragment_input(c, loc + j, var, j);
if (c->s->info.stage != MESA_SHADER_FRAGMENT)
return;
- nir_foreach_variable(var, &c->s->outputs) {
+ nir_foreach_shader_out_variable(var, c->s) {
unsigned array_len = MAX2(glsl_get_length(var->type), 1);
unsigned loc = var->data.driver_location * 4;
vir_uniform(c, QUNIFORM_IMAGE_WIDTH, image_index));
if (instr->num_components > 1) {
ntq_store_dest(c, &instr->dest, 1,
- vir_uniform(c, QUNIFORM_IMAGE_HEIGHT,
+ vir_uniform(c,
+ instr->num_components == 2 && is_array ?
+ QUNIFORM_IMAGE_ARRAY_SIZE :
+ QUNIFORM_IMAGE_HEIGHT,
image_index));
}
if (instr->num_components > 2) {
{
assert(instr->num_components == 1);
+ struct qreg offset = ntq_get_src(c, instr->src[1], 0);
+
uint32_t base_offset = nir_intrinsic_base(instr);
- struct qreg src_offset = ntq_get_src(c, instr->src[1], 0);
- struct qreg offset =
- vir_ADD(c, vir_uniform_ui(c, base_offset), src_offset);
+
+ if (base_offset)
+ offset = vir_ADD(c, vir_uniform_ui(c, base_offset), offset);
/* Usually, for VS or FS, we only emit outputs once at program end so
* our VPM writes are never in non-uniform control flow, but this
vir_uniform(c, QUNIFORM_ALPHA_REF, 0));
break;
+ case nir_intrinsic_load_line_coord:
+ ntq_store_dest(c, &instr->dest, 0, vir_MOV(c, c->line_x));
+ break;
+
+ case nir_intrinsic_load_line_width:
+ ntq_store_dest(c, &instr->dest, 0,
+ vir_uniform(c, QUNIFORM_LINE_WIDTH, 0));
+ break;
+
+ case nir_intrinsic_load_aa_line_width:
+ ntq_store_dest(c, &instr->dest, 0,
+ vir_uniform(c, QUNIFORM_AA_LINE_WIDTH, 0));
+ break;
+
case nir_intrinsic_load_sample_mask_in:
ntq_store_dest(c, &instr->dest, 0, vir_MSF(c));
break;
case nir_jump_return:
unreachable("All returns shouold be lowered\n");
+ break;
+
+ case nir_jump_goto:
+ case nir_jump_goto_if:
+ unreachable("not supported\n");
+ break;
}
}
c->point_x = emit_fragment_varying(c, NULL, 0, 0);
c->point_y = emit_fragment_varying(c, NULL, 0, 0);
c->uses_implicit_point_line_varyings = true;
- } else if (c->fs_key->is_lines && c->devinfo->ver < 40) {
+ } else if (c->fs_key->is_lines &&
+ (c->devinfo->ver < 40 ||
+ (c->s->info.system_values_read &
+ BITFIELD64_BIT(SYSTEM_VALUE_LINE_COORD)))) {
c->line_x = emit_fragment_varying(c, NULL, 0, 0);
c->uses_implicit_point_line_varyings = true;
}
break;
if (c->threads == min_threads) {
- fprintf(stderr, "Failed to register allocate at %d threads:\n",
- c->threads);
- vir_dump(c);
- c->failed = true;
+ if (c->fallback_scheduler) {
+ fprintf(stderr,
+ "Failed to register allocate at %d "
+ "threads:\n",
+ c->threads);
+ vir_dump(c);
+ }
+ c->compilation_result =
+ V3D_COMPILATION_FAILED_REGISTER_ALLOCATION;
return;
}