mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2024-11-23 02:04:41 +08:00
draw: primitive ID is per-patch
Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32231>
This commit is contained in:
parent
c2b7bafd76
commit
b80d0d8bf4
@ -449,6 +449,32 @@ gs_flush(struct draw_geometry_shader *shader)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
increment_prim(struct draw_geometry_shader *shader)
|
||||
{
|
||||
/* Primitive ID must be per-patch instead of per
|
||||
* tessellation primitive. If we have patch lengths
|
||||
* we use these to compute the primitive index.
|
||||
* See patch_lengths in llvm_pipeline_generic for
|
||||
* more info.
|
||||
*/
|
||||
++shader->fetched_prim_count;
|
||||
if (shader->next_patch_length) {
|
||||
shader->tess_prim_idx++;
|
||||
if (shader->tess_prim_idx >= *shader->next_patch_length) {
|
||||
++shader->in_prim_idx;
|
||||
++shader->next_patch_length;
|
||||
shader->tess_prim_idx = 0;
|
||||
}
|
||||
} else {
|
||||
++shader->in_prim_idx;
|
||||
}
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gs_point(struct draw_geometry_shader *shader, int idx)
|
||||
{
|
||||
@ -458,11 +484,8 @@ gs_point(struct draw_geometry_shader *shader, int idx)
|
||||
|
||||
shader->fetch_inputs(shader, indices, 1,
|
||||
shader->fetched_prim_count);
|
||||
++shader->in_prim_idx;
|
||||
++shader->fetched_prim_count;
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
increment_prim(shader);
|
||||
}
|
||||
|
||||
|
||||
@ -476,11 +499,8 @@ gs_line(struct draw_geometry_shader *shader, int i0, int i1)
|
||||
|
||||
shader->fetch_inputs(shader, indices, 2,
|
||||
shader->fetched_prim_count);
|
||||
++shader->in_prim_idx;
|
||||
++shader->fetched_prim_count;
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
increment_prim(shader);
|
||||
}
|
||||
|
||||
|
||||
@ -497,11 +517,8 @@ gs_line_adj(struct draw_geometry_shader *shader,
|
||||
|
||||
shader->fetch_inputs(shader, indices, 4,
|
||||
shader->fetched_prim_count);
|
||||
++shader->in_prim_idx;
|
||||
++shader->fetched_prim_count;
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
increment_prim(shader);
|
||||
}
|
||||
|
||||
|
||||
@ -517,11 +534,8 @@ gs_tri(struct draw_geometry_shader *shader,
|
||||
|
||||
shader->fetch_inputs(shader, indices, 3,
|
||||
shader->fetched_prim_count);
|
||||
++shader->in_prim_idx;
|
||||
++shader->fetched_prim_count;
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
increment_prim(shader);
|
||||
}
|
||||
|
||||
|
||||
@ -541,11 +555,8 @@ gs_tri_adj(struct draw_geometry_shader *shader,
|
||||
|
||||
shader->fetch_inputs(shader, indices, 6,
|
||||
shader->fetched_prim_count);
|
||||
++shader->in_prim_idx;
|
||||
++shader->fetched_prim_count;
|
||||
|
||||
if (draw_gs_should_flush(shader))
|
||||
gs_flush(shader);
|
||||
increment_prim(shader);
|
||||
}
|
||||
|
||||
#define FUNC gs_run
|
||||
@ -568,6 +579,7 @@ draw_geometry_shader_run(struct draw_geometry_shader *shader,
|
||||
const struct draw_vertex_info *input_verts,
|
||||
const struct draw_prim_info *input_prim,
|
||||
const struct tgsi_shader_info *input_info,
|
||||
uint32_t *const *patch_lengths,
|
||||
struct draw_vertex_info *output_verts,
|
||||
struct draw_prim_info *output_prims)
|
||||
{
|
||||
@ -638,6 +650,7 @@ draw_geometry_shader_run(struct draw_geometry_shader *shader,
|
||||
shader->input_vertex_stride = input_stride;
|
||||
shader->input = input;
|
||||
shader->input_info = input_info;
|
||||
shader->next_patch_length = patch_lengths ? *patch_lengths : NULL;
|
||||
|
||||
#if DRAW_LLVM_AVAILABLE
|
||||
if (shader->draw->llvm) {
|
||||
@ -1007,4 +1020,5 @@ draw_geometry_shader_new_instance(struct draw_geometry_shader *gs)
|
||||
return;
|
||||
|
||||
gs->in_prim_idx = 0;
|
||||
gs->tess_prim_idx = 0;
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ struct draw_geometry_shader {
|
||||
unsigned num_vertex_streams;
|
||||
|
||||
unsigned in_prim_idx;
|
||||
unsigned tess_prim_idx;
|
||||
const uint32_t *next_patch_length;
|
||||
unsigned input_vertex_stride;
|
||||
unsigned fetched_prim_count;
|
||||
const float (*input)[4];
|
||||
@ -142,8 +144,9 @@ draw_geometry_shader_run(struct draw_geometry_shader *shader,
|
||||
const struct draw_vertex_info *input_verts,
|
||||
const struct draw_prim_info *input_prim,
|
||||
const struct tgsi_shader_info *input_info,
|
||||
uint32_t *const *patch_lengths,
|
||||
struct draw_vertex_info *output_verts,
|
||||
struct draw_prim_info *output_prims );
|
||||
struct draw_prim_info *output_prims);
|
||||
|
||||
void
|
||||
draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
|
||||
|
@ -3601,6 +3601,11 @@ draw_tes_llvm_generate(struct draw_llvm *llvm,
|
||||
system_values.vertices_in = lp_build_broadcast_scalar(&bldvec, patch_vertices_in);
|
||||
|
||||
if (variant->key.primid_needed) {
|
||||
/* In a fragment shader, it (gl_PrimitiveID) will contain the [...] value that would have been
|
||||
* presented as input to the geometry shader had it been present.
|
||||
* https://docs.vulkan.org/spec/latest/chapters/interfaces.html#interfaces-builtin-variables
|
||||
* Store the primitive ID as-if the geometry shader did `gl_PrimitiveID = gl_PrimitiveIDIn`.
|
||||
*/
|
||||
int slot = variant->key.primid_output;
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
outputs[slot][i] = lp_build_alloca(gallivm, lp_build_int_vec_type(gallivm, tes_type), "primid");
|
||||
|
@ -289,6 +289,7 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle,
|
||||
vert_info,
|
||||
prim_info,
|
||||
&vshader->info,
|
||||
NULL,
|
||||
gs_vert_info,
|
||||
gs_prim_info);
|
||||
|
||||
|
@ -575,6 +575,24 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
|
||||
vert_info = &llvm_vert_info;
|
||||
}
|
||||
|
||||
/* Keep track of the patch lengths if we have a geometry shader, this way we can increment
|
||||
* gl_PrimitiveID once per patch, instead of per tessellation output primitive.
|
||||
* The Vulkan and OpenGL specs say:
|
||||
* In a geometry shader, it (gl_PrimitiveID) will contain the number of primitives presented
|
||||
* as input to the shader since the current set of rendering primitives was started.
|
||||
* This sounds like gl_PrimitiveID will be the index of each output primitive from the
|
||||
* tessellation shader, so multiple per patch. But drivers implement the more specific language
|
||||
* from ARB_tessellation_shader:
|
||||
* In geometry language the input variable gl_PrimitiveIDIn behaves identically to the
|
||||
* tessellation control and evaluation shader input variable gl_PrimitiveID.
|
||||
* Which implies on primitive index per patch. DirectX is also more specific:
|
||||
* The geometry-shader stage can consume the SV_PrimitiveID system-generated value that is
|
||||
* auto-generated by the IA. This allows per-primitive data to be fetched or computed if desired.
|
||||
* The input-assembler (IA) stage happens before the tessellation, so we would expect one index
|
||||
* per patch.
|
||||
*/
|
||||
uint32_t *patch_lengths = NULL;
|
||||
|
||||
if (opt & PT_SHADE) {
|
||||
struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
|
||||
if (tcs_shader) {
|
||||
@ -602,7 +620,9 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
|
||||
prim_info,
|
||||
tcs_shader ? &tcs_shader->info : &vshader->info,
|
||||
&tes_vert_info,
|
||||
&tes_prim_info, &tes_elts_out);
|
||||
&tes_prim_info,
|
||||
gshader ? &patch_lengths : NULL,
|
||||
&tes_elts_out);
|
||||
|
||||
FREE(vert_info->verts);
|
||||
vert_info = &tes_vert_info;
|
||||
@ -631,6 +651,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
|
||||
vert_info,
|
||||
prim_info,
|
||||
tes_shader ? &tes_shader->info : &vshader->info,
|
||||
tes_shader ? &patch_lengths : NULL,
|
||||
gs_vert_info,
|
||||
gs_prim_info);
|
||||
|
||||
@ -706,9 +727,14 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
|
||||
}
|
||||
|
||||
FREE(vert_info->verts);
|
||||
if (gshader && gshader->num_vertex_streams > 1)
|
||||
if (gshader && gshader->num_vertex_streams > 1) {
|
||||
for (unsigned i = 1; i < gshader->num_vertex_streams; i++)
|
||||
FREE(gs_vert_info[i].verts);
|
||||
}
|
||||
|
||||
if (patch_lengths) {
|
||||
FREE(patch_lengths);
|
||||
}
|
||||
|
||||
if (free_prim_info) {
|
||||
FREE(tes_elts_out);
|
||||
|
@ -325,6 +325,7 @@ int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
|
||||
const struct tgsi_shader_info *input_info,
|
||||
struct draw_vertex_info *output_verts,
|
||||
struct draw_prim_info *output_prims,
|
||||
uint32_t **patch_lengths,
|
||||
uint16_t **elts_out)
|
||||
{
|
||||
const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
|
||||
@ -346,6 +347,10 @@ int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
|
||||
output_prims->primitive_lengths = NULL;
|
||||
output_prims->primitive_count = 0;
|
||||
|
||||
if (patch_lengths) {
|
||||
*patch_lengths = MALLOC(input_prim->primitive_count * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
shader->input = input;
|
||||
shader->input_vertex_stride = input_stride;
|
||||
shader->input_info = input_info;
|
||||
@ -382,7 +387,7 @@ int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
|
||||
elts = REALLOC(elts, elt_start * sizeof(uint16_t),
|
||||
output_prims->count * sizeof(uint16_t));
|
||||
|
||||
for (unsigned i = 0; i < data.num_indices; i++)
|
||||
for (uint32_t i = 0; i < data.num_indices; i++)
|
||||
elts[elt_start + i] = vert_start + data.indices[i];
|
||||
|
||||
llvm_fetch_tes_input(shader, input_prim, i, num_input_vertices_per_patch);
|
||||
@ -396,10 +401,15 @@ int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
|
||||
}
|
||||
|
||||
uint32_t prim_len = u_prim_vertex_count(output_prims->prim)->min;
|
||||
output_prims->primitive_count += data.num_indices / prim_len;
|
||||
uint32_t prims_per_patch = data.num_indices / prim_len;
|
||||
output_prims->primitive_count += prims_per_patch;
|
||||
if (patch_lengths) {
|
||||
(*patch_lengths)[i] = prims_per_patch;
|
||||
}
|
||||
|
||||
output_prims->primitive_lengths = REALLOC(output_prims->primitive_lengths, prim_start * sizeof(uint32_t),
|
||||
output_prims->primitive_count * sizeof(uint32_t));
|
||||
for (unsigned i = prim_start; i < output_prims->primitive_count; i++) {
|
||||
for (uint32_t i = prim_start; i < output_prims->primitive_count; i++) {
|
||||
output_prims->primitive_lengths[i] = prim_len;
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
|
||||
const struct tgsi_shader_info *input_info,
|
||||
struct draw_vertex_info *output_verts,
|
||||
struct draw_prim_info *output_prims,
|
||||
uint32_t **patch_lengths,
|
||||
uint16_t **elts_out);
|
||||
|
||||
#if DRAW_LLVM_AVAILABLE
|
||||
|
Loading…
Reference in New Issue
Block a user