From b545e78f12b02069fa363a4a7ef749a996ea3c4b Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 23 Nov 2023 11:33:57 +0100 Subject: [PATCH] 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: --- 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 6f979ee92915e..c936ed4510cd9 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -2431,6 +2431,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) + @@ -2478,39 +2485,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 4f893b1098a6f..6c4e340f6af87 100644 --- a/src/broadcom/vulkan/v3dvx_pipeline.c +++ b/src/broadcom/vulkan/v3dvx_pipeline.c @@ -357,6 +357,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)); @@ -369,6 +373,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 @@ -376,17 +388,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