diff --git a/src/panfrost/compiler/bifrost_compile.c b/src/panfrost/compiler/bifrost_compile.c index 96d4353734b..1cf3b2c35f8 100644 --- a/src/panfrost/compiler/bifrost_compile.c +++ b/src/panfrost/compiler/bifrost_compile.c @@ -5856,7 +5856,7 @@ bifrost_compile_shader_nir(nir_shader *nir, info->tls_size = nir->scratch_size; info->vs.idvs = bi_should_idvs(nir, inputs); - pan_nir_collect_varyings(nir, info); + pan_nir_collect_varyings(nir, info, PAN_MEDIUMP_VARY_32BIT); if (info->vs.idvs) { bi_compile_variant(nir, inputs, binary, info, BI_IDVS_POSITION); diff --git a/src/panfrost/midgard/midgard_compile.c b/src/panfrost/midgard/midgard_compile.c index 45807719d89..52250f3e097 100644 --- a/src/panfrost/midgard/midgard_compile.c +++ b/src/panfrost/midgard/midgard_compile.c @@ -2984,7 +2984,7 @@ midgard_compile_shader_nir(nir_shader *nir, /* Collect varyings after lowering I/O */ info->quirk_no_auto32 = (ctx->quirks & MIDGARD_NO_AUTO32); - pan_nir_collect_varyings(nir, info); + pan_nir_collect_varyings(nir, info, PAN_MEDIUMP_VARY_SMOOTH_16BIT); /* Optimisation passes */ optimise_nir(nir, ctx->quirks, inputs->is_blend); diff --git a/src/panfrost/util/pan_collect_varyings.c b/src/panfrost/util/pan_collect_varyings.c index ea6c74f534f..1987d85d713 100644 --- a/src/panfrost/util/pan_collect_varyings.c +++ b/src/panfrost/util/pan_collect_varyings.c @@ -69,6 +69,7 @@ struct slot_info { }; struct walk_varyings_data { + enum pan_mediump_vary mediump; struct pan_shader_info *info; struct slot_info *slots; }; @@ -128,19 +129,20 @@ walk_varyings(UNUSED nir_builder *b, nir_instr *instr, void *data) bool auto32 = !info->quirk_no_auto32; nir_alu_type type = (flat && auto32) ? nir_type_uint : nir_type_float; - /* Demote interpolated float varyings to fp16 where possible. We do not - * demote flat varyings, including integer varyings, due to various - * issues with the Midgard hardware behaviour and TGSI shaders, as well - * as having no demonstrable benefit in practice. - */ - if (type == nir_type_float && sem.medium_precision) - size = 16; - else { - /* We never emit 16-bit user varyings except for lowered mediump floats */ - if (sem.location >= VARYING_SLOT_VAR0) - assert(size == 32); + if (sem.medium_precision) { + /* Demote interpolated float varyings to fp16 where possible. We do not + * demote flat varyings, including integer varyings, due to various + * issues with the Midgard hardware behaviour and TGSI shaders, as well + * as having no demonstrable benefit in practice. + */ + if (wv_data->mediump == PAN_MEDIUMP_VARY_SMOOTH_16BIT) + size = type == nir_type_float ? 16 : 32; + + if (wv_data->mediump == PAN_MEDIUMP_VARY_32BIT) + size = 32; } + assert(size == 32 || size == 16); type |= size; /* Count currently contains the number of components accessed by this @@ -206,14 +208,15 @@ pan_nir_collect_noperspective_varyings_fs(nir_shader *s) } void -pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info) +pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info, + enum pan_mediump_vary mediump) { if (s->info.stage != MESA_SHADER_VERTEX && s->info.stage != MESA_SHADER_FRAGMENT) return; struct slot_info slots[64] = {0}; - struct walk_varyings_data wv_data = {info, slots}; + struct walk_varyings_data wv_data = {mediump, info, slots}; nir_shader_instructions_pass(s, walk_varyings, nir_metadata_all, &wv_data); struct pan_shader_varying *varyings = (s->info.stage == MESA_SHADER_VERTEX) diff --git a/src/panfrost/util/pan_ir.h b/src/panfrost/util/pan_ir.h index 32ce7515797..0459c45af20 100644 --- a/src/panfrost/util/pan_ir.h +++ b/src/panfrost/util/pan_ir.h @@ -393,6 +393,15 @@ void pan_print_alu_type(nir_alu_type t, FILE *fp); #define PAN_WRITEOUT_S 4 #define PAN_WRITEOUT_2 8 +/* Specify the mediump lowering behavior for pan_nir_collect_varyings */ +enum pan_mediump_vary { + /* Always assign a 32-bit format to mediump varyings */ + PAN_MEDIUMP_VARY_32BIT, + /* Assign a 16-bit format to varyings with smooth interpolation, and a + * 32-bit format to varyings with flat interpolation */ + PAN_MEDIUMP_VARY_SMOOTH_16BIT, +}; + bool pan_nir_lower_zs_store(nir_shader *nir); bool pan_nir_lower_store_component(nir_shader *shader); @@ -413,7 +422,8 @@ bool pan_lower_xfb(nir_shader *nir); bool pan_lower_image_index(nir_shader *shader, unsigned vs_img_attrib_offset); uint32_t pan_nir_collect_noperspective_varyings_fs(nir_shader *s); -void pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info); +void pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info, + enum pan_mediump_vary mediump); /* * Helper returning the subgroup size. Generally, this is equal to the number of diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index 022857ae8b6..67429ed74d0 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -197,31 +197,11 @@ emit_varying_descs(const struct panvk_cmd_buffer *cmdbuf, if (var->location < VARYING_SLOT_VAR0) continue; - /* We currently always write out F32 in the vertex shaders, so the format - * needs to reflect this. */ - enum pipe_format f = var->format; - switch (f) { - case PIPE_FORMAT_R16_FLOAT: - f = PIPE_FORMAT_R32_FLOAT; - break; - case PIPE_FORMAT_R16G16_FLOAT: - f = PIPE_FORMAT_R32G32_FLOAT; - break; - case PIPE_FORMAT_R16G16B16_FLOAT: - f = PIPE_FORMAT_R32G32B32_FLOAT; - break; - case PIPE_FORMAT_R16G16B16A16_FLOAT: - f = PIPE_FORMAT_R32G32B32A32_FLOAT; - break; - default: - break; - } - uint32_t loc = var->location - VARYING_SLOT_VAR0; pan_pack(&descs[i], ATTRIBUTE, cfg) { cfg.attribute_type = MALI_ATTRIBUTE_TYPE_VERTEX_PACKET; cfg.offset_enable = false; - cfg.format = GENX(panfrost_format_from_pipe_format)(f)->hw; + cfg.format = GENX(panfrost_format_from_pipe_format)(var->format)->hw; cfg.table = 61; cfg.frequency = MALI_ATTRIBUTE_FREQUENCY_VERTEX; cfg.offset = 1024 + (loc * 16);