diff options
| author | Simon Perretta <simon.perretta@imgtec.com> | 2025-08-30 22:06:52 +0100 |
|---|---|---|
| committer | Marge Bot <marge-bot@fdo.invalid> | 2025-09-30 12:15:46 +0000 |
| commit | cb6c92150226148787a52c9ac96c12e2b7bb5f81 (patch) | |
| tree | 074e55a149b639c9216828d46ca4fc0dc784bc29 | |
| parent | 9d48088428bfe52d234319d2ec9c5b01d56edbc8 (diff) | |
pvr, pco: add multiview compiler support, advertise extension
- Pass view index to fragment shader via linked flat varying.
- Use view index instead of layer id for input attachments when required.
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37512>
| -rw-r--r-- | docs/features.txt | 2 | ||||
| -rw-r--r-- | src/imagination/pco/pco.h | 6 | ||||
| -rw-r--r-- | src/imagination/pco/pco_data.h | 3 | ||||
| -rw-r--r-- | src/imagination/pco/pco_internal.h | 3 | ||||
| -rw-r--r-- | src/imagination/pco/pco_nir.c | 22 | ||||
| -rw-r--r-- | src/imagination/pco/pco_nir_pvfio.c | 65 | ||||
| -rw-r--r-- | src/imagination/pco/pco_nir_tex.c | 17 | ||||
| -rw-r--r-- | src/imagination/pco/pco_trans_nir.c | 1 | ||||
| -rw-r--r-- | src/imagination/vulkan/pvr_device.c | 10 | ||||
| -rw-r--r-- | src/imagination/vulkan/pvr_pipeline.c | 46 |
10 files changed, 167 insertions, 8 deletions
diff --git a/docs/features.txt b/docs/features.txt index 62aa1c79078..5d778d6c1c4 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -452,7 +452,7 @@ Vulkan 1.1 -- all DONE: anv, hk, lvp, nvk, panvk/v10+, radv, tu, vn VK_KHR_maintenance1 DONE (anv, dzn, hasvk, lvp, nvk, panvk, pvr, radv, tu, v3dv, vn) VK_KHR_maintenance2 DONE (anv, dzn, hasvk, lvp, nvk, panvk, pvr, radv, tu, v3dv, vn) VK_KHR_maintenance3 DONE (anv, dzn, hasvk, lvp, nvk, panvk, pvr, radv, tu, v3dv, vn) - VK_KHR_multiview DONE (anv, dzn, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn) + VK_KHR_multiview DONE (anv, dzn, hasvk, lvp, nvk, panvk/v10+, pvr, radv, tu, v3dv, vn) VK_KHR_relaxed_block_layout DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn) VK_KHR_sampler_ycbcr_conversion DONE (anv, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn) VK_KHR_shader_draw_parameters DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, vn) diff --git a/src/imagination/pco/pco.h b/src/imagination/pco/pco.h index ed915c18c47..03e4b02103f 100644 --- a/src/imagination/pco/pco.h +++ b/src/imagination/pco/pco.h @@ -34,7 +34,11 @@ const struct spirv_to_nir_options *pco_spirv_options(void); const nir_shader_compiler_options *pco_nir_options(void); void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir); -void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer); +void pco_link_nir(pco_ctx *ctx, + nir_shader *producer, + nir_shader *consumer, + pco_data *producer_data, + pco_data *consumer_data); void pco_rev_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer); void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data); void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data); diff --git a/src/imagination/pco/pco_data.h b/src/imagination/pco/pco_data.h index 4dddec6ed53..d754f03427b 100644 --- a/src/imagination/pco/pco_data.h +++ b/src/imagination/pco/pco_data.h @@ -106,6 +106,8 @@ typedef struct _pco_fs_data { pco_range sample_locations; + gl_varying_slot view_index_slot; + struct { bool w; /** Whether the shader uses pos.w. */ bool z; /** Whether the shader uses pos.z */ @@ -224,6 +226,7 @@ typedef struct _pco_common_data { bool robust_buffer_access; bool image_2d_view_of_3d; + bool multiview; } pco_common_data; /** PCO shader data. */ diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 713946f262e..ab5a0ba4645 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -1756,6 +1756,9 @@ bool pco_legalize(pco_shader *shader); bool pco_opt_comp_only_vecs(pco_shader *shader); bool pco_nir_compute_instance_check(nir_shader *shader); bool pco_nir_link_clip_cull_vars(nir_shader *producer, nir_shader *consumer); +bool pco_nir_link_multiview(nir_shader *producer, + nir_shader *consumer, + pco_data *consumer_data); bool pco_nir_lower_algebraic(nir_shader *shader); bool pco_nir_lower_algebraic_late(nir_shader *shader); bool pco_nir_lower_atomics(nir_shader *shader, pco_data *data); diff --git a/src/imagination/pco/pco_nir.c b/src/imagination/pco/pco_nir.c index 6ee2a6848a1..9ce0eb9acec 100644 --- a/src/imagination/pco/pco_nir.c +++ b/src/imagination/pco/pco_nir.c @@ -636,15 +636,27 @@ void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir) } } +static bool can_remove_var(nir_variable *var, UNUSED void *data) +{ + return !var->data.always_active_io; +} + /** * \brief Performs linking optimizations on consecutive NIR shader stages. * * \param[in] ctx PCO compiler context. * \param[in,out] producer NIR producer shader. * \param[in,out] consumer NIR consumer shader. + * \param[in,out] producer_data Producer shader data. + * \param[in,out] consumer_data Consumer shader data. */ -void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer) +void pco_link_nir(pco_ctx *ctx, + nir_shader *producer, + nir_shader *consumer, + pco_data *producer_data, + pco_data *consumer_data) { + pco_nir_link_multiview(producer, consumer, consumer_data); pco_nir_link_clip_cull_vars(producer, consumer); nir_lower_io_array_vars_to_elements(producer, consumer); @@ -660,8 +672,12 @@ void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer) if (nir_link_opt_varyings(producer, consumer)) pco_nir_opt(ctx, consumer); - NIR_PASS(_, producer, nir_remove_dead_variables, nir_var_shader_out, NULL); - NIR_PASS(_, consumer, nir_remove_dead_variables, nir_var_shader_in, NULL); + nir_remove_dead_variables_options rdv = { + .can_remove_var = can_remove_var, + }; + + NIR_PASS(_, producer, nir_remove_dead_variables, nir_var_shader_out, &rdv); + NIR_PASS(_, consumer, nir_remove_dead_variables, nir_var_shader_in, &rdv); bool progress = nir_remove_unused_varyings(producer, consumer); nir_compact_varyings(producer, consumer, true); diff --git a/src/imagination/pco/pco_nir_pvfio.c b/src/imagination/pco/pco_nir_pvfio.c index b004261e5f0..04799be13f7 100644 --- a/src/imagination/pco/pco_nir_pvfio.c +++ b/src/imagination/pco/pco_nir_pvfio.c @@ -1549,3 +1549,68 @@ bool pco_nir_lower_interpolation(nir_shader *shader, pco_fs_data *fs) return progress; } + +static bool lower_load_view_index_fs(struct nir_builder *b, + nir_intrinsic_instr *intr, + void *cb_data) +{ + if (intr->intrinsic != nir_intrinsic_load_view_index) + return false; + + nir_variable *view_index_var = cb_data; + b->cursor = nir_before_instr(&intr->instr); + nir_def_replace(&intr->def, nir_load_var(b, view_index_var)); + nir_instr_free(&intr->instr); + + return true; +} + +bool pco_nir_link_multiview(nir_shader *producer, + nir_shader *consumer, + pco_data *consumer_data) +{ + if (producer->info.stage != MESA_SHADER_VERTEX || + consumer->info.stage != MESA_SHADER_FRAGMENT || + !consumer_data->common.multiview) { + return false; + } + + /* Find unused varying slot for the view index. */ + gl_varying_slot view_index_slot = VARYING_SLOT_VAR0; + nir_foreach_shader_out_variable (var, producer) { + view_index_slot = MAX2(view_index_slot, var->data.location + 1); + } + assert(view_index_slot < VARYING_SLOT_MAX); + consumer_data->fs.view_index_slot = view_index_slot; + + /* Create output variable in the producer. */ + nir_variable *view_index_var = nir_variable_create(producer, + nir_var_shader_out, + glsl_uint_type(), + "view_index"); + view_index_var->data.location = view_index_slot; + view_index_var->data.interpolation = INTERP_MODE_FLAT; + view_index_var->data.always_active_io = true; + + /* Store view index in the producer. */ + nir_builder b = nir_builder_at(nir_after_block( + nir_impl_last_block(nir_shader_get_entrypoint(producer)))); + nir_store_var(&b, view_index_var, nir_load_view_index(&b), 1); + + /* Create input variable in the consumer. */ + view_index_var = nir_variable_create(consumer, + nir_var_shader_in, + glsl_uint_type(), + "view_index"); + view_index_var->data.location = view_index_slot; + view_index_var->data.interpolation = INTERP_MODE_FLAT; + view_index_var->data.always_active_io = true; + + /* Lower view index loads in the consumer. */ + nir_shader_intrinsics_pass(consumer, + lower_load_view_index_fs, + nir_metadata_all, + view_index_var); + + return true; +} diff --git a/src/imagination/pco/pco_nir_tex.c b/src/imagination/pco/pco_nir_tex.c index a07d4083b8c..74aefa2c7a8 100644 --- a/src/imagination/pco/pco_nir_tex.c +++ b/src/imagination/pco/pco_nir_tex.c @@ -1226,7 +1226,22 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) frag_coords = nir_f2i32(b, frag_coords); coords = nir_iadd(b, frag_coords, coords); - nir_def *layer = nir_load_layer_id(b); /* TODO: view id for multiview? */ + nir_def *layer = nir_load_layer_id(b); + + /* Use the view index instead if we're in multiview. */ + if (data->common.multiview) { + assert(data->fs.view_index_slot >= VARYING_SLOT_VAR0 && + data->fs.view_index_slot < VARYING_SLOT_MAX); + layer = nir_load_input(b, + 1, + 32, + nir_imm_int(b, 0), + .dest_type = nir_type_uint32, + .io_semantics = (nir_io_semantics){ + .location = data->fs.view_index_slot, + .num_slots = 1, + }); + } coords = nir_pad_vector(b, coords, 3); coords = nir_vector_insert_imm(b, coords, layer, 2); diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 32b65e356dc..962ec90d2a8 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -2113,6 +2113,7 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr) case nir_intrinsic_load_base_instance: case nir_intrinsic_load_base_vertex: case nir_intrinsic_load_draw_id: + case nir_intrinsic_load_view_index: /* Compute sysvals. */ case nir_intrinsic_load_local_invocation_index: diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 82c0d5f9c5a..6b0ce3419c9 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -189,6 +189,7 @@ static void pvr_physical_device_get_supported_extensions( .KHR_maintenance1 = true, .KHR_maintenance2 = true, .KHR_maintenance3 = true, + .KHR_multiview = true, .KHR_present_id2 = PVR_USE_WSI_PLATFORM, .KHR_present_wait2 = PVR_USE_WSI_PLATFORM, .KHR_separate_depth_stencil_layouts = true, @@ -293,6 +294,11 @@ static void pvr_physical_device_get_supported_features( /* Vulkan 1.2 / VK_KHR_imageless_framebuffer */ .imagelessFramebuffer = true, + /* Vulkan 1.1 / VK_KHR_multiview */ + .multiview = true, + .multiviewGeometryShader = false, + .multiviewTessellationShader = false, + /* Vulkan 1.2 / VK_KHR_timeline_semaphore */ .timelineSemaphore = true, @@ -586,6 +592,10 @@ static bool pvr_physical_device_get_properties( .maxPerSetDescriptors = PVR_MAX_DESCRIPTORS_PER_SET, .maxMemoryAllocationSize = max_memory_alloc_size, + /* Vulkan 1.1 / VK_KHR_multiview */ + .maxMultiviewViewCount = PVR_MAX_MULTIVIEW, + .maxMultiviewInstanceIndex = (1 << 27) - 1, + /* Vulkan 1.2 / VK_KHR_driver_properties */ .driverID = VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA, .driverName = "Imagination open-source Mesa driver", diff --git a/src/imagination/vulkan/pvr_pipeline.c b/src/imagination/vulkan/pvr_pipeline.c index 49673af035b..5fdc2d07e3a 100644 --- a/src/imagination/vulkan/pvr_pipeline.c +++ b/src/imagination/vulkan/pvr_pipeline.c @@ -400,6 +400,11 @@ static VkResult pvr_pds_vertex_attrib_programs_create_and_upload( input.draw_index_register = sys_vals[SYSTEM_VALUE_DRAW_ID].start; } + if (sys_vals[SYSTEM_VALUE_VIEW_INDEX].count > 0) { + input.flags |= PVR_PDS_VERTEX_FLAGS_VIEW_INDEX_REQUIRED; + input.view_index_register = sys_vals[SYSTEM_VALUE_VIEW_INDEX].start; + } + pvr_pds_setup_doutu(&input.usc_task_control, 0, usc_temp_count, @@ -930,6 +935,10 @@ static void pvr_pipeline_finish(struct pvr_device *device, vk_object_base_finish(&pipeline->base); } +static void pvr_early_init_shader_data(pco_data *data, + nir_shader *nir, + const void *pCreateInfo); + static void pvr_preprocess_shader_data(pco_data *data, nir_shader *nir, @@ -987,6 +996,7 @@ static VkResult pvr_compute_pipeline_compile( if (result != VK_SUCCESS) goto err_free_build_context; + pvr_early_init_shader_data(&shader_data, nir, pCreateInfo); pco_preprocess_nir(pco_ctx, nir); pvr_preprocess_shader_data(&shader_data, nir, pCreateInfo, layout, NULL); pco_lower_nir(pco_ctx, nir, &shader_data); @@ -1651,7 +1661,7 @@ static void pvr_alloc_vs_sysvals(pco_data *data, nir_shader *nir) gl_system_value sys_vals[] = { SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_INSTANCE_ID, SYSTEM_VALUE_BASE_INSTANCE, SYSTEM_VALUE_BASE_VERTEX, - SYSTEM_VALUE_DRAW_ID, + SYSTEM_VALUE_DRAW_ID, SYSTEM_VALUE_VIEW_INDEX, }; for (unsigned u = 0; u < ARRAY_SIZE(sys_vals); ++u) { @@ -2570,6 +2580,29 @@ static void pvr_postprocess_shader_data(pco_data *data, /* TODO: common things, like large constants being put into shareds. */ } +static void pvr_early_init_shader_data(pco_data *data, + nir_shader *nir, + const void *pCreateInfo) +{ + const VkGraphicsPipelineCreateInfo *pGraphicsCreateInfo = pCreateInfo; + + switch (nir->info.stage) { + case MESA_SHADER_VERTEX: + case MESA_SHADER_FRAGMENT: { + VK_FROM_HANDLE(pvr_render_pass, pass, pGraphicsCreateInfo->renderPass); + data->common.multiview = pass->multiview_enabled; + + break; + } + + case MESA_SHADER_COMPUTE: + break; + + default: + UNREACHABLE("Unsupported stage."); + } +} + /* Compiles and uploads shaders and PDS programs. */ static VkResult pvr_graphics_pipeline_compile(struct pvr_device *const device, @@ -2594,6 +2627,7 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, nir_shader *producer = NULL; nir_shader *consumer = NULL; pco_data shader_data[MESA_SHADER_STAGES] = { 0 }; + pco_data *producer_data = NULL; nir_shader *nir_shaders[MESA_SHADER_STAGES] = { 0 }; pco_shader *pco_shaders[MESA_SHADER_STAGES] = { 0 }; pco_shader **vs = &pco_shaders[MESA_SHADER_VERTEX]; @@ -2621,6 +2655,9 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, if (result != VK_SUCCESS) goto err_free_build_context; + pvr_early_init_shader_data(&shader_data[stage], + nir_shaders[stage], + pCreateInfo); pco_preprocess_nir(pco_ctx, nir_shaders[stage]); } @@ -2629,9 +2666,14 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, continue; if (producer) - pco_link_nir(pco_ctx, producer, nir_shaders[stage]); + pco_link_nir(pco_ctx, + producer, + nir_shaders[stage], + producer_data, + &shader_data[stage]); producer = nir_shaders[stage]; + producer_data = &shader_data[stage]; } for (mesa_shader_stage stage = MESA_SHADER_STAGES; stage-- > 0;) { |