From 64ad5a1f7b3be382a9b6297a4a035dcaa1b36740 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Fri, 21 Aug 2020 13:45:16 +0200 Subject: [PATCH] ir3, tu: Link per-view position correctly Part-of: --- src/freedreno/ir3/ir3_compiler_nir.c | 13 ++++++++++++- src/freedreno/ir3/ir3_shader.h | 1 + src/freedreno/vulkan/tu_pipeline.c | 27 ++++++++++++++++++++------- src/freedreno/vulkan/tu_private.h | 1 + 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 1fd4bf2b42a..b72f5bbcbe8 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -3106,7 +3106,16 @@ setup_output(struct ir3_context *ctx, nir_intrinsic_instr *intr) unsigned n = nir_intrinsic_base(intr) + offset; unsigned frac = nir_intrinsic_component(intr); unsigned ncomp = nir_intrinsic_src_components(intr, 0); - unsigned slot = io.location + offset; + + /* For per-view variables, each user-facing slot corresponds to multiple + * views, each with a corresponding driver_location, and the offset is for + * the driver_location. To properly figure out of the slot, we'd need to + * plumb through the number of views. However, for now we only use + * per-view with gl_Position, so we assume that the variable is not an + * array or matrix (so there are no indirect accesses to the variable + * itself) and the indirect offset corresponds to the view. + */ + unsigned slot = io.location + (io.per_view ? 0 : offset); if (ctx->so->type == MESA_SHADER_FRAGMENT) { switch (slot) { @@ -3172,6 +3181,8 @@ setup_output(struct ir3_context *ctx, nir_intrinsic_instr *intr) compile_assert(ctx, so->outputs_count < ARRAY_SIZE(so->outputs)); so->outputs[n].slot = slot; + if (io.per_view) + so->outputs[n].view = offset; for (int i = 0; i < ncomp; i++) { unsigned idx = (n * 4) + i + frac; diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index 5b0ce85918b..39870066956 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -562,6 +562,7 @@ struct ir3_shader_variant { struct { uint8_t slot; uint8_t regid; + uint8_t view; bool half : 1; } outputs[32 + 2]; /* +POSITION +PSIZE */ bool writes_pos, writes_smask, writes_psize, writes_stencilref; diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 5b6a41e6e6e..9f11c810086 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -825,8 +825,6 @@ tu6_emit_vpc(struct tu_cs *cs, tu_cs_emit(cs, ~linkage.varmask[3]); /* a6xx finds position/pointsize at the end */ - const uint32_t position_regid = - ir3_find_output_regid(last_shader, VARYING_SLOT_POS); const uint32_t pointsize_regid = ir3_find_output_regid(last_shader, VARYING_SLOT_PSIZ); const uint32_t layer_regid = @@ -839,18 +837,31 @@ tu6_emit_vpc(struct tu_cs *cs, ir3_find_output_regid(gs, VARYING_SLOT_GS_VERTEX_FLAGS_IR3) : 0; uint32_t pointsize_loc = 0xff, position_loc = 0xff, layer_loc = 0xff, view_loc = 0xff; + if (layer_regid != regid(63, 0)) { layer_loc = linkage.max_loc; ir3_link_add(&linkage, layer_regid, 0x1, linkage.max_loc); } + if (view_regid != regid(63, 0)) { view_loc = linkage.max_loc; ir3_link_add(&linkage, view_regid, 0x1, linkage.max_loc); } - if (position_regid != regid(63, 0)) { - position_loc = linkage.max_loc; - ir3_link_add(&linkage, position_regid, 0xf, linkage.max_loc); + + unsigned extra_pos = 0; + + for (unsigned i = 0; i < last_shader->outputs_count; i++) { + if (last_shader->outputs[i].slot != VARYING_SLOT_POS) + continue; + + if (position_loc == 0xff) + position_loc = linkage.max_loc; + + ir3_link_add(&linkage, last_shader->outputs[i].regid, + 0xf, position_loc + 4 * last_shader->outputs[i].view); + extra_pos = MAX2(extra_pos, last_shader->outputs[i].view); } + if (pointsize_regid != regid(63, 0)) { pointsize_loc = linkage.max_loc; ir3_link_add(&linkage, pointsize_regid, 0x1, linkage.max_loc); @@ -889,7 +900,8 @@ tu6_emit_vpc(struct tu_cs *cs, tu_cs_emit_pkt4(cs, cfg->reg_vpc_xs_pack, 1); tu_cs_emit(cs, A6XX_VPC_VS_PACK_POSITIONLOC(position_loc) | A6XX_VPC_VS_PACK_PSIZELOC(pointsize_loc) | - A6XX_VPC_VS_PACK_STRIDE_IN_VPC(linkage.max_loc)); + A6XX_VPC_VS_PACK_STRIDE_IN_VPC(linkage.max_loc) | + A6XX_VPC_VS_PACK_EXTRAPOS(extra_pos)); tu_cs_emit_pkt4(cs, cfg->reg_vpc_xs_clip_cntl, 1); tu_cs_emit(cs, 0xffff00); @@ -1397,6 +1409,7 @@ tu6_emit_program(struct tu_cs *cs, gl_shader_stage stage = MESA_SHADER_VERTEX; uint32_t cps_per_patch = builder->create_info->pTessellationState ? builder->create_info->pTessellationState->patchControlPoints : 0; + bool multi_pos_output = builder->shaders[MESA_SHADER_VERTEX]->multi_pos_output; STATIC_ASSERT(MESA_SHADER_VERTEX == 0); @@ -1430,7 +1443,7 @@ tu6_emit_program(struct tu_cs *cs, uint32_t multiview_cntl = builder->multiview_mask ? A6XX_PC_MULTIVIEW_CNTL_ENABLE | A6XX_PC_MULTIVIEW_CNTL_VIEWS(multiview_views) | - A6XX_PC_MULTIVIEW_CNTL_DISABLEMULTIPOS /* TODO multi-pos output */ + COND(!multi_pos_output, A6XX_PC_MULTIVIEW_CNTL_DISABLEMULTIPOS) : 0; /* Copy what the blob does here. This will emit an extra 0x3f diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index f018ed5abc7..37e75fc1eeb 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1027,6 +1027,7 @@ struct tu_shader struct tu_push_constant_range push_consts; uint8_t active_desc_sets; + bool multi_pos_output; }; bool