From 00d43ee86592691f24bfc1c8aeacb206256a78ed Mon Sep 17 00:00:00 2001
From: Koichiro Iwao
Date: Wed, 9 Apr 2025 13:06:44 +0900
Subject: [PATCH] Add support for Raspberry Pi 2712D0 stepping
---
SOURCES/raspberrypi-2712D0.patch | 736 +++++++++++++++++++++++++++++++
SPECS/mesa.spec | 15 +-
2 files changed, 749 insertions(+), 2 deletions(-)
create mode 100644 SOURCES/raspberrypi-2712D0.patch
diff --git a/SOURCES/raspberrypi-2712D0.patch b/SOURCES/raspberrypi-2712D0.patch
new file mode 100644
index 0000000..6ade7ad
--- /dev/null
+++ b/SOURCES/raspberrypi-2712D0.patch
@@ -0,0 +1,736 @@
+From 646544da9e3b50cc72b963fe9693c979dbbbf636 Mon Sep 17 00:00:00 2001
+From: Iago Toral Quiroga
+Date: Tue, 14 May 2024 09:40:16 +0200
+Subject: [PATCH 1/3] broadcom/cle: fix up shader record for V3D 7.1.10 /
+ 2712D0
+
+Part-of:
+(cherry picked from commit 7b807c3e948398da96293c6252c57505e11c74c9)
+---
+ src/broadcom/cle/v3d_packet.xml | 63 +++++++++++++++++++++++++++++++++
+ 1 file changed, 63 insertions(+)
+
+diff --git a/src/broadcom/cle/v3d_packet.xml b/src/broadcom/cle/v3d_packet.xml
+index 09dde392fac..4763b891aab 100644
+--- a/src/broadcom/cle/v3d_packet.xml
++++ b/src/broadcom/cle/v3d_packet.xml
+@@ -1211,6 +1211,69 @@
+
+
+
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+
+
+
+--
+2.49.0
+
+From 576044e52be2c504ef011029015ecce1b95744b6 Mon Sep 17 00:00:00 2001
+From: Iago Toral Quiroga
+Date: Tue, 14 May 2024 10:24:07 +0200
+Subject: [PATCH 2/3] 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:
+(cherry picked from commit 1fc846dce396e2e0d1be23568e22ae2510df71bd)
+---
+ 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 ||
+--
+2.49.0
+
+From de2176a6688d036abdfd6d2a13d4aa9834cf870c Mon Sep 17 00:00:00 2001
+From: Iago Toral Quiroga
+Date: Thu, 23 Nov 2023 11:33:57 +0100
+Subject: [PATCH 3/3] v3dv: support 2712D0
+
+2712D0 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 versioning framework doesn't
+support changes based on revision number alone.
+
+Part-of:
+(cherry picked from commit b545e78f12b02069fa363a4a7ef749a996ea3c4b)
+---
+ src/broadcom/vulkan/v3dvx_cmd_buffer.c | 94 +++++++++++++++++---------
+ src/broadcom/vulkan/v3dvx_pipeline.c | 75 +++++++++++++++++---
+ 2 files changed, 129 insertions(+), 40 deletions(-)
+
+diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+index 1b511408bfe..1b9d02e126c 100644
+--- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c
++++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+@@ -2343,6 +2343,13 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
+
+ uint32_t shader_state_record_length =
+ cl_packet_length(GL_SHADER_STATE_RECORD);
++#if V3D_VERSION >= 71
++ if (v3d_device_has_draw_index(&pipeline->device->devinfo)) {
++ shader_state_record_length =
++ cl_packet_length(GL_SHADER_STATE_RECORD_DRAW_INDEX);
++ }
++#endif
++
+ if (pipeline->has_gs) {
+ shader_state_record_length +=
+ cl_packet_length(GEOMETRY_SHADER_STATE_RECORD) +
+@@ -2390,39 +2397,64 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
+ pipeline->device->default_attribute_float;
+ #endif
+
+- cl_emit_with_prepacked(&job->indirect, GL_SHADER_STATE_RECORD,
+- pipeline->shader_state_record, shader) {
+-
+- /* FIXME: we are setting this values here and during the
+- * prepacking. This is because both cl_emit_with_prepacked and v3dvx_pack
+- * asserts for minimum values of these. It would be good to get
+- * v3dvx_pack to assert on the final value if possible
+- */
+- shader.min_coord_shader_input_segments_required_in_play =
+- pipeline->vpm_cfg_bin.As;
+- shader.min_vertex_shader_input_segments_required_in_play =
+- pipeline->vpm_cfg.As;
+-
+- shader.coordinate_shader_code_address =
+- v3dv_cl_address(assembly_bo, vs_bin_variant->assembly_offset);
+- shader.vertex_shader_code_address =
+- v3dv_cl_address(assembly_bo, vs_variant->assembly_offset);
+- shader.fragment_shader_code_address =
+- v3dv_cl_address(assembly_bo, fs_variant->assembly_offset);
+-
+- shader.coordinate_shader_uniforms_address = cmd_buffer->state.uniforms.vs_bin;
+- shader.vertex_shader_uniforms_address = cmd_buffer->state.uniforms.vs;
+- shader.fragment_shader_uniforms_address = cmd_buffer->state.uniforms.fs;
+-
+-#if V3D_VERSION == 42
+- shader.address_of_default_attribute_values =
+- v3dv_cl_address(default_attribute_values, 0);
++#if V3D_VERSION >= 71
++ if (v3d_device_has_draw_index(&pipeline->device->devinfo)) {
++ cl_emit_with_prepacked(&job->indirect, GL_SHADER_STATE_RECORD_DRAW_INDEX,
++ pipeline->shader_state_record, shader) {
++ shader.min_coord_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg_bin.As;
++ shader.min_vertex_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg.As;
++ shader.coordinate_shader_code_address =
++ v3dv_cl_address(assembly_bo, vs_bin_variant->assembly_offset);
++ shader.vertex_shader_code_address =
++ v3dv_cl_address(assembly_bo, vs_variant->assembly_offset);
++ shader.fragment_shader_code_address =
++ v3dv_cl_address(assembly_bo, fs_variant->assembly_offset);
++ shader.coordinate_shader_uniforms_address = cmd_buffer->state.uniforms.vs_bin;
++ shader.vertex_shader_uniforms_address = cmd_buffer->state.uniforms.vs;
++ shader.fragment_shader_uniforms_address = cmd_buffer->state.uniforms.fs;
++ shader.any_shader_reads_hardware_written_primitive_id =
++ (pipeline->has_gs && prog_data_gs->uses_pid) || prog_data_fs->uses_pid;
++ shader.insert_primitive_id_as_first_varying_to_fragment_shader =
++ !pipeline->has_gs && prog_data_fs->uses_pid;
++ }
++ } else
+ #endif
++ {
++ cl_emit_with_prepacked(&job->indirect, GL_SHADER_STATE_RECORD,
++ pipeline->shader_state_record, shader) {
++ /* FIXME: we are setting this values here and during the
++ * prepacking. This is because both cl_emit_with_prepacked and v3dvx_pack
++ * asserts for minimum values of these. It would be good to get
++ * v3dvx_pack to assert on the final value if possible
++ */
++ shader.min_coord_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg_bin.As;
++ shader.min_vertex_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg.As;
+
+- shader.any_shader_reads_hardware_written_primitive_id =
+- (pipeline->has_gs && prog_data_gs->uses_pid) || prog_data_fs->uses_pid;
+- shader.insert_primitive_id_as_first_varying_to_fragment_shader =
+- !pipeline->has_gs && prog_data_fs->uses_pid;
++ shader.coordinate_shader_code_address =
++ v3dv_cl_address(assembly_bo, vs_bin_variant->assembly_offset);
++ shader.vertex_shader_code_address =
++ v3dv_cl_address(assembly_bo, vs_variant->assembly_offset);
++ shader.fragment_shader_code_address =
++ v3dv_cl_address(assembly_bo, fs_variant->assembly_offset);
++
++ shader.coordinate_shader_uniforms_address = cmd_buffer->state.uniforms.vs_bin;
++ shader.vertex_shader_uniforms_address = cmd_buffer->state.uniforms.vs;
++ shader.fragment_shader_uniforms_address = cmd_buffer->state.uniforms.fs;
++
++ #if V3D_VERSION == 42
++ shader.address_of_default_attribute_values =
++ v3dv_cl_address(default_attribute_values, 0);
++ #endif
++
++ shader.any_shader_reads_hardware_written_primitive_id =
++ (pipeline->has_gs && prog_data_gs->uses_pid) || prog_data_fs->uses_pid;
++ shader.insert_primitive_id_as_first_varying_to_fragment_shader =
++ !pipeline->has_gs && prog_data_fs->uses_pid;
++ }
+ }
+
+ /* Upload vertex element attributes (SHADER_STATE_ATTRIBUTE_RECORD) */
+diff --git a/src/broadcom/vulkan/v3dvx_pipeline.c b/src/broadcom/vulkan/v3dvx_pipeline.c
+index 5ae0d2597b0..ad66374289e 100644
+--- a/src/broadcom/vulkan/v3dvx_pipeline.c
++++ b/src/broadcom/vulkan/v3dvx_pipeline.c
+@@ -394,6 +394,10 @@ v3dX(pipeline_pack_state)(struct v3dv_pipeline *pipeline,
+ static void
+ pack_shader_state_record(struct v3dv_pipeline *pipeline)
+ {
++ /* To siplify the code we ignore here GL_SHADER_STATE_RECORD_DRAW_INDEX
++ * used with 2712D0, since we know that has the same size as the regular
++ * version.
++ */
+ assert(sizeof(pipeline->shader_state_record) >=
+ cl_packet_length(GL_SHADER_STATE_RECORD));
+
+@@ -406,6 +410,14 @@ pack_shader_state_record(struct v3dv_pipeline *pipeline)
+ struct v3d_vs_prog_data *prog_data_vs_bin =
+ pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN]->prog_data.vs;
+
++ bool point_size_in_shaded_vertex_data;
++ if (!pipeline->has_gs) {
++ point_size_in_shaded_vertex_data = pipeline->topology == MESA_PRIM_POINTS;
++ } else {
++ struct v3d_gs_prog_data *prog_data_gs =
++ pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY]->prog_data.gs;
++ point_size_in_shaded_vertex_data = prog_data_gs->writes_psiz;
++ }
+
+ /* Note: we are not packing addresses, as we need the job (see
+ * cl_pack_emit_reloc). Additionally uniforms can't be filled up at this
+@@ -413,17 +425,62 @@ pack_shader_state_record(struct v3dv_pipeline *pipeline)
+ * pipeline (like viewport), . Would need to be filled later, so we are
+ * doing a partial prepacking.
+ */
++#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 device at run time which packet we need
++ * to emit.
++ */
++ if (v3d_device_has_draw_index(&pipeline->device->devinfo)) {
++ v3dvx_pack(pipeline->shader_state_record, GL_SHADER_STATE_RECORD_DRAW_INDEX, shader) {
++ shader.enable_clipping = true;
++ shader.point_size_in_shaded_vertex_data = point_size_in_shaded_vertex_data;
++ shader.fragment_shader_does_z_writes = prog_data_fs->writes_z;
++ shader.turn_off_early_z_test = prog_data_fs->disable_ez;
++ shader.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 =
++ prog_data_fs->uses_center_w;
++ shader.enable_sample_rate_shading =
++ pipeline->sample_rate_shading ||
++ (pipeline->msaa && prog_data_fs->force_per_sample_msaa);
++ shader.any_shader_reads_hardware_written_primitive_id = false;
++ shader.do_scoreboard_wait_on_first_thread_switch =
++ prog_data_fs->lock_scoreboard_on_first_thrsw;
++ shader.disable_implicit_point_line_varyings =
++ !prog_data_fs->uses_implicit_point_line_varyings;
++ shader.number_of_varyings_in_fragment_shader = prog_data_fs->num_inputs;
++ shader.coordinate_shader_input_vpm_segment_size = prog_data_vs_bin->vpm_input_size;
++ shader.vertex_shader_input_vpm_segment_size = prog_data_vs->vpm_input_size;
++ shader.coordinate_shader_output_vpm_segment_size = prog_data_vs_bin->vpm_output_size;
++ shader.vertex_shader_output_vpm_segment_size = prog_data_vs->vpm_output_size;
++ shader.min_coord_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg_bin.As;
++ shader.min_vertex_shader_input_segments_required_in_play =
++ pipeline->vpm_cfg.As;
++ shader.min_coord_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size =
++ pipeline->vpm_cfg_bin.Ve;
++ shader.min_vertex_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size =
++ pipeline->vpm_cfg.Ve;
++ shader.coordinate_shader_4_way_threadable = prog_data_vs_bin->base.threads == 4;
++ shader.vertex_shader_4_way_threadable = prog_data_vs->base.threads == 4;
++ shader.fragment_shader_4_way_threadable = prog_data_fs->base.threads == 4;
++ shader.coordinate_shader_start_in_final_thread_section = prog_data_vs_bin->base.single_seg;
++ shader.vertex_shader_start_in_final_thread_section = prog_data_vs->base.single_seg;
++ shader.fragment_shader_start_in_final_thread_section = prog_data_fs->base.single_seg;
++ shader.vertex_id_read_by_coordinate_shader = prog_data_vs_bin->uses_vid;
++ shader.base_instance_id_read_by_coordinate_shader = prog_data_vs_bin->uses_biid;
++ shader.instance_id_read_by_coordinate_shader = prog_data_vs_bin->uses_iid;
++ shader.vertex_id_read_by_vertex_shader = prog_data_vs->uses_vid;
++ shader.base_instance_id_read_by_vertex_shader = prog_data_vs->uses_biid;
++ shader.instance_id_read_by_vertex_shader = prog_data_vs->uses_iid;
++ }
++ return;
++ }
++#endif
++
+ v3dvx_pack(pipeline->shader_state_record, GL_SHADER_STATE_RECORD, shader) {
+ shader.enable_clipping = true;
+-
+- if (!pipeline->has_gs) {
+- shader.point_size_in_shaded_vertex_data =
+- pipeline->topology == MESA_PRIM_POINTS;
+- } else {
+- struct v3d_gs_prog_data *prog_data_gs =
+- pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY]->prog_data.gs;
+- shader.point_size_in_shaded_vertex_data = prog_data_gs->writes_psiz;
+- }
++ shader.point_size_in_shaded_vertex_data = point_size_in_shaded_vertex_data;
+
+ /* Must be set if the shader modifies Z, discards, or modifies
+ * the sample mask. For any of these cases, the fragment
+--
+2.49.0
+
diff --git a/SPECS/mesa.spec b/SPECS/mesa.spec
index 7455e44..08a3f10 100644
--- a/SPECS/mesa.spec
+++ b/SPECS/mesa.spec
@@ -75,7 +75,7 @@ Name: mesa
Summary: Mesa graphics libraries
%global ver 24.1.2
Version: %{lua:ver = string.gsub(rpm.expand("%{ver}"), "-", "~"); print(ver)}
-Release: 3%{?dist}.alma.1
+Release: 3%{?dist}.alma.2
License: MIT AND BSD-3-Clause AND SGI-B-2.0
URL: http://www.mesa3d.org
@@ -123,6 +123,9 @@ Patch12: 0001-Revert-ac-radeonsi-remove-has_syncobj-has_fence_to_h.patch
# s390x only
Patch100: fix-egl-on-s390x.patch
+# Add support for Raspberry Pi 2712D0 stepping
+Patch1000: raspberrypi-2712D0.patch
+
# Build our own version but keep the dependency for the RPM macros
BuildRequires: meson
BuildRequires: gcc
@@ -441,6 +444,10 @@ The drivers with support for the Vulkan API.
%ifarch s390x
%autopatch -p1 -m 100
%endif
+%ifarch aarch64
+%autopatch -p1 -m 1000
+%endif
+
cp %{SOURCE1} docs/
# Extract meson
@@ -876,7 +883,11 @@ popd
%endif
%changelog
-* Thu Oct 03 2024 Eduard Abdullin - 23.3.3-1.alma.1
+* Wed Apr 09 2025 Koichiro Iwao - 24.1.2-3.alma.2
+- Add support for Raspberry Pi 2712D0 stepping
+ Resolves: https://bugs.almalinux.org/view.php?id=497
+
+* Thu Oct 03 2024 Eduard Abdullin - 24.1.2-3.alma.1
- Enable vc4 and v3d for Raspberry Pi graphics in AlmaLinux
Resolves: https://github.com/AlmaLinux/raspberry-pi/issues/32