From: Kenneth Graunke Date: Wed, 21 Nov 2018 08:06:46 +0000 (-0800) Subject: iris: Do the 48-bit vertex buffer address invalidation workaround X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5dbd6df9f7dd9c51c27795d3ee98489a8683649b;p=mesa.git iris: Do the 48-bit vertex buffer address invalidation workaround --- diff --git a/src/gallium/drivers/iris/iris_blorp.c b/src/gallium/drivers/iris/iris_blorp.c index b474e1032ff..6f359bb5cb9 100644 --- a/src/gallium/drivers/iris/iris_blorp.c +++ b/src/gallium/drivers/iris/iris_blorp.c @@ -188,15 +188,14 @@ blorp_alloc_vertex_buffer(struct blorp_batch *blorp_batch, } /** - * See vf_invalidate_for_vb_48b_transitions in iris_state.c. - * XXX: actually add this + * See iris_upload_render_state's IRIS_DIRTY_VERTEX_BUFFERS handling for + * a comment about why these VF invalidations are needed. */ static void -blorp_vf_invalidate_for_vb_48b_transitions(struct blorp_batch *batch, +blorp_vf_invalidate_for_vb_48b_transitions(struct blorp_batch *blorp_batch, const struct blorp_address *addrs, unsigned num_vbs) { -#if 0 struct iris_context *ice = blorp_batch->blorp->driver_ctx; struct iris_batch *batch = blorp_batch->driver_batch; bool need_invalidate = false; @@ -214,7 +213,6 @@ blorp_vf_invalidate_for_vb_48b_transitions(struct blorp_batch *batch, if (need_invalidate) { iris_emit_pipe_control_flush(batch, PIPE_CONTROL_VF_CACHE_INVALIDATE); } -#endif } static struct blorp_address diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 3eb50238b0c..42adbf60d4e 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -482,6 +482,10 @@ struct iris_context { struct iris_border_color_pool border_color_pool; + /** The high 16-bits of the last VBO/index buffer addresses */ + uint16_t last_vbo_high_bits[33]; + uint16_t last_index_bo_high_bits; + /** * Resources containing streamed state which our render context * currently points to. Used to re-add these to the validation diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 075753b170f..7c898a6cd85 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -4337,14 +4337,39 @@ iris_upload_dirty_render_state(struct iris_context *ice, const unsigned vb_dwords = GENX(VERTEX_BUFFER_STATE_length); if (cso->num_buffers > 0) { - iris_batch_emit(batch, cso->vertex_buffers, sizeof(uint32_t) * - (1 + vb_dwords * cso->num_buffers)); + /* The VF cache designers cut corners, and made the cache key's + * tuple only consider the bottom + * 32 bits of the address. If you have two vertex buffers which get + * placed exactly 4 GiB apart and use them in back-to-back draw calls, + * you can get collisions (even within a single batch). + * + * So, we need to do a VF cache invalidate if the buffer for a VB + * slot slot changes [48:32] address bits from the previous time. + */ + bool need_invalidate = false; for (unsigned i = 0; i < cso->num_buffers; i++) { + uint16_t high_bits = 0; + struct iris_resource *res = (void *) cso->resources[i]; - if (res) + if (res) { iris_use_pinned_bo(batch, res->bo, false); + + high_bits = res->bo->gtt_offset >> 32ull; + if (high_bits != ice->state.last_vbo_high_bits[i]) { + need_invalidate = true; + ice->state.last_vbo_high_bits[i] = high_bits; + } + } } + + if (need_invalidate) { + iris_emit_pipe_control_flush(batch, + PIPE_CONTROL_VF_CACHE_INVALIDATE); + } + + iris_batch_emit(batch, cso->vertex_buffers, sizeof(uint32_t) * + (1 + vb_dwords * cso->num_buffers)); } } @@ -4424,6 +4449,13 @@ iris_upload_render_state(struct iris_context *ice, ib.BufferSize = bo->size; ib.BufferStartingAddress = ro_bo(bo, offset); } + + /* The VF cache key only uses 32-bits, see vertex buffer comment above */ + uint16_t high_bits = bo->gtt_offset >> 32ull; + if (high_bits != ice->state.last_index_bo_high_bits) { + iris_emit_pipe_control_flush(batch, PIPE_CONTROL_VF_CACHE_INVALIDATE); + ice->state.last_index_bo_high_bits = high_bits; + } } #define _3DPRIM_END_OFFSET 0x2420