From 7997b5f005d4051e84bf64d6d1294f3da5076e5a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 8 Aug 2015 14:02:02 +0200 Subject: [PATCH] winsys/amdgpu: Add support for const IB. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit v2: Use the correct IB to update request (Bas Nieuwenhuizen) v3: Add preamble IB. (Bas Nieuwenhuizen) Reviewed-by: Marek Olšák --- src/gallium/drivers/radeon/radeon_winsys.h | 30 ++++++++ src/gallium/winsys/amdgpu/drm/amdgpu_cs.c | 88 +++++++++++++++++++++- src/gallium/winsys/amdgpu/drm/amdgpu_cs.h | 11 ++- 3 files changed, 124 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h index aa94df69362..451d8a4ec0c 100644 --- a/src/gallium/drivers/radeon/radeon_winsys.h +++ b/src/gallium/drivers/radeon/radeon_winsys.h @@ -602,6 +602,36 @@ struct radeon_winsys { struct pipe_fence_handle **fence), void *flush_ctx); + /** + * Add a constant engine IB to a graphics CS. This makes the graphics CS + * from "cs_create" a group of two IBs that share a buffer list and are + * flushed together. + * + * The returned constant CS is only a stream for writing packets to the new + * IB. Calling other winsys functions with it is not allowed, not even + * "cs_destroy". + * + * In order to add buffers and check memory usage, use the graphics CS. + * In order to flush it, use the graphics CS, which will flush both IBs. + * Destroying the graphics CS will destroy both of them. + * + * \param cs The graphics CS from "cs_create" that will hold the buffer + * list and will be used for flushing. + */ + struct radeon_winsys_cs *(*cs_add_const_ib)(struct radeon_winsys_cs *cs); + + /** + * Add a constant engine preamble IB to a graphics CS. This add an extra IB + * in similar manner to cs_add_const_ib. This should always be called after + * cs_add_const_ib. + * + * The returned IB is a constant engine IB that only gets flushed if the + * context changed. + * + * \param cs The graphics CS from "cs_create" that will hold the buffer + * list and will be used for flushing. + */ + struct radeon_winsys_cs *(*cs_add_const_preamble_ib)(struct radeon_winsys_cs *cs); /** * Destroy a command stream. * diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c index b0fe8b91b1c..01826603912 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c @@ -350,19 +350,62 @@ amdgpu_cs_create(struct radeon_winsys_ctx *rwctx, return NULL; } - if (!amdgpu_get_new_ib(&ctx->ws->base, &cs->main, &cs->ib)) { + if (!amdgpu_get_new_ib(&ctx->ws->base, &cs->main, &cs->ib[IB_MAIN])) { amdgpu_destroy_cs_context(cs); FREE(cs); return NULL; } cs->request.number_of_ibs = 1; - cs->request.ibs = &cs->ib; + cs->request.ibs = &cs->ib[IB_MAIN]; p_atomic_inc(&ctx->ws->num_cs); return &cs->main.base; } +static struct radeon_winsys_cs * +amdgpu_cs_add_const_ib(struct radeon_winsys_cs *rcs) +{ + struct amdgpu_cs *cs = (struct amdgpu_cs*)rcs; + struct amdgpu_winsys *ws = cs->ctx->ws; + + /* only one const IB can be added */ + if (cs->ring_type != RING_GFX || cs->const_ib.ib_mapped) + return NULL; + + if (!amdgpu_get_new_ib(&ws->base, &cs->const_ib, &cs->ib[IB_CONST])) + return NULL; + + cs->request.number_of_ibs = 2; + cs->request.ibs = &cs->ib[IB_CONST]; + cs->ib[IB_CONST].flags = AMDGPU_IB_FLAG_CE; + + return &cs->const_ib.base; +} + +static struct radeon_winsys_cs * +amdgpu_cs_add_const_preamble_ib(struct radeon_winsys_cs *rcs) +{ + struct amdgpu_cs *cs = (struct amdgpu_cs*)rcs; + struct amdgpu_winsys *ws = cs->ctx->ws; + + /* only one const preamble IB can be added and only when the const IB has + * also been mapped */ + if (cs->ring_type != RING_GFX || !cs->const_ib.ib_mapped || + cs->const_preamble_ib.ib_mapped) + return NULL; + + if (!amdgpu_get_new_ib(&ws->base, &cs->const_preamble_ib, + &cs->ib[IB_CONST_PREAMBLE], IB_CONST_PREAMBLE)) + return NULL; + + cs->request.number_of_ibs = 3; + cs->request.ibs = &cs->ib[IB_CONST_PREAMBLE]; + cs->ib[IB_CONST_PREAMBLE].flags = AMDGPU_IB_FLAG_CE | AMDGPU_IB_FLAG_PREAMBLE; + + return &cs->const_preamble_ib.base; +} + #define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value) int amdgpu_lookup_buffer(struct amdgpu_cs *cs, struct amdgpu_winsys_bo *bo) @@ -621,6 +664,15 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs, /* pad GFX ring to 8 DWs to meet CP fetch alignment requirements */ while (rcs->cdw & 7) OUT_CS(rcs, 0xffff1000); /* type3 nop packet */ + + /* Also pad the const IB. */ + if (cs->const_ib.ib_mapped) + while (!cs->const_ib.base.cdw || (cs->const_ib.base.cdw & 7)) + OUT_CS(&cs->const_ib.base, 0xffff1000); /* type3 nop packet */ + + if (cs->const_preamble_ib.ib_mapped) + while (!cs->const_preamble_ib.base.cdw || (cs->const_preamble_ib.base.cdw & 7)) + OUT_CS(&cs->const_preamble_ib.base, 0xffff1000); break; case RING_UVD: while (rcs->cdw & 15) @@ -637,6 +689,14 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs, amdgpu_cs_add_buffer(rcs, cs->main.big_ib_buffer, RADEON_USAGE_READ, 0, RADEON_PRIO_IB1); + if (cs->const_ib.ib_mapped) + amdgpu_cs_add_buffer(rcs, cs->const_ib.big_ib_buffer, + RADEON_USAGE_READ, 0, RADEON_PRIO_IB1); + + if (cs->const_preamble_ib.ib_mapped) + amdgpu_cs_add_buffer(rcs, cs->const_preamble_ib.big_ib_buffer, + RADEON_USAGE_READ, 0, RADEON_PRIO_IB1); + /* If the CS is not empty or overflowed.... */ if (cs->main.base.cdw && cs->main.base.cdw <= cs->main.base.max_dw && !debug_get_option_noop()) { int r; @@ -677,9 +737,19 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs, goto cleanup; } - cs->ib.size = cs->main.base.cdw; + cs->ib[IB_MAIN].size = cs->main.base.cdw; cs->main.used_ib_space += cs->main.base.cdw * 4; + if (cs->const_ib.ib_mapped) { + cs->ib[IB_CONST].size = cs->const_ib.base.cdw; + cs->const_ib.used_ib_space += cs->const_ib.base.cdw * 4; + } + + if (cs->const_preamble_ib.ib_mapped) { + cs->ib[IB_CONST_PREAMBLE].size = cs->const_preamble_ib.base.cdw; + cs->const_preamble_ib.used_ib_space += cs->const_preamble_ib.base.cdw * 4; + } + amdgpu_cs_do_submission(cs, fence); /* Cleanup. */ @@ -689,7 +759,13 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs, cleanup: amdgpu_cs_context_cleanup(cs); - amdgpu_get_new_ib(&ws->base, &cs->main, &cs->ib); + + amdgpu_get_new_ib(&ws->base, &cs->main, &cs->ib[IB_MAIN]); + if (cs->const_ib.ib_mapped) + amdgpu_get_new_ib(&ws->base, &cs->const_ib, &cs->ib[IB_CONST]); + if (cs->const_preamble_ib.ib_mapped) + amdgpu_get_new_ib(&ws->base, &cs->const_preamble_ib, + &cs->ib[IB_CONST_PREAMBLE]); ws->num_cs_flushes++; } @@ -701,6 +777,8 @@ static void amdgpu_cs_destroy(struct radeon_winsys_cs *rcs) amdgpu_destroy_cs_context(cs); p_atomic_dec(&cs->ctx->ws->num_cs); pb_reference(&cs->main.big_ib_buffer, NULL); + pb_reference(&cs->const_ib.big_ib_buffer, NULL); + pb_reference(&cs->const_preamble_ib.big_ib_buffer, NULL); FREE(cs); } @@ -720,6 +798,8 @@ void amdgpu_cs_init_functions(struct amdgpu_winsys *ws) ws->base.ctx_destroy = amdgpu_ctx_destroy; ws->base.ctx_query_reset_status = amdgpu_ctx_query_reset_status; ws->base.cs_create = amdgpu_cs_create; + ws->base.cs_add_const_ib = amdgpu_cs_add_const_ib; + ws->base.cs_add_const_preamble_ib = amdgpu_cs_add_const_preamble_ib; ws->base.cs_destroy = amdgpu_cs_destroy; ws->base.cs_add_buffer = amdgpu_cs_add_buffer; ws->base.cs_lookup_buffer = amdgpu_cs_lookup_buffer; diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h index 888b85b77b1..4ed830b34b7 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h @@ -59,8 +59,17 @@ struct amdgpu_ib { unsigned used_ib_space; }; +enum { + IB_CONST_PREAMBLE = 0, + IB_CONST = 1, /* the const IB must be first */ + IB_MAIN = 2, + IB_NUM +}; + struct amdgpu_cs { struct amdgpu_ib main; /* must be first because this is inherited */ + struct amdgpu_ib const_ib; /* optional constant engine IB */ + struct amdgpu_ib const_preamble_ib; struct amdgpu_ctx *ctx; /* Flush CS. */ @@ -70,7 +79,7 @@ struct amdgpu_cs { /* amdgpu_cs_submit parameters */ enum ring_type ring_type; struct amdgpu_cs_request request; - struct amdgpu_cs_ib_info ib; + struct amdgpu_cs_ib_info ib[IB_NUM]; /* Buffers. */ unsigned max_num_buffers; -- 2.30.2