diff options
author | Nicolai Hähnle <[email protected]> | 2017-02-20 10:46:13 +0100 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2017-03-01 13:34:41 +0000 |
commit | 7cb353520d89e264e97b193b6f8a1710e378d33c (patch) | |
tree | d0462eb722d84103a06c54b060b2ded96d369161 /src/gallium/drivers | |
parent | c47f1d6350c5902d018f9ded484aff31e31e12be (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: [email protected]
Reviewed-by: Marek Olšák <[email protected]>
Acked-by: Edward O'Callaghan <[email protected]>
(cherry picked from commit 6a1d9684f4ec1e1eed49bc14749be7b7784277ec)
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_draw.c | 60 |
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 2ea11689ebf..51323686300 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -906,13 +906,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; |