asahi: Lower edge flags

With the common geometry shader based lowering added for zink. Fixes edge flag
related piglits.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26614>
This commit is contained in:
Alyssa Rosenzweig 2023-11-27 11:53:14 -04:00
parent f4a648c607
commit 23f216d6e7
7 changed files with 60 additions and 9 deletions

View file

@ -2943,6 +2943,8 @@ agx_preprocess_nir(nir_shader *nir, const nir_shader *libagx,
out->inputs_flat_shaded = masks.flat;
out->inputs_linear_shaded = masks.linear;
}
} else if (nir->info.stage == MESA_SHADER_VERTEX) {
out->has_edgeflags = nir->info.outputs_written & VARYING_BIT_EDGE;
}
/* Clean up deref gunk after lowering I/O */

View file

@ -98,6 +98,7 @@ union agx_varyings {
struct agx_uncompiled_shader_info {
uint64_t inputs_flat_shaded;
uint64_t inputs_linear_shaded;
bool has_edgeflags;
};
struct agx_shader_info {

View file

@ -390,7 +390,12 @@ lower_id(nir_builder *b, nir_intrinsic_instr *intr, void *data)
id = load_instance_id(b);
else if (intr->intrinsic == nir_intrinsic_load_num_vertices)
id = nir_channel(b, nir_load_num_workgroups(b), 0);
else
else if (intr->intrinsic == nir_intrinsic_load_flat_mask)
id = load_geometry_param(b, flat_outputs);
else if (intr->intrinsic == nir_intrinsic_load_provoking_last) {
id = nir_b2b32(
b, libagx_is_provoking_last(b, nir_load_input_assembly_buffer_agx(b)));
} else
return false;
b->cursor = nir_instr_remove(&intr->instr);

View file

@ -463,3 +463,9 @@ libagx_prefix_sum(global uint *buffer, uint len, uint words, uint2 local_id)
*ptr = count + sub_group_scan_exclusive_add(value) + value;
}
}
bool
libagx_is_provoking_last(global struct agx_ia_state *ia)
{
return !ia->flatshade_first;
}

View file

@ -131,6 +131,9 @@ struct agx_geometry_params {
*/
uint32_t xfb_prims[MAX_VERTEX_STREAMS];
/* Location-indexed mask of flat outputs, used for lowering GL edge flags. */
uint64_t flat_outputs;
/* Within an indirect GS draw, the grid used to dispatch the GS written out
* by the GS indirect setup kernel. Unused for direct GS draws.
*/

View file

@ -409,6 +409,14 @@ agx_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
ctx->rast = so;
}
static bool
has_edgeflags(struct agx_context *ctx, enum mesa_prim mode)
{
return ctx->stage[PIPE_SHADER_VERTEX].shader->info.has_edgeflags &&
mode == MESA_PRIM_TRIANGLES &&
(ctx->rast->base.fill_front != PIPE_POLYGON_MODE_FILL);
}
static enum agx_wrap
agx_wrap_from_pipe(enum pipe_tex_wrap in)
{
@ -2318,9 +2326,13 @@ agx_delete_shader_state(struct pipe_context *ctx, void *cso)
_mesa_hash_table_destroy(so->variants, agx_delete_compiled_shader);
blob_finish(&so->serialized_nir);
for (unsigned i = 0; i < ARRAY_SIZE(so->passthrough_progs); ++i) {
if (so->passthrough_progs[i])
agx_delete_shader_state(ctx, so->passthrough_progs[i]);
for (unsigned i = 0; i < MESA_PRIM_COUNT; ++i) {
for (unsigned j = 0; j < 3; ++j) {
for (unsigned k = 0; k < 2; ++k) {
if (so->passthrough_progs[i][j][k])
agx_delete_shader_state(ctx, so->passthrough_progs[i][j][k]);
}
}
}
ralloc_free(so);
@ -3466,6 +3478,8 @@ agx_batch_geometry_params(struct agx_batch *batch, uint64_t input_index_buffer,
struct agx_geometry_params params = {
.state = agx_batch_geometry_state(batch),
.indirect_desc = batch->geom_indirect,
.flat_outputs =
batch->ctx->stage[PIPE_SHADER_FRAGMENT].shader->info.inputs_flat_shaded,
};
for (unsigned i = 0; i < ARRAY_SIZE(batch->ctx->streamout.targets); ++i) {
@ -3800,17 +3814,37 @@ agx_needs_passthrough_gs(struct agx_context *ctx,
ctx->streamout.num_targets)
return true;
/* Edge flags are emulated with a geometry shader */
if (has_edgeflags(ctx, info->mode))
return true;
/* Otherwise, we don't need one */
return false;
}
static enum mesa_prim
rast_prim(enum mesa_prim mode, unsigned fill_mode)
{
if (u_reduced_prim(mode) == MESA_PRIM_TRIANGLES) {
if (fill_mode == PIPE_POLYGON_MODE_POINT)
return MESA_PRIM_POINTS;
else if (fill_mode == PIPE_POLYGON_MODE_LINE)
return MESA_PRIM_LINES;
}
return mode;
}
static struct agx_uncompiled_shader *
agx_get_passthrough_gs(struct agx_context *ctx,
struct agx_uncompiled_shader *prev_cso,
enum mesa_prim mode)
{
if (prev_cso->passthrough_progs[mode])
return prev_cso->passthrough_progs[mode];
bool edgeflags = has_edgeflags(ctx, mode);
unsigned poly_mode = ctx->rast->base.fill_front;
if (prev_cso->passthrough_progs[mode][poly_mode][edgeflags])
return prev_cso->passthrough_progs[mode][poly_mode][edgeflags];
struct blob_reader reader;
blob_reader_init(&reader, prev_cso->early_serialized_nir.data,
@ -3818,13 +3852,13 @@ agx_get_passthrough_gs(struct agx_context *ctx,
nir_shader *prev = nir_deserialize(NULL, &agx_nir_options, &reader);
nir_shader *gs = nir_create_passthrough_gs(
&agx_nir_options, prev, mode, mode, false /* emulate edge flags */,
&agx_nir_options, prev, mode, rast_prim(mode, poly_mode), edgeflags,
false /* force line strip out */);
ralloc_free(prev);
struct agx_uncompiled_shader *cso = pipe_shader_from_nir(&ctx->base, gs);
prev_cso->passthrough_progs[mode] = cso;
prev_cso->passthrough_progs[mode][poly_mode][edgeflags] = cso;
return cso;
}

View file

@ -198,7 +198,7 @@ struct agx_uncompiled_shader {
uint8_t nir_sha1[20];
struct agx_uncompiled_shader_info info;
struct hash_table *variants;
struct agx_uncompiled_shader *passthrough_progs[MESA_PRIM_COUNT];
struct agx_uncompiled_shader *passthrough_progs[MESA_PRIM_COUNT][3][2];
bool has_xfb_info;
/* Whether the shader accesses indexed samplers via the bindless heap */