diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 6e9717bbe02..fca740990fa 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -44,6 +44,7 @@ #include "draw_vs.h" #include "draw_gs.h" #include "draw_tess.h" +#include "draw_mesh.h" #ifdef DRAW_LLVM_AVAILABLE #include "gallivm/lp_bld_init.h" @@ -626,7 +627,9 @@ draw_remove_extra_vertex_attribs(struct draw_context *draw) struct tgsi_shader_info * draw_get_shader_info(const struct draw_context *draw) { - if (draw->gs.geometry_shader) { + if (draw->ms.mesh_shader) { + return &draw->ms.mesh_shader->info; + } else if (draw->gs.geometry_shader) { return &draw->gs.geometry_shader->info; } else if (draw->tes.tess_eval_shader) { return &draw->tes.tess_eval_shader->info; @@ -921,6 +924,8 @@ void draw_do_flush(struct draw_context *draw, unsigned flags) uint draw_current_shader_outputs(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.num_ms_outputs; if (draw->gs.geometry_shader) return draw->gs.num_gs_outputs; if (draw->tes.tess_eval_shader) @@ -936,6 +941,8 @@ draw_current_shader_outputs(const struct draw_context *draw) uint draw_current_shader_position_output(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.position_output; if (draw->gs.geometry_shader) return draw->gs.position_output; if (draw->tes.tess_eval_shader) @@ -951,6 +958,8 @@ draw_current_shader_position_output(const struct draw_context *draw) uint draw_current_shader_viewport_index_output(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.mesh_shader->viewport_index_output; if (draw->gs.geometry_shader) return draw->gs.geometry_shader->viewport_index_output; else if (draw->tes.tess_eval_shader) @@ -966,6 +975,8 @@ draw_current_shader_viewport_index_output(const struct draw_context *draw) boolean draw_current_shader_uses_viewport_index(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.mesh_shader->info.writes_viewport_index; if (draw->gs.geometry_shader) return draw->gs.geometry_shader->info.writes_viewport_index; else if (draw->tes.tess_eval_shader) @@ -983,6 +994,8 @@ draw_current_shader_uses_viewport_index(const struct draw_context *draw) uint draw_current_shader_clipvertex_output(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.clipvertex_output; if (draw->gs.geometry_shader) return draw->gs.clipvertex_output; if (draw->tes.tess_eval_shader) @@ -995,6 +1008,8 @@ uint draw_current_shader_ccdistance_output(const struct draw_context *draw, int index) { assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); + if (draw->ms.mesh_shader) + return draw->ms.mesh_shader->ccdistance_output[index]; if (draw->gs.geometry_shader) return draw->gs.geometry_shader->ccdistance_output[index]; if (draw->tes.tess_eval_shader) @@ -1006,6 +1021,8 @@ draw_current_shader_ccdistance_output(const struct draw_context *draw, int index uint draw_current_shader_num_written_clipdistances(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.mesh_shader->info.num_written_clipdistance; if (draw->gs.geometry_shader) return draw->gs.geometry_shader->info.num_written_clipdistance; if (draw->tes.tess_eval_shader) @@ -1016,6 +1033,8 @@ draw_current_shader_num_written_clipdistances(const struct draw_context *draw) uint draw_current_shader_num_written_culldistances(const struct draw_context *draw) { + if (draw->ms.mesh_shader) + return draw->ms.mesh_shader->info.num_written_culldistance; if (draw->gs.geometry_shader) return draw->gs.geometry_shader->info.num_written_culldistance; if (draw->tes.tess_eval_shader) diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 002675395c7..5c1edf31fb4 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -48,6 +48,7 @@ struct draw_vertex_shader; struct draw_geometry_shader; struct draw_tess_ctrl_shader; struct draw_tess_eval_shader; +struct draw_mesh_shader; struct draw_fragment_shader; struct tgsi_sampler; struct tgsi_image; @@ -281,6 +282,17 @@ void draw_set_tess_state(struct draw_context *draw, const float default_outer_level[4], const float default_inner_level[2]); +/* + * Mesh shader functions + */ +struct draw_mesh_shader * +draw_create_mesh_shader(struct draw_context *draw, + const struct pipe_shader_state *shader); +void draw_bind_mesh_shader(struct draw_context *draw, + struct draw_mesh_shader *dvs); +void draw_delete_mesh_shader(struct draw_context *draw, + struct draw_mesh_shader *dvs); + /* * Vertex data functions */ diff --git a/src/gallium/auxiliary/draw/draw_mesh.c b/src/gallium/auxiliary/draw/draw_mesh.c new file mode 100644 index 00000000000..d4dc0347e86 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_mesh.c @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2023 Red Hat. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "draw_mesh.h" +#include "draw_context.h" + +#include "tgsi/tgsi_scan.h" +#include "nir/nir_to_tgsi_info.h" +#include "pipe/p_shader_tokens.h" + +struct draw_mesh_shader * +draw_create_mesh_shader(struct draw_context *draw, + const struct pipe_shader_state *state) +{ + struct draw_mesh_shader *ms; + + ms = CALLOC_STRUCT(draw_mesh_shader); + + if (!ms) + return NULL; + + ms->draw = draw; + + nir_tgsi_scan_shader(state->ir.nir, &ms->info, true); + + nir_shader *nir = state->ir.nir; + + ms->output_primitive = nir->info.mesh.primitive_type; + + ms->position_output = -1; + bool found_clipvertex = false; + for (unsigned i = 0; i < ms->info.num_outputs; i++) { + if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && + ms->info.output_semantic_index[i] == 0) + ms->position_output = i; + if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) + ms->viewport_index_output = i; + if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX && + ms->info.output_semantic_index[i] == 0) { + found_clipvertex = true; + ms->clipvertex_output = i; + } + if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) { + assert(ms->info.output_semantic_index[i] < + PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); + ms->ccdistance_output[ms->info.output_semantic_index[i]] = i; + } + } + if (!found_clipvertex) + ms->clipvertex_output = ms->position_output; + return ms; +} + +void +draw_bind_mesh_shader(struct draw_context *draw, + struct draw_mesh_shader *dms) +{ + draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE); + + if (dms) { + draw->ms.mesh_shader = dms; + draw->ms.num_ms_outputs = dms->info.num_outputs; + draw->ms.position_output = dms->position_output; + draw->ms.clipvertex_output = dms->clipvertex_output; + } else { + draw->ms.mesh_shader = NULL; + draw->ms.num_ms_outputs = 0; + } +} + +void +draw_delete_mesh_shader(struct draw_context *draw, + struct draw_mesh_shader *dms) +{ + if (!dms) + return; + + FREE(dms); +} diff --git a/src/gallium/auxiliary/draw/draw_mesh.h b/src/gallium/auxiliary/draw/draw_mesh.h new file mode 100644 index 00000000000..50b9bd5a494 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_mesh.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2023 Red Hat. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRAW_MESH_H +#define DRAW_MESH_H + +#include "draw_context.h" +#include "draw_private.h" +#include "tgsi/tgsi_exec.h" +#include "tgsi/tgsi_scan.h" + +struct draw_context; + +struct draw_mesh_shader { + struct draw_context *draw; + + struct tgsi_shader_info info; + + unsigned position_output; + unsigned viewport_index_output; + unsigned clipvertex_output; + unsigned ccdistance_output[PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT]; + unsigned output_primitive; +}; + +#endif diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 2357637f727..9f965beb9d7 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -356,6 +356,13 @@ struct draw_context struct draw_fragment_shader *fragment_shader; } fs; + struct { + struct draw_mesh_shader *mesh_shader; + uint num_ms_outputs; /**< convenience, from geometry_shader */ + uint position_output; + uint clipvertex_output; + } ms; + /** Stream output (vertex feedback) state */ struct { struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS]; diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c index 865e12a9d7b..b907af14c9e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c @@ -61,6 +61,8 @@ draw_so_info(const struct draw_context *draw) { const struct pipe_stream_output_info *state = NULL; + if (draw->ms.mesh_shader) + return state; if (draw->gs.geometry_shader) { state = &draw->gs.geometry_shader->state.stream_output; } else if (draw->tes.tess_eval_shader) { diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index 85e1bc9352a..7ed95417185 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -34,6 +34,8 @@ files_libgallium = files( 'draw/draw_gs.c', 'draw/draw_gs.h', 'draw/draw_gs_tmp.h', + 'draw/draw_mesh.c', + 'draw/draw_mesh.h', 'draw/draw_pipe_aaline.c', 'draw/draw_pipe_aapoint.c', 'draw/draw_pipe.c',