summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan A. Suarez Romero <jasuarez@igalia.com>2023-04-26 16:17:27 +0200
committerMarge Bot <emma+marge@anholt.net>2023-05-16 20:39:43 +0000
commit975a2c17a4e8cfd235dddd4c06e0dc49ab7504b3 (patch)
tree541c7ee2120d27337ddd0517d6f4fca6047e7373
parentb4c4d2826306541ba1dd2145cb30c9fcd3e213a5 (diff)
downloadmesa-975a2c17a4e8cfd235dddd4c06e0dc49ab7504b3.tar.gz
v3d: delay offset/counter values with primitive restart
Some values like the transform feedback offset or the number of output vertices in VS can be obtained knowing how many vertices and primitive type are used in the drawcall. But when the primitive restart is enabled, doing this is quite more complex, as we should parse the vertex buffer to know where is the restart values, and so on. In this case, delay this computation after the drawcall is executed, by querying the GPU to know these values. Similarly, this delay is also applied to compute the transform feedback buffer offsets when there is a geometry shader, as we don't know beforehand how many vertices it is going to output. This fixes `spec@!opengl 3.1@primitive-restart-xfb flush` and `spec@!opengl 3.1@primitive-restart-xfb generated`. Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> Signed-off-by: Juan A. Suarez Romero <jasuarez@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22716>
-rw-r--r--src/broadcom/ci/broadcom-rpi4-fails.txt2
-rw-r--r--src/gallium/drivers/v3d/v3d_context.h1
-rw-r--r--src/gallium/drivers/v3d/v3d_job.c18
-rw-r--r--src/gallium/drivers/v3d/v3dx_draw.c16
4 files changed, 28 insertions, 9 deletions
diff --git a/src/broadcom/ci/broadcom-rpi4-fails.txt b/src/broadcom/ci/broadcom-rpi4-fails.txt
index de59f844495..7d5a2053c77 100644
--- a/src/broadcom/ci/broadcom-rpi4-fails.txt
+++ b/src/broadcom/ci/broadcom-rpi4-fails.txt
@@ -98,8 +98,6 @@ spec@!opengl 2.0@gl-2.0-edgeflag-immediate,Fail
spec@!opengl 2.1@pbo,Fail
spec@!opengl 2.1@pbo@test_polygon_stip,Fail
spec@!opengl 2.1@polygon-stipple-fs,Fail
-spec@!opengl 3.1@primitive-restart-xfb flush,Fail
-spec@!opengl 3.1@primitive-restart-xfb generated,Fail
spec@arb_color_buffer_float@gl_rgba32f-render,Fail
spec@arb_color_buffer_float@gl_rgba32f-render-fog,Fail
spec@arb_color_buffer_float@gl_rgba32f-render-sanity,Fail
diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h
index 7f62fbaf223..b4663b35ff6 100644
--- a/src/gallium/drivers/v3d/v3d_context.h
+++ b/src/gallium/drivers/v3d/v3d_context.h
@@ -600,6 +600,7 @@ struct v3d_context {
uint32_t tf_prims_generated;
uint32_t prims_generated;
+ bool prim_restart;
uint32_t n_primitives_generated_queries_in_flight;
diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c
index b4957054b9b..10c7861d8ce 100644
--- a/src/gallium/drivers/v3d/v3d_job.c
+++ b/src/gallium/drivers/v3d/v3d_job.c
@@ -35,6 +35,7 @@
#include "util/hash_table.h"
#include "util/ralloc.h"
#include "util/set.h"
+#include "util/u_prim.h"
#include "broadcom/clif/clif_dump.h"
void
@@ -466,11 +467,22 @@ v3d_read_and_accumulate_primitive_counters(struct v3d_context *v3d)
if (v3d_bo_wait(rsc->bo, PIPE_TIMEOUT_INFINITE, "prim-counts")) {
uint32_t *map = v3d_bo_map(rsc->bo) + v3d->prim_counts_offset;
v3d->tf_prims_generated += map[V3D_PRIM_COUNTS_TF_WRITTEN];
- /* When we only have a vertex shader we determine the primitive
- * count in the CPU so don't update it here again.
+ /* When we only have a vertex shader with no primitive
+ * restart, we determine the primitive count in the CPU so
+ * don't update it here again.
*/
- if (v3d->prog.gs)
+ if (v3d->prog.gs || v3d->prim_restart) {
v3d->prims_generated += map[V3D_PRIM_COUNTS_WRITTEN];
+ uint8_t prim_mode =
+ v3d->prog.gs ? v3d->prog.gs->prog_data.gs->out_prim_type
+ : v3d->prim_mode;
+ uint32_t vertices_written =
+ map[V3D_PRIM_COUNTS_TF_WRITTEN] * u_vertices_per_prim(prim_mode);
+ for (int i = 0; i < v3d->streamout.num_targets; i++) {
+ v3d_stream_output_target(v3d->streamout.targets[i])->offset +=
+ vertices_written;
+ }
+ }
}
}
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index ae9026a6fae..503475f6832 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -1131,7 +1131,9 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
prim_tf_enable = (V3D_PRIM_POINTS_TF - V3D_PRIM_POINTS);
#endif
- if (!v3d->prog.gs)
+ v3d->prim_restart = info->primitive_restart;
+
+ if (!v3d->prog.gs && !v3d->prim_restart)
v3d_update_primitives_generated_counter(v3d, info, &draws[0]);
uint32_t hw_prim_type = v3d_hw_prim_type(info->mode);
@@ -1258,10 +1260,16 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
/* Increment the TF offsets by how many verts we wrote. XXX: This
* needs some clamping to the buffer size.
+ *
+ * If primitive restart is enabled or we have a geometry shader, we
+ * update it later, when we can query the device to know how many
+ * vertices were written.
*/
- for (int i = 0; i < v3d->streamout.num_targets; i++)
- v3d_stream_output_target(v3d->streamout.targets[i])->offset +=
- u_stream_outputs_for_vertices(info->mode, draws[0].count);
+ if (!v3d->prog.gs && !v3d->prim_restart) {
+ for (int i = 0; i < v3d->streamout.num_targets; i++)
+ v3d_stream_output_target(v3d->streamout.targets[i])->offset +=
+ u_stream_outputs_for_vertices(info->mode, draws[0].count);
+ }
if (v3d->zsa && job->zsbuf && v3d->zsa->base.depth_enabled) {
struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture);