From 2de15273d5b332eb116841cab546464236dffc1d Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Mon, 28 Feb 2022 14:45:19 -0800 Subject: [PATCH] freedreno: Improve robustness behavior for VBs with offset > size. We were just emitting the bad reloc (either an assert fail on a debug build or for a release build likely a GPU hang from the resulting fault). Given that the GLES 3.2 spec's robust context requirement says we should return undefined data but not terminate for element indices outside of the VB, ignoring the offset in this case seems like a better behavior to have in all cases. Part-of: --- src/gallium/drivers/freedreno/a3xx/fd3_emit.c | 9 --------- src/gallium/drivers/freedreno/a4xx/fd4_emit.c | 8 -------- src/gallium/drivers/freedreno/a5xx/fd5_emit.c | 8 -------- src/gallium/drivers/freedreno/freedreno_state.c | 8 ++++++++ 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 6a1b3960f7a..b06727cdec8 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -424,15 +424,6 @@ fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd3_emit *emit) uint32_t off = vb->buffer_offset + elem->src_offset; uint32_t fs = util_format_get_blocksize(pfmt); -#ifdef DEBUG - /* see - * dEQP-GLES31.stress.vertex_attribute_binding.buffer_bounds.bind_vertex_buffer_offset_near_wrap_10 - * should mesa/st be protecting us from this? - */ - if (off > fd_bo_size(rsc->bo)) - continue; -#endif - debug_assert(fmt != VFMT_NONE); OUT_PKT0(ring, REG_A3XX_VFD_FETCH(j), 2); diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index 7fc96ead832..066fd5db38d 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -431,14 +431,6 @@ fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit) uint32_t size = vb->buffer.resource->width0 - off; debug_assert(fmt != VFMT4_NONE); -#ifdef DEBUG - /* see - * dEQP-GLES31.stress.vertex_attribute_binding.buffer_bounds.bind_vertex_buffer_offset_near_wrap_10 - */ - if (off > fd_bo_size(rsc->bo)) - continue; -#endif - OUT_PKT0(ring, REG_A4XX_VFD_FETCH(j), 4); OUT_RING(ring, A4XX_VFD_FETCH_INSTR_0_FETCHSIZE(fs - 1) | A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(vb->stride) | diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c index 3cb1f977eb8..5caaf9d5d5f 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c @@ -490,14 +490,6 @@ fd5_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd5_emit *emit) uint32_t size = vb->buffer.resource->width0 - off; debug_assert(fmt != VFMT5_NONE); -#ifdef DEBUG - /* see - * dEQP-GLES31.stress.vertex_attribute_binding.buffer_bounds.bind_vertex_buffer_offset_near_wrap_10 - */ - if (off > fd_bo_size(rsc->bo)) - continue; -#endif - OUT_PKT4(ring, REG_A5XX_VFD_FETCH(j), 4); OUT_RELOC(ring, rsc->bo, off, 0, 0); OUT_RING(ring, size); /* VFD_FETCH[j].SIZE */ diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index aa9b33793ab..d932af09c1b 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -405,6 +405,14 @@ fd_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, for (unsigned i = 0; i < count; i++) { assert(!vb[i].is_user_buffer); fd_resource_set_usage(vb[i].buffer.resource, FD_DIRTY_VTXBUF); + + /* Robust buffer access: Return undefined data (the start of the buffer) + * instead of process termination or a GPU hang in case of overflow. + */ + if (vb[i].buffer.resource && + unlikely(vb[i].buffer_offset >= vb[i].buffer.resource->width0)) { + so->vb[start_slot + i].buffer_offset = 0; + } } }