Mesa (main): v3dv: emit state packets for geometry shaders
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jul 12 07:56:03 UTC 2021
Module: Mesa
Branch: main
Commit: 991cca2e77b730113dc6388db8b617b76e359e6e
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=991cca2e77b730113dc6388db8b617b76e359e6e
Author: Iago Toral Quiroga <itoral at igalia.com>
Date: Thu Jul 1 09:08:02 2021 +0200
v3dv: emit state packets for geometry shaders
Reviewed-by: Alejandro Piñeiro <apinheiro at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11783>
---
src/broadcom/vulkan/v3dv_cmd_buffer.c | 34 ++++++
src/broadcom/vulkan/v3dv_private.h | 2 +
src/broadcom/vulkan/v3dvx_cmd_buffer.c | 203 ++++++++++++++++++++++++++++++---
3 files changed, 222 insertions(+), 17 deletions(-)
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 72092b2c47e..42755a7923d 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -2086,6 +2086,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
const bool has_new_push_constants = dirty_uniform_state & V3DV_CMD_DIRTY_PUSH_CONSTANTS;
const bool has_new_descriptors = dirty_uniform_state & V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
+ /* VK_SHADER_STAGE_FRAGMENT_BIT */
const bool has_new_descriptors_fs =
has_new_descriptors &&
(cmd_buffer->state.dirty_descriptor_stages & VK_SHADER_STAGE_FRAGMENT_BIT);
@@ -2106,6 +2107,39 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
v3dv_write_uniforms(cmd_buffer, pipeline, fs_variant);
}
+ /* VK_SHADER_STAGE_GEOMETRY_BIT */
+ if (pipeline->has_gs) {
+ const bool has_new_descriptors_gs =
+ has_new_descriptors &&
+ (cmd_buffer->state.dirty_descriptor_stages &
+ VK_SHADER_STAGE_GEOMETRY_BIT);
+
+ const bool has_new_push_constants_gs =
+ has_new_push_constants &&
+ (cmd_buffer->state.dirty_push_constants_stages &
+ VK_SHADER_STAGE_GEOMETRY_BIT);
+
+ const bool needs_gs_update = has_new_viewport ||
+ has_new_pipeline ||
+ has_new_push_constants_gs ||
+ has_new_descriptors_gs;
+
+ if (needs_gs_update) {
+ struct v3dv_shader_variant *gs_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY];
+
+ struct v3dv_shader_variant *gs_bin_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY_BIN];
+
+ cmd_buffer->state.uniforms.gs =
+ v3dv_write_uniforms(cmd_buffer, pipeline, gs_variant);
+
+ cmd_buffer->state.uniforms.gs_bin =
+ v3dv_write_uniforms(cmd_buffer, pipeline, gs_bin_variant);
+ }
+ }
+
+ /* VK_SHADER_STAGE_VERTEX_BIT */
const bool has_new_descriptors_vs =
has_new_descriptors &&
(cmd_buffer->state.dirty_descriptor_stages & VK_SHADER_STAGE_VERTEX_BIT);
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 6440695246d..e53a2f9f5a0 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1132,6 +1132,8 @@ struct v3dv_cmd_buffer_state {
struct {
struct v3dv_cl_reloc vs_bin;
struct v3dv_cl_reloc vs;
+ struct v3dv_cl_reloc gs_bin;
+ struct v3dv_cl_reloc gs;
struct v3dv_cl_reloc fs;
} uniforms;
diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
index 3f71ad72cbf..933f55b2737 100644
--- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
@@ -1648,6 +1648,117 @@ v3dX(cmd_buffer_execute_inside_pass)(struct v3dv_cmd_buffer *primary,
}
}
+static void
+emit_gs_shader_state_record(struct v3dv_job *job,
+ struct v3dv_bo *assembly_bo,
+ struct v3dv_shader_variant *gs_bin,
+ struct v3dv_cl_reloc gs_bin_uniforms,
+ struct v3dv_shader_variant *gs,
+ struct v3dv_cl_reloc gs_render_uniforms)
+{
+ cl_emit(&job->indirect, GEOMETRY_SHADER_STATE_RECORD, shader) {
+ shader.geometry_bin_mode_shader_code_address =
+ v3dv_cl_address(assembly_bo, gs_bin->assembly_offset);
+ shader.geometry_bin_mode_shader_4_way_threadable =
+ gs_bin->prog_data.gs->base.threads == 4;
+ shader.geometry_bin_mode_shader_start_in_final_thread_section =
+ gs_bin->prog_data.gs->base.single_seg;
+ shader.geometry_bin_mode_shader_propagate_nans = true;
+ shader.geometry_bin_mode_shader_uniforms_address =
+ gs_bin_uniforms;
+
+ shader.geometry_render_mode_shader_code_address =
+ v3dv_cl_address(assembly_bo, gs->assembly_offset);
+ shader.geometry_render_mode_shader_4_way_threadable =
+ gs->prog_data.gs->base.threads == 4;
+ shader.geometry_render_mode_shader_start_in_final_thread_section =
+ gs->prog_data.gs->base.single_seg;
+ shader.geometry_render_mode_shader_propagate_nans = true;
+ shader.geometry_render_mode_shader_uniforms_address =
+ gs_render_uniforms;
+ }
+}
+
+static uint8_t
+v3d_gs_output_primitive(uint32_t prim_type)
+{
+ switch (prim_type) {
+ case GL_POINTS:
+ return GEOMETRY_SHADER_POINTS;
+ case GL_LINE_STRIP:
+ return GEOMETRY_SHADER_LINE_STRIP;
+ case GL_TRIANGLE_STRIP:
+ return GEOMETRY_SHADER_TRI_STRIP;
+ default:
+ unreachable("Unsupported primitive type");
+ }
+}
+
+static void
+emit_tes_gs_common_params(struct v3dv_job *job,
+ uint8_t gs_out_prim_type,
+ uint8_t gs_num_invocations)
+{
+ cl_emit(&job->indirect, TESSELLATION_GEOMETRY_COMMON_PARAMS, shader) {
+ shader.tessellation_type = TESSELLATION_TYPE_TRIANGLE;
+ shader.tessellation_point_mode = false;
+ shader.tessellation_edge_spacing = TESSELLATION_EDGE_SPACING_EVEN;
+ shader.tessellation_clockwise = true;
+ shader.tessellation_invocations = 1;
+
+ shader.geometry_shader_output_format =
+ v3d_gs_output_primitive(gs_out_prim_type);
+ shader.geometry_shader_instances = gs_num_invocations & 0x1F;
+ }
+}
+
+static uint8_t
+simd_width_to_gs_pack_mode(uint32_t width)
+{
+ switch (width) {
+ case 16:
+ return V3D_PACK_MODE_16_WAY;
+ case 8:
+ return V3D_PACK_MODE_8_WAY;
+ case 4:
+ return V3D_PACK_MODE_4_WAY;
+ case 1:
+ return V3D_PACK_MODE_1_WAY;
+ default:
+ unreachable("Invalid SIMD width");
+ };
+}
+
+static void
+emit_tes_gs_shader_params(struct v3dv_job *job,
+ uint32_t gs_simd,
+ uint32_t gs_vpm_output_size,
+ uint32_t gs_max_vpm_input_size_per_batch)
+{
+ cl_emit(&job->indirect, TESSELLATION_GEOMETRY_SHADER_PARAMS, shader) {
+ shader.tcs_batch_flush_mode = V3D_TCS_FLUSH_MODE_FULLY_PACKED;
+ shader.per_patch_data_column_depth = 1;
+ shader.tcs_output_segment_size_in_sectors = 1;
+ shader.tcs_output_segment_pack_mode = V3D_PACK_MODE_16_WAY;
+ shader.tes_output_segment_size_in_sectors = 1;
+ shader.tes_output_segment_pack_mode = V3D_PACK_MODE_16_WAY;
+ shader.gs_output_segment_size_in_sectors = gs_vpm_output_size;
+ shader.gs_output_segment_pack_mode =
+ simd_width_to_gs_pack_mode(gs_simd);
+ shader.tbg_max_patches_per_tcs_batch = 1;
+ shader.tbg_max_extra_vertex_segs_for_patches_after_first = 0;
+ shader.tbg_min_tcs_output_segments_required_in_play = 1;
+ shader.tbg_min_per_patch_data_segments_required_in_play = 1;
+ shader.tpg_max_patches_per_tes_batch = 1;
+ shader.tpg_max_vertex_segments_per_tes_batch = 0;
+ shader.tpg_max_tcs_output_segments_per_tes_batch = 1;
+ shader.tpg_min_tes_output_segments_required_in_play = 1;
+ shader.gbg_max_tes_output_vertex_segments_per_gs_batch =
+ gs_max_vpm_input_size_per_batch;
+ shader.gbg_min_gs_output_segments_required_in_play = 1;
+ }
+}
+
void
v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
{
@@ -1658,37 +1769,86 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
struct v3dv_pipeline *pipeline = state->gfx.pipeline;
assert(pipeline);
- struct v3d_vs_prog_data *prog_data_vs =
- pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX]->prog_data.vs;
- struct v3d_vs_prog_data *prog_data_vs_bin =
- pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN]->prog_data.vs;
- struct v3d_fs_prog_data *prog_data_fs =
- pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT]->prog_data.fs;
+ struct v3dv_shader_variant *vs_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX];
+ struct v3d_vs_prog_data *prog_data_vs = vs_variant->prog_data.vs;
+
+ struct v3dv_shader_variant *vs_bin_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN];
+ struct v3d_vs_prog_data *prog_data_vs_bin = vs_bin_variant->prog_data.vs;
+
+ struct v3dv_shader_variant *fs_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];
+ struct v3d_fs_prog_data *prog_data_fs = fs_variant->prog_data.fs;
+
+ struct v3dv_shader_variant *gs_variant = NULL;
+ struct v3dv_shader_variant *gs_bin_variant = NULL;
+ struct v3d_gs_prog_data *prog_data_gs = NULL;
+ struct v3d_gs_prog_data *prog_data_gs_bin = NULL;
+ if (pipeline->has_gs) {
+ gs_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY];
+ prog_data_gs = gs_variant->prog_data.gs;
+
+ gs_bin_variant =
+ pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY_BIN];
+ prog_data_gs_bin = gs_bin_variant->prog_data.gs;
+ }
/* Update the cache dirty flag based on the shader progs data */
job->tmu_dirty_rcl |= prog_data_vs_bin->base.tmu_dirty_rcl;
job->tmu_dirty_rcl |= prog_data_vs->base.tmu_dirty_rcl;
job->tmu_dirty_rcl |= prog_data_fs->base.tmu_dirty_rcl;
+ if (pipeline->has_gs) {
+ job->tmu_dirty_rcl |= prog_data_gs_bin->base.tmu_dirty_rcl;
+ job->tmu_dirty_rcl |= prog_data_gs->base.tmu_dirty_rcl;
+ }
/* See GFXH-930 workaround below */
uint32_t num_elements_to_emit = MAX2(pipeline->va_count, 1);
+ uint32_t shader_state_record_length =
+ cl_packet_length(GL_SHADER_STATE_RECORD);
+ if (pipeline->has_gs) {
+ shader_state_record_length +=
+ cl_packet_length(GEOMETRY_SHADER_STATE_RECORD) +
+ cl_packet_length(TESSELLATION_GEOMETRY_COMMON_PARAMS) +
+ 2 * cl_packet_length(TESSELLATION_GEOMETRY_SHADER_PARAMS);
+ }
+
uint32_t shader_rec_offset =
v3dv_cl_ensure_space(&job->indirect,
- cl_packet_length(GL_SHADER_STATE_RECORD) +
+ shader_state_record_length +
num_elements_to_emit *
cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD),
32);
v3dv_return_if_oom(cmd_buffer, NULL);
- struct v3dv_shader_variant *vs_variant =
- pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX];
- struct v3dv_shader_variant *vs_bin_variant =
- pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN];
- struct v3dv_shader_variant *fs_variant =
- pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];
struct v3dv_bo *assembly_bo = pipeline->shared_data->assembly_bo;
+ if (pipeline->has_gs) {
+ emit_gs_shader_state_record(job,
+ assembly_bo,
+ gs_bin_variant,
+ cmd_buffer->state.uniforms.gs_bin,
+ gs_variant,
+ cmd_buffer->state.uniforms.gs);
+
+ emit_tes_gs_common_params(job,
+ prog_data_gs->out_prim_type,
+ prog_data_gs->num_invocations);
+
+ emit_tes_gs_shader_params(job,
+ pipeline->vpm_cfg_bin.gs_width,
+ pipeline->vpm_cfg_bin.Gd,
+ pipeline->vpm_cfg_bin.Gv);
+
+ emit_tes_gs_shader_params(job,
+ pipeline->vpm_cfg.gs_width,
+ pipeline->vpm_cfg.Gd,
+ pipeline->vpm_cfg.Gv);
+ }
+
struct v3dv_bo *default_attribute_values =
pipeline->default_attribute_values != NULL ?
pipeline->default_attribute_values :
@@ -1720,6 +1880,9 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
shader.address_of_default_attribute_values =
v3dv_cl_address(default_attribute_values, 0);
+
+ shader.any_shader_reads_hardware_written_primitive_id =
+ pipeline->has_gs ? prog_data_gs->uses_pid : false;
}
/* Upload vertex element attributes (SHADER_STATE_ATTRIBUTE_RECORD) */
@@ -1815,10 +1978,16 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
cl_packet_length(GL_SHADER_STATE));
v3dv_return_if_oom(cmd_buffer, NULL);
- cl_emit(&job->bcl, GL_SHADER_STATE, state) {
- state.address = v3dv_cl_address(job->indirect.bo,
- shader_rec_offset);
- state.number_of_attribute_arrays = num_elements_to_emit;
+ if (pipeline->has_gs) {
+ cl_emit(&job->bcl, GL_SHADER_STATE_INCLUDING_GS, state) {
+ state.address = v3dv_cl_address(job->indirect.bo, shader_rec_offset);
+ state.number_of_attribute_arrays = num_elements_to_emit;
+ }
+ } else {
+ cl_emit(&job->bcl, GL_SHADER_STATE, state) {
+ state.address = v3dv_cl_address(job->indirect.bo, shader_rec_offset);
+ state.number_of_attribute_arrays = num_elements_to_emit;
+ }
}
cmd_buffer->state.dirty &= ~(V3DV_CMD_DIRTY_VERTEX_BUFFER |
More information about the mesa-commit
mailing list