From 1fc846dce396e2e0d1be23568e22ae2510df71bd Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Tue, 14 May 2024 10:24:07 +0200 Subject: [PATCH] v3d: support 2712D0 2710D0 has V3D 7.1.10 which included draw index and base vertex in the shader state record packet, shuffling the locations of most of its fields. Handle this at run time by emitting the appropriate packet based on the V3D version since our current versoning framework doesn't support changes based on revision number alone. Part-of: --- src/broadcom/common/v3d_device_info.h | 6 + src/gallium/drivers/v3d/v3dx_draw.c | 354 +++++++++++++++++--------- 2 files changed, 233 insertions(+), 127 deletions(-) diff --git a/src/broadcom/common/v3d_device_info.h b/src/broadcom/common/v3d_device_info.h index 8dfc7858727..0df25e8dcce 100644 --- a/src/broadcom/common/v3d_device_info.h +++ b/src/broadcom/common/v3d_device_info.h @@ -52,4 +52,10 @@ typedef int (*v3d_ioctl_fun)(int fd, unsigned long request, void *arg); bool v3d_get_device_info(int fd, struct v3d_device_info* devinfo, v3d_ioctl_fun fun); +static inline bool +v3d_device_has_draw_index(struct v3d_device_info *devinfo) +{ + return devinfo->ver > 71 || (devinfo->ver == 71 && devinfo->rev >= 10); +} + #endif diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 6bcb5818fb4..754bd54f0b0 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -471,6 +471,230 @@ v3d_emit_tes_gs_shader_params(struct v3d_job *job, } } +static void +emit_shader_state_record(struct v3d_context *v3d, + struct v3d_job *job, + const struct pipe_draw_info *info, + struct v3d_vertex_stateobj *vtx, + struct v3d_cl_reloc cs_uniforms, + struct v3d_cl_reloc vs_uniforms, + struct v3d_cl_reloc fs_uniforms, + struct vpm_config *vpm_cfg_bin, + struct vpm_config *vpm_cfg) +{ +#if V3D_VERSION >= 71 + /* 2712D0 (V3D 7.1.10) has included draw index and base vertex, + * shuffling all the fields in the packet. Since the versioning + * framework doesn't handle revision numbers, the XML has a + * different shader state record packet including the new fields + * and we decide at run time which packet we need to emit. + */ + if (v3d_device_has_draw_index(&v3d->screen->devinfo)) { + cl_emit(&job->indirect, GL_SHADER_STATE_RECORD_DRAW_INDEX, shader) { + shader.enable_clipping = true; + shader.point_size_in_shaded_vertex_data = + (info->mode == MESA_PRIM_POINTS && + v3d->rasterizer->base.point_size_per_vertex); + shader.fragment_shader_does_z_writes = + v3d->prog.fs->prog_data.fs->writes_z; + shader.turn_off_early_z_test = + v3d->prog.fs->prog_data.fs->disable_ez; + shader.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 = + v3d->prog.fs->prog_data.fs->uses_center_w; + shader.any_shader_reads_hardware_written_primitive_id = + (v3d->prog.gs && v3d->prog.gs->prog_data.gs->uses_pid) || + v3d->prog.fs->prog_data.fs->uses_pid; + shader.insert_primitive_id_as_first_varying_to_fragment_shader = + !v3d->prog.gs && v3d->prog.fs->prog_data.fs->uses_pid; + shader.do_scoreboard_wait_on_first_thread_switch = + v3d->prog.fs->prog_data.fs->lock_scoreboard_on_first_thrsw; + shader.disable_implicit_point_line_varyings = + !v3d->prog.fs->prog_data.fs->uses_implicit_point_line_varyings; + shader.number_of_varyings_in_fragment_shader = + v3d->prog.fs->prog_data.fs->num_inputs; + shader.coordinate_shader_code_address = + cl_address(v3d_resource(v3d->prog.cs->resource)->bo, + v3d->prog.cs->offset); + shader.vertex_shader_code_address = + cl_address(v3d_resource(v3d->prog.vs->resource)->bo, + v3d->prog.vs->offset); + shader.fragment_shader_code_address = + cl_address(v3d_resource(v3d->prog.fs->resource)->bo, + v3d->prog.fs->offset); + shader.coordinate_shader_input_vpm_segment_size = + v3d->prog.cs->prog_data.vs->vpm_input_size; + shader.vertex_shader_input_vpm_segment_size = + v3d->prog.vs->prog_data.vs->vpm_input_size; + shader.coordinate_shader_output_vpm_segment_size = + v3d->prog.cs->prog_data.vs->vpm_output_size; + shader.vertex_shader_output_vpm_segment_size = + v3d->prog.vs->prog_data.vs->vpm_output_size; + shader.coordinate_shader_uniforms_address = cs_uniforms; + shader.vertex_shader_uniforms_address = vs_uniforms; + shader.fragment_shader_uniforms_address = fs_uniforms; + shader.min_coord_shader_input_segments_required_in_play = + vpm_cfg_bin->As; + shader.min_vertex_shader_input_segments_required_in_play = + vpm_cfg->As; + shader.min_coord_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = + vpm_cfg_bin->Ve; + shader.min_vertex_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = + vpm_cfg->Ve; + shader.coordinate_shader_4_way_threadable = + v3d->prog.cs->prog_data.vs->base.threads == 4; + shader.vertex_shader_4_way_threadable = + v3d->prog.vs->prog_data.vs->base.threads == 4; + shader.fragment_shader_4_way_threadable = + v3d->prog.fs->prog_data.fs->base.threads == 4; + shader.coordinate_shader_start_in_final_thread_section = + v3d->prog.cs->prog_data.vs->base.single_seg; + shader.vertex_shader_start_in_final_thread_section = + v3d->prog.vs->prog_data.vs->base.single_seg; + shader.fragment_shader_start_in_final_thread_section = + v3d->prog.fs->prog_data.fs->base.single_seg; + shader.vertex_id_read_by_coordinate_shader = + v3d->prog.cs->prog_data.vs->uses_vid; + shader.instance_id_read_by_coordinate_shader = + v3d->prog.cs->prog_data.vs->uses_iid; + shader.vertex_id_read_by_vertex_shader = + v3d->prog.vs->prog_data.vs->uses_vid; + shader.instance_id_read_by_vertex_shader = + v3d->prog.vs->prog_data.vs->uses_iid; + } + return; + } +#endif + + assert(!v3d_device_has_draw_index(&v3d->screen->devinfo)); + cl_emit(&job->indirect, GL_SHADER_STATE_RECORD, shader) { + shader.enable_clipping = true; + /* V3D_DIRTY_PRIM_MODE | V3D_DIRTY_RASTERIZER */ + shader.point_size_in_shaded_vertex_data = + (info->mode == MESA_PRIM_POINTS && + v3d->rasterizer->base.point_size_per_vertex); + + /* Must be set if the shader modifies Z, discards, or modifies + * the sample mask. For any of these cases, the fragment + * shader needs to write the Z value (even just discards). + */ + shader.fragment_shader_does_z_writes = + v3d->prog.fs->prog_data.fs->writes_z; + + /* Set if the EZ test must be disabled (due to shader side + * effects and the early_z flag not being present in the + * shader). + */ + shader.turn_off_early_z_test = + v3d->prog.fs->prog_data.fs->disable_ez; + + shader.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 = + v3d->prog.fs->prog_data.fs->uses_center_w; + + shader.any_shader_reads_hardware_written_primitive_id = + (v3d->prog.gs && v3d->prog.gs->prog_data.gs->uses_pid) || + v3d->prog.fs->prog_data.fs->uses_pid; + shader.insert_primitive_id_as_first_varying_to_fragment_shader = + !v3d->prog.gs && v3d->prog.fs->prog_data.fs->uses_pid; + + shader.do_scoreboard_wait_on_first_thread_switch = + v3d->prog.fs->prog_data.fs->lock_scoreboard_on_first_thrsw; + shader.disable_implicit_point_line_varyings = + !v3d->prog.fs->prog_data.fs->uses_implicit_point_line_varyings; + + shader.number_of_varyings_in_fragment_shader = + v3d->prog.fs->prog_data.fs->num_inputs; + + shader.coordinate_shader_code_address = + cl_address(v3d_resource(v3d->prog.cs->resource)->bo, + v3d->prog.cs->offset); + shader.vertex_shader_code_address = + cl_address(v3d_resource(v3d->prog.vs->resource)->bo, + v3d->prog.vs->offset); + shader.fragment_shader_code_address = + cl_address(v3d_resource(v3d->prog.fs->resource)->bo, + v3d->prog.fs->offset); + +#if V3D_VERSION == 42 + shader.coordinate_shader_propagate_nans = true; + shader.vertex_shader_propagate_nans = true; + shader.fragment_shader_propagate_nans = true; + + /* XXX: Use combined input/output size flag in the common + * case. + */ + shader.coordinate_shader_has_separate_input_and_output_vpm_blocks = + v3d->prog.cs->prog_data.vs->separate_segments; + shader.vertex_shader_has_separate_input_and_output_vpm_blocks = + v3d->prog.vs->prog_data.vs->separate_segments; + shader.coordinate_shader_input_vpm_segment_size = + v3d->prog.cs->prog_data.vs->separate_segments ? + v3d->prog.cs->prog_data.vs->vpm_input_size : 1; + shader.vertex_shader_input_vpm_segment_size = + v3d->prog.vs->prog_data.vs->separate_segments ? + v3d->prog.vs->prog_data.vs->vpm_input_size : 1; +#endif + /* On V3D 7.1 there isn't a specific flag to set if we are using + * shared/separate segments or not. We just set the value of + * vpm_input_size to 0, and set output to the max needed. That should be + * already properly set on prog_data_vs_bin + */ +#if V3D_VERSION == 71 + shader.coordinate_shader_input_vpm_segment_size = + v3d->prog.cs->prog_data.vs->vpm_input_size; + shader.vertex_shader_input_vpm_segment_size = + v3d->prog.vs->prog_data.vs->vpm_input_size; +#endif + + shader.coordinate_shader_output_vpm_segment_size = + v3d->prog.cs->prog_data.vs->vpm_output_size; + shader.vertex_shader_output_vpm_segment_size = + v3d->prog.vs->prog_data.vs->vpm_output_size; + + shader.coordinate_shader_uniforms_address = cs_uniforms; + shader.vertex_shader_uniforms_address = vs_uniforms; + shader.fragment_shader_uniforms_address = fs_uniforms; + + shader.min_coord_shader_input_segments_required_in_play = + vpm_cfg_bin->As; + shader.min_vertex_shader_input_segments_required_in_play = + vpm_cfg->As; + + shader.min_coord_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = + vpm_cfg_bin->Ve; + shader.min_vertex_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = + vpm_cfg->Ve; + + shader.coordinate_shader_4_way_threadable = + v3d->prog.cs->prog_data.vs->base.threads == 4; + shader.vertex_shader_4_way_threadable = + v3d->prog.vs->prog_data.vs->base.threads == 4; + shader.fragment_shader_4_way_threadable = + v3d->prog.fs->prog_data.fs->base.threads == 4; + + shader.coordinate_shader_start_in_final_thread_section = + v3d->prog.cs->prog_data.vs->base.single_seg; + shader.vertex_shader_start_in_final_thread_section = + v3d->prog.vs->prog_data.vs->base.single_seg; + shader.fragment_shader_start_in_final_thread_section = + v3d->prog.fs->prog_data.fs->base.single_seg; + + shader.vertex_id_read_by_coordinate_shader = + v3d->prog.cs->prog_data.vs->uses_vid; + shader.instance_id_read_by_coordinate_shader = + v3d->prog.cs->prog_data.vs->uses_iid; + shader.vertex_id_read_by_vertex_shader = + v3d->prog.vs->prog_data.vs->uses_vid; + shader.instance_id_read_by_vertex_shader = + v3d->prog.vs->prog_data.vs->uses_iid; + +#if V3D_VERSION == 42 + shader.address_of_default_attribute_values = + cl_address(v3d_resource(vtx->defaults)->bo, + vtx->defaults_offset); +#endif + } +} + static void v3d_emit_gl_shader_state(struct v3d_context *v3d, const struct pipe_draw_info *info) @@ -580,133 +804,9 @@ v3d_emit_gl_shader_state(struct v3d_context *v3d, vpm_cfg.Gv); } - cl_emit(&job->indirect, GL_SHADER_STATE_RECORD, shader) { - shader.enable_clipping = true; - /* V3D_DIRTY_PRIM_MODE | V3D_DIRTY_RASTERIZER */ - shader.point_size_in_shaded_vertex_data = - (info->mode == MESA_PRIM_POINTS && - v3d->rasterizer->base.point_size_per_vertex); - - /* Must be set if the shader modifies Z, discards, or modifies - * the sample mask. For any of these cases, the fragment - * shader needs to write the Z value (even just discards). - */ - shader.fragment_shader_does_z_writes = - v3d->prog.fs->prog_data.fs->writes_z; - - /* Set if the EZ test must be disabled (due to shader side - * effects and the early_z flag not being present in the - * shader). - */ - shader.turn_off_early_z_test = - v3d->prog.fs->prog_data.fs->disable_ez; - - shader.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 = - v3d->prog.fs->prog_data.fs->uses_center_w; - - shader.any_shader_reads_hardware_written_primitive_id = - (v3d->prog.gs && v3d->prog.gs->prog_data.gs->uses_pid) || - v3d->prog.fs->prog_data.fs->uses_pid; - shader.insert_primitive_id_as_first_varying_to_fragment_shader = - !v3d->prog.gs && v3d->prog.fs->prog_data.fs->uses_pid; - - shader.do_scoreboard_wait_on_first_thread_switch = - v3d->prog.fs->prog_data.fs->lock_scoreboard_on_first_thrsw; - shader.disable_implicit_point_line_varyings = - !v3d->prog.fs->prog_data.fs->uses_implicit_point_line_varyings; - - shader.number_of_varyings_in_fragment_shader = - v3d->prog.fs->prog_data.fs->num_inputs; - - shader.coordinate_shader_code_address = - cl_address(v3d_resource(v3d->prog.cs->resource)->bo, - v3d->prog.cs->offset); - shader.vertex_shader_code_address = - cl_address(v3d_resource(v3d->prog.vs->resource)->bo, - v3d->prog.vs->offset); - shader.fragment_shader_code_address = - cl_address(v3d_resource(v3d->prog.fs->resource)->bo, - v3d->prog.fs->offset); - -#if V3D_VERSION == 42 - shader.coordinate_shader_propagate_nans = true; - shader.vertex_shader_propagate_nans = true; - shader.fragment_shader_propagate_nans = true; - - /* XXX: Use combined input/output size flag in the common - * case. - */ - shader.coordinate_shader_has_separate_input_and_output_vpm_blocks = - v3d->prog.cs->prog_data.vs->separate_segments; - shader.vertex_shader_has_separate_input_and_output_vpm_blocks = - v3d->prog.vs->prog_data.vs->separate_segments; - shader.coordinate_shader_input_vpm_segment_size = - v3d->prog.cs->prog_data.vs->separate_segments ? - v3d->prog.cs->prog_data.vs->vpm_input_size : 1; - shader.vertex_shader_input_vpm_segment_size = - v3d->prog.vs->prog_data.vs->separate_segments ? - v3d->prog.vs->prog_data.vs->vpm_input_size : 1; -#endif - /* On V3D 7.1 there isn't a specific flag to set if we are using - * shared/separate segments or not. We just set the value of - * vpm_input_size to 0, and set output to the max needed. That should be - * already properly set on prog_data_vs_bin - */ -#if V3D_VERSION == 71 - shader.coordinate_shader_input_vpm_segment_size = - v3d->prog.cs->prog_data.vs->vpm_input_size; - shader.vertex_shader_input_vpm_segment_size = - v3d->prog.vs->prog_data.vs->vpm_input_size; -#endif - - shader.coordinate_shader_output_vpm_segment_size = - v3d->prog.cs->prog_data.vs->vpm_output_size; - shader.vertex_shader_output_vpm_segment_size = - v3d->prog.vs->prog_data.vs->vpm_output_size; - - shader.coordinate_shader_uniforms_address = cs_uniforms; - shader.vertex_shader_uniforms_address = vs_uniforms; - shader.fragment_shader_uniforms_address = fs_uniforms; - - shader.min_coord_shader_input_segments_required_in_play = - vpm_cfg_bin.As; - shader.min_vertex_shader_input_segments_required_in_play = - vpm_cfg.As; - - shader.min_coord_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = - vpm_cfg_bin.Ve; - shader.min_vertex_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size = - vpm_cfg.Ve; - - shader.coordinate_shader_4_way_threadable = - v3d->prog.cs->prog_data.vs->base.threads == 4; - shader.vertex_shader_4_way_threadable = - v3d->prog.vs->prog_data.vs->base.threads == 4; - shader.fragment_shader_4_way_threadable = - v3d->prog.fs->prog_data.fs->base.threads == 4; - - shader.coordinate_shader_start_in_final_thread_section = - v3d->prog.cs->prog_data.vs->base.single_seg; - shader.vertex_shader_start_in_final_thread_section = - v3d->prog.vs->prog_data.vs->base.single_seg; - shader.fragment_shader_start_in_final_thread_section = - v3d->prog.fs->prog_data.fs->base.single_seg; - - shader.vertex_id_read_by_coordinate_shader = - v3d->prog.cs->prog_data.vs->uses_vid; - shader.instance_id_read_by_coordinate_shader = - v3d->prog.cs->prog_data.vs->uses_iid; - shader.vertex_id_read_by_vertex_shader = - v3d->prog.vs->prog_data.vs->uses_vid; - shader.instance_id_read_by_vertex_shader = - v3d->prog.vs->prog_data.vs->uses_iid; - -#if V3D_VERSION == 42 - shader.address_of_default_attribute_values = - cl_address(v3d_resource(vtx->defaults)->bo, - vtx->defaults_offset); -#endif - } + emit_shader_state_record(v3d, job, info, vtx, + cs_uniforms, vs_uniforms, fs_uniforms, + &vpm_cfg_bin, &vpm_cfg); bool cs_loaded_any = false; const bool cs_uses_builtins = v3d->prog.cs->prog_data.vs->uses_iid ||