broadcom/compiler: track partially interpolated fragment inputs
We will need these to implement GLSL's interpolateAt*() functions where we are required to perform interpolation in the shader at arbitrary offsets. Acked-by: Eric Anholt <eric@anholt.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7155>
This commit is contained in:

committed by
Alejandro Piñeiro

parent
71ed8c5aa6
commit
3ec165bce9
@@ -92,6 +92,29 @@ resize_qreg_array(struct v3d_compile *c,
|
|||||||
(*regs)[i] = c->undef;
|
(*regs)[i] = c->undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
resize_interp_array(struct v3d_compile *c,
|
||||||
|
struct v3d_interp_input **regs,
|
||||||
|
uint32_t *size,
|
||||||
|
uint32_t decl_size)
|
||||||
|
{
|
||||||
|
if (*size >= decl_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t old_size = *size;
|
||||||
|
*size = MAX2(*size * 2, decl_size);
|
||||||
|
*regs = reralloc(c, *regs, struct v3d_interp_input, *size);
|
||||||
|
if (!*regs) {
|
||||||
|
fprintf(stderr, "Malloc failure\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = old_size; i < *size; i++) {
|
||||||
|
(*regs)[i].vp = c->undef;
|
||||||
|
(*regs)[i].C = c->undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vir_emit_thrsw(struct v3d_compile *c)
|
vir_emit_thrsw(struct v3d_compile *c)
|
||||||
{
|
{
|
||||||
@@ -665,7 +688,7 @@ emit_fragcoord_input(struct v3d_compile *c, int attr)
|
|||||||
|
|
||||||
static struct qreg
|
static struct qreg
|
||||||
emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
||||||
uint8_t swizzle, int array_index)
|
int8_t input_idx, uint8_t swizzle, int array_index)
|
||||||
{
|
{
|
||||||
struct qreg r3 = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R3);
|
struct qreg r3 = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R3);
|
||||||
struct qreg r5 = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R5);
|
struct qreg r5 = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R5);
|
||||||
@@ -681,11 +704,22 @@ emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
|||||||
vary = r3;
|
vary = r3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the input value before interpolation so we can implement
|
||||||
|
* GLSL's interpolateAt functions if the shader uses them.
|
||||||
|
*/
|
||||||
|
if (input_idx >= 0) {
|
||||||
|
assert(var);
|
||||||
|
c->interp[input_idx].vp = vary;
|
||||||
|
c->interp[input_idx].C = vir_MOV(c, r5);
|
||||||
|
c->interp[input_idx].mode = var->data.interpolation;
|
||||||
|
}
|
||||||
|
|
||||||
/* For gl_PointCoord input or distance along a line, we'll be called
|
/* For gl_PointCoord input or distance along a line, we'll be called
|
||||||
* with no nir_variable, and we don't count toward VPM size so we
|
* with no nir_variable, and we don't count toward VPM size so we
|
||||||
* don't track an input slot.
|
* don't track an input slot.
|
||||||
*/
|
*/
|
||||||
if (!var) {
|
if (!var) {
|
||||||
|
assert(input_idx < 0);
|
||||||
return vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5);
|
return vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,6 +728,7 @@ emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
|||||||
v3d_slot_from_slot_and_component(var->data.location +
|
v3d_slot_from_slot_and_component(var->data.location +
|
||||||
array_index, swizzle);
|
array_index, swizzle);
|
||||||
|
|
||||||
|
struct qreg result;
|
||||||
switch (var->data.interpolation) {
|
switch (var->data.interpolation) {
|
||||||
case INTERP_MODE_NONE:
|
case INTERP_MODE_NONE:
|
||||||
/* If a gl_FrontColor or gl_BackColor input has no interp
|
/* If a gl_FrontColor or gl_BackColor input has no interp
|
||||||
@@ -708,11 +743,12 @@ emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
|||||||
if (c->fs_key->shade_model_flat) {
|
if (c->fs_key->shade_model_flat) {
|
||||||
BITSET_SET(c->flat_shade_flags, i);
|
BITSET_SET(c->flat_shade_flags, i);
|
||||||
vir_MOV_dest(c, c->undef, vary);
|
vir_MOV_dest(c, c->undef, vary);
|
||||||
return vir_MOV(c, r5);
|
result = vir_MOV(c, r5);
|
||||||
} else {
|
} else {
|
||||||
return vir_FADD(c, vir_FMUL(c, vary,
|
result = vir_FADD(c, vir_FMUL(c, vary,
|
||||||
c->payload_w), r5);
|
c->payload_w), r5);
|
||||||
}
|
}
|
||||||
|
goto done;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -720,21 +756,32 @@ emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
|
|||||||
case INTERP_MODE_SMOOTH:
|
case INTERP_MODE_SMOOTH:
|
||||||
if (var->data.centroid) {
|
if (var->data.centroid) {
|
||||||
BITSET_SET(c->centroid_flags, i);
|
BITSET_SET(c->centroid_flags, i);
|
||||||
return vir_FADD(c, vir_FMUL(c, vary,
|
result = vir_FADD(c, vir_FMUL(c, vary,
|
||||||
c->payload_w_centroid), r5);
|
c->payload_w_centroid), r5);
|
||||||
} else {
|
} else {
|
||||||
return vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5);
|
result = vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case INTERP_MODE_NOPERSPECTIVE:
|
case INTERP_MODE_NOPERSPECTIVE:
|
||||||
BITSET_SET(c->noperspective_flags, i);
|
BITSET_SET(c->noperspective_flags, i);
|
||||||
return vir_FADD(c, vir_MOV(c, vary), r5);
|
result = vir_FADD(c, vir_MOV(c, vary), r5);
|
||||||
|
break;
|
||||||
|
|
||||||
case INTERP_MODE_FLAT:
|
case INTERP_MODE_FLAT:
|
||||||
BITSET_SET(c->flat_shade_flags, i);
|
BITSET_SET(c->flat_shade_flags, i);
|
||||||
vir_MOV_dest(c, c->undef, vary);
|
vir_MOV_dest(c, c->undef, vary);
|
||||||
return vir_MOV(c, r5);
|
result = vir_MOV(c, r5);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unreachable("Bad interp mode");
|
unreachable("Bad interp mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (input_idx >= 0)
|
||||||
|
c->inputs[input_idx] = result;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -743,8 +790,8 @@ emit_fragment_input(struct v3d_compile *c, int base_attr, nir_variable *var,
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < nelem ; i++) {
|
for (int i = 0; i < nelem ; i++) {
|
||||||
int chan = var->data.location_frac + i;
|
int chan = var->data.location_frac + i;
|
||||||
c->inputs[(base_attr + array_index) * 4 + chan] =
|
int input_idx = (base_attr + array_index) * 4 + chan;
|
||||||
emit_fragment_varying(c, var, chan, array_index);
|
emit_fragment_varying(c, var, input_idx, chan, array_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,8 +804,8 @@ emit_compact_fragment_input(struct v3d_compile *c, int attr, nir_variable *var,
|
|||||||
*/
|
*/
|
||||||
int loc_offset = array_index / 4;
|
int loc_offset = array_index / 4;
|
||||||
int chan = var->data.location_frac + array_index % 4;
|
int chan = var->data.location_frac + array_index % 4;
|
||||||
c->inputs[(attr + loc_offset) * 4 + chan] =
|
int input_idx = (attr + loc_offset) * 4 + chan;
|
||||||
emit_fragment_varying(c, var, chan, loc_offset);
|
emit_fragment_varying(c, var, input_idx, chan, loc_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1705,8 +1752,12 @@ ntq_setup_fs_inputs(struct v3d_compile *c)
|
|||||||
unsigned var_len = glsl_count_vec4_slots(var->type, false, false);
|
unsigned var_len = glsl_count_vec4_slots(var->type, false, false);
|
||||||
unsigned loc = var->data.driver_location;
|
unsigned loc = var->data.driver_location;
|
||||||
|
|
||||||
|
uint32_t inputs_array_size = c->inputs_array_size;
|
||||||
|
uint32_t inputs_array_required_size = (loc + var_len) * 4;
|
||||||
resize_qreg_array(c, &c->inputs, &c->inputs_array_size,
|
resize_qreg_array(c, &c->inputs, &c->inputs_array_size,
|
||||||
(loc + var_len) * 4);
|
inputs_array_required_size);
|
||||||
|
resize_interp_array(c, &c->interp, &inputs_array_size,
|
||||||
|
inputs_array_required_size);
|
||||||
|
|
||||||
if (var->data.location == VARYING_SLOT_POS) {
|
if (var->data.location == VARYING_SLOT_POS) {
|
||||||
emit_fragcoord_input(c, loc);
|
emit_fragcoord_input(c, loc);
|
||||||
@@ -2841,14 +2892,14 @@ nir_to_vir(struct v3d_compile *c)
|
|||||||
*/
|
*/
|
||||||
if (c->fs_key->is_points &&
|
if (c->fs_key->is_points &&
|
||||||
(c->devinfo->ver < 40 || program_reads_point_coord(c))) {
|
(c->devinfo->ver < 40 || program_reads_point_coord(c))) {
|
||||||
c->point_x = emit_fragment_varying(c, NULL, 0, 0);
|
c->point_x = emit_fragment_varying(c, NULL, -1, 0, 0);
|
||||||
c->point_y = emit_fragment_varying(c, NULL, 0, 0);
|
c->point_y = emit_fragment_varying(c, NULL, -1, 0, 0);
|
||||||
c->uses_implicit_point_line_varyings = true;
|
c->uses_implicit_point_line_varyings = true;
|
||||||
} else if (c->fs_key->is_lines &&
|
} else if (c->fs_key->is_lines &&
|
||||||
(c->devinfo->ver < 40 ||
|
(c->devinfo->ver < 40 ||
|
||||||
(c->s->info.system_values_read &
|
(c->s->info.system_values_read &
|
||||||
BITFIELD64_BIT(SYSTEM_VALUE_LINE_COORD)))) {
|
BITFIELD64_BIT(SYSTEM_VALUE_LINE_COORD)))) {
|
||||||
c->line_x = emit_fragment_varying(c, NULL, 0, 0);
|
c->line_x = emit_fragment_varying(c, NULL, -1, 0, 0);
|
||||||
c->uses_implicit_point_line_varyings = true;
|
c->uses_implicit_point_line_varyings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -525,6 +525,17 @@ struct v3d_compiler {
|
|||||||
unsigned int reg_class_phys_or_acc[3];
|
unsigned int reg_class_phys_or_acc[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds partially interpolated inputs as provided by hardware
|
||||||
|
* (The Vp = A*(x - x0) + B*(y - y0) term), as well as the C coefficient
|
||||||
|
* required to compute the final interpolated value.
|
||||||
|
*/
|
||||||
|
struct v3d_interp_input {
|
||||||
|
struct qreg vp;
|
||||||
|
struct qreg C;
|
||||||
|
unsigned mode; /* interpolation mode */
|
||||||
|
};
|
||||||
|
|
||||||
struct v3d_compile {
|
struct v3d_compile {
|
||||||
const struct v3d_device_info *devinfo;
|
const struct v3d_device_info *devinfo;
|
||||||
nir_shader *s;
|
nir_shader *s;
|
||||||
@@ -552,6 +563,10 @@ struct v3d_compile {
|
|||||||
* Not all fragment shader QFILE_VARY reads are present in this array.
|
* Not all fragment shader QFILE_VARY reads are present in this array.
|
||||||
*/
|
*/
|
||||||
struct qreg *inputs;
|
struct qreg *inputs;
|
||||||
|
/**
|
||||||
|
* Partially interpolated inputs to the shader.
|
||||||
|
*/
|
||||||
|
struct v3d_interp_input *interp;
|
||||||
struct qreg *outputs;
|
struct qreg *outputs;
|
||||||
bool msaa_per_sample_output;
|
bool msaa_per_sample_output;
|
||||||
struct qreg color_reads[V3D_MAX_DRAW_BUFFERS * V3D_MAX_SAMPLES * 4];
|
struct qreg color_reads[V3D_MAX_DRAW_BUFFERS * V3D_MAX_SAMPLES * 4];
|
||||||
|
Reference in New Issue
Block a user