diff --git a/src/freedreno/vulkan/tu_nir_lower_multiview.cc b/src/freedreno/vulkan/tu_nir_lower_multiview.cc index c5882805bbe..78ca0787763 100644 --- a/src/freedreno/vulkan/tu_nir_lower_multiview.cc +++ b/src/freedreno/vulkan/tu_nir_lower_multiview.cc @@ -17,7 +17,8 @@ * gl_Position = ((1ull << gl_ViewIndex) & view_mask) ? gl_Position : vec4(0.); * * Scan backwards until we find the gl_Position write (there should only be - * one). + * one). This also needs to happen with multi-position, which doesn't respect + * the view mask. */ static bool lower_multiview_mask(nir_shader *nir, uint32_t *mask) @@ -70,15 +71,18 @@ lower_multiview_mask(nir_shader *nir, uint32_t *mask) } bool -tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev) +tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev, + bool last_stage) { bool progress = false; nir_lower_multiview_options options = { .view_mask = mask, - .allowed_per_view_outputs = VARYING_BIT_POS + .allowed_per_view_outputs = + last_stage ? VARYING_BIT_POS : ~0ull, }; - if (!dev->physical_device->info->props.supports_multiview_mask) + if (!dev->physical_device->info->props.supports_multiview_mask && + last_stage) NIR_PASS(progress, nir, lower_multiview_mask, &options.view_mask); unsigned num_views = util_logbase2(mask) + 1; @@ -95,10 +99,16 @@ tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev) */ nir_assign_io_var_locations(nir, nir_var_shader_out); + if (!last_stage) { + /* We will store outputs per-view and loop over all active views in the + * shader. + */ + NIR_PASS(progress, nir, nir_lower_multiview, options); + /* In addition to the generic checks done by NIR, check that we don't * overflow VPC with the extra copies of gl_Position. */ - if (!TU_DEBUG(NOMULTIPOS) && + } else if (!TU_DEBUG(NOMULTIPOS) && num_views <= max_views_for_multipos && nir->num_outputs + (num_views - 1) <= 32 && nir_can_lower_multiview(nir, options)) { /* It appears that the multiview mask is ignored when multi-position diff --git a/src/freedreno/vulkan/tu_pipeline.cc b/src/freedreno/vulkan/tu_pipeline.cc index df4f18085bb..bf303389676 100644 --- a/src/freedreno/vulkan/tu_pipeline.cc +++ b/src/freedreno/vulkan/tu_pipeline.cc @@ -1304,7 +1304,7 @@ tu6_emit_geom_tess_consts(struct tu_cs *cs, if (gs && !hs) { tu6_emit_vs_params(cs, ir3_const_state(vs), vs->constlen, - vs->output_size, gs->gs.vertices_in); + vs->output_size, gs->gs.vertices_in * vs->view_count); } if (hs) { @@ -1312,9 +1312,9 @@ tu6_emit_geom_tess_consts(struct tu_cs *cs, tu_get_tess_iova(dev, &tess_factor_iova, &tess_param_iova); uint32_t ds_params[8] = { - gs ? ds->output_size * gs->gs.vertices_in * 4 : 0, /* ds primitive stride */ - ds->output_size * 4, /* ds vertex stride */ - hs->output_size, /* hs vertex stride (dwords) */ + gs ? ds->output_size * ds->view_count * gs->gs.vertices_in * 4 : 0, /* ds primitive stride */ + ds->output_size * 4, /* ds vertex stride */ + hs->output_size, /* hs vertex stride (dwords) */ hs->tess.tcs_vertices_out, tess_param_iova, tess_param_iova >> 32, @@ -1330,8 +1330,8 @@ tu6_emit_geom_tess_consts(struct tu_cs *cs, if (gs) { const struct ir3_shader_variant *prev = ds ? ds : vs; uint32_t gs_params[4] = { - prev->output_size * gs->gs.vertices_in * 4, /* gs primitive stride */ - prev->output_size * 4, /* gs vertex stride */ + prev->output_size * prev->view_count * gs->gs.vertices_in * 4, /* gs primitive stride */ + prev->output_size * 4, /* gs vertex stride */ 0, 0, }; @@ -1887,8 +1887,12 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, if (builder->state & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { - keys[MESA_SHADER_VERTEX].multiview_mask = - builder->graphics_state.mv->view_mask; + for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { + if (nir[i] || stage_infos[i]) { + keys[i].multiview_mask = + builder->graphics_state.mv->view_mask; + } + } mesa_shader_stage last_pre_rast_stage = MESA_SHADER_VERTEX; for (int i = MESA_SHADER_GEOMETRY; i >= MESA_SHADER_VERTEX; i--) { @@ -4972,7 +4976,7 @@ tu_compute_pipeline_create(VkDevice device, nir_shader_as_str(nir, pipeline->base.executables_mem_ctx) : NULL; struct tu_shader_info info = {}; - tu_lower_nir(dev, nir, &key, &info); + tu_lower_nir(dev, nir, &key, &ir3_key, &info); result = tu_shader_create(dev, &shader, nir, &key, &info, &ir3_key, pipeline_blake3, sizeof(pipeline_blake3), layout, executable_info); diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc index 5d80753dee4..721d4a7c06a 100644 --- a/src/freedreno/vulkan/tu_shader.cc +++ b/src/freedreno/vulkan/tu_shader.cc @@ -2934,6 +2934,7 @@ void tu_lower_nir(struct tu_device *dev, nir_shader *nir, const struct tu_shader_key *key, + const struct ir3_shader_key *ir3_key, struct tu_shader_info *info) { const nir_opt_access_options access_options = { @@ -2999,9 +3000,13 @@ tu_lower_nir(struct tu_device *dev, */ ir3_nir_lower_io_vars_to_temporaries(nir); - if (nir->info.stage == MESA_SHADER_VERTEX && key->multiview_mask) { - tu_nir_lower_multiview(nir, key->multiview_mask, dev); - } + bool is_last_stage = + (nir->info.stage == MESA_SHADER_VERTEX && !ir3_key->has_gs && !ir3_key->tessellation); + + if (nir->info.stage == MESA_SHADER_VERTEX && key->multiview_mask) + tu_nir_lower_multiview(nir, key->multiview_mask, dev, is_last_stage); + if (nir->info.stage == MESA_SHADER_GEOMETRY) + nir->info.view_mask = key->multiview_mask; if (!key->multiview_mask) tu_nir_lower_view_to_zero(nir); @@ -3347,7 +3352,7 @@ tu_compile_shaders(struct tu_device *device, int64_t stage_start = os_time_get_nano(); - tu_lower_nir(device, nir[stage], &keys[stage], &info[stage]); + tu_lower_nir(device, nir[stage], &keys[stage], &ir3_key, &info[stage]); stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } diff --git a/src/freedreno/vulkan/tu_shader.h b/src/freedreno/vulkan/tu_shader.h index 3ae62052002..d67785ead49 100644 --- a/src/freedreno/vulkan/tu_shader.h +++ b/src/freedreno/vulkan/tu_shader.h @@ -146,7 +146,8 @@ void tu_destroy_softfloat(struct tu_device *device); bool -tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev); +tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev, + bool last_stage); bool tu_nir_lower_ray_queries(nir_shader *nir); @@ -202,6 +203,7 @@ void tu_lower_nir(struct tu_device *dev, nir_shader *nir, const struct tu_shader_key *key, + const struct ir3_shader_key *ir3_key, struct tu_shader_info *info); VkResult