summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-02-20 10:46:13 +0100
committerEmil Velikov <emil.l.velikov@gmail.com>2017-03-15 14:39:55 +0000
commit5c1a970aa10a4396e2e534bbc4144cf931e1a7c5 (patch)
tree884678b6030c0d1e33115fa6301987d0ab768817 /src/gallium
parentf9673f8213ad5790a5219c5562f3b828ff793d10 (diff)
radeonsi: handle MultiDrawIndirect in si_get_draw_start_count
Also handle the GL_ARB_indirect_parameters case where the count itself is in a buffer. Use transfers rather than mapping the buffers directly. This anticipates the possibility that the buffers are sparse (once ARB_sparse_buffer is implemented), in which case they cannot be mapped directly. Fixes GL45-CTS.gtf43.GL3Tests.multi_draw_indirect.multi_draw_indirect_type on <= CIK. v2: - unmap the indirect buffer correctly - handle the corner case where we have indirect draws, but all of them have count 0. Cc: mesa-stable@lists.freedesktop.org Reviewed-by: Marek Olšák <marek.olsak@amd.com> Acked-by: Edward O'Callaghan <funfunctor@folklore1984.net> (cherry picked from commit 6a1d9684f4ec1e1eed49bc14749be7b7784277ec)
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/radeonsi/si_state_draw.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index d54eabfe0b9..66d19d9abc9 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -901,13 +901,59 @@ static void si_get_draw_start_count(struct si_context *sctx,
unsigned *start, unsigned *count)
{
if (info->indirect) {
- struct r600_resource *indirect =
- (struct r600_resource*)info->indirect;
- int *data = r600_buffer_map_sync_with_rings(&sctx->b,
- indirect, PIPE_TRANSFER_READ);
- data += info->indirect_offset/sizeof(int);
- *start = data[2];
- *count = data[0];
+ unsigned indirect_count;
+ struct pipe_transfer *transfer;
+ unsigned begin, end;
+ unsigned map_size;
+ unsigned *data;
+
+ if (info->indirect_params) {
+ data = pipe_buffer_map_range(&sctx->b.b,
+ info->indirect_params,
+ info->indirect_params_offset,
+ sizeof(unsigned),
+ PIPE_TRANSFER_READ, &transfer);
+
+ indirect_count = *data;
+
+ pipe_buffer_unmap(&sctx->b.b, transfer);
+ } else {
+ indirect_count = info->indirect_count;
+ }
+
+ if (!indirect_count) {
+ *start = *count = 0;
+ return;
+ }
+
+ map_size = (indirect_count - 1) * info->indirect_stride + 3 * sizeof(unsigned);
+ data = pipe_buffer_map_range(&sctx->b.b, info->indirect,
+ info->indirect_offset, map_size,
+ PIPE_TRANSFER_READ, &transfer);
+
+ begin = UINT_MAX;
+ end = 0;
+
+ for (unsigned i = 0; i < indirect_count; ++i) {
+ unsigned count = data[0];
+ unsigned start = data[2];
+
+ if (count > 0) {
+ begin = MIN2(begin, start);
+ end = MAX2(end, start + count);
+ }
+
+ data += info->indirect_stride / sizeof(unsigned);
+ }
+
+ pipe_buffer_unmap(&sctx->b.b, transfer);
+
+ if (begin < end) {
+ *start = begin;
+ *count = end - begin;
+ } else {
+ *start = *count = 0;
+ }
} else {
*start = info->start;
*count = info->count;