From 0aeef7c8bd5917633392decce1c07ff36c652cc1 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 29 Jan 2019 15:00:34 -0800 Subject: [PATCH] turnip: add TU_CS_MODE_SUB_STREAM When in TU_CS_MODE_SUB_STREAM, tu_cs_begin_sub_stream (or tu_cs_end_sub_stream) should be called instead of tu_cs_begin (or tu_cs_end). It gives the caller a TU_CS_MODE_EXTERNAL cs to emit commands to. --- src/freedreno/vulkan/tu_cmd_buffer.c | 2 +- src/freedreno/vulkan/tu_cs.c | 64 ++++++++++++++++++++++++++-- src/freedreno/vulkan/tu_cs.h | 11 ++++- src/freedreno/vulkan/tu_private.h | 10 +++++ 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 541a37b6dde..e01de4cf68a 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -736,7 +736,7 @@ tu_create_cmd_buffer(struct tu_device *device, } tu_bo_list_init(&cmd_buffer->bo_list); - tu_cs_init(&cmd_buffer->cs, 4096); + tu_cs_init(&cmd_buffer->cs, TU_CS_MODE_GROW, 4096); *pCommandBuffer = tu_cmd_buffer_to_handle(cmd_buffer); diff --git a/src/freedreno/vulkan/tu_cs.c b/src/freedreno/vulkan/tu_cs.c index 226abb05510..193ae5cc9fe 100644 --- a/src/freedreno/vulkan/tu_cs.c +++ b/src/freedreno/vulkan/tu_cs.c @@ -27,11 +27,13 @@ * Initialize a command stream. */ void -tu_cs_init(struct tu_cs *cs, uint32_t initial_size) +tu_cs_init(struct tu_cs *cs, enum tu_cs_mode mode, uint32_t initial_size) { + assert(mode != TU_CS_MODE_EXTERNAL); + memset(cs, 0, sizeof(*cs)); - cs->mode = TU_CS_MODE_GROW; + cs->mode = mode; cs->next_bo_size = initial_size; } @@ -209,11 +211,12 @@ tu_cs_add_entry(struct tu_cs *cs) /** * Begin (or continue) command packet emission. This does nothing but sanity - * checks currently. + * checks currently. \a cs must not be in TU_CS_MODE_SUB_STREAM mode. */ void tu_cs_begin(struct tu_cs *cs) { + assert(cs->mode != TU_CS_MODE_SUB_STREAM); assert(tu_cs_is_empty(cs)); } @@ -223,10 +226,59 @@ tu_cs_begin(struct tu_cs *cs) void tu_cs_end(struct tu_cs *cs) { + assert(cs->mode != TU_CS_MODE_SUB_STREAM); + if (cs->mode == TU_CS_MODE_GROW && !tu_cs_is_empty(cs)) tu_cs_add_entry(cs); } +/** + * Begin command packet emission to a sub-stream. \a cs must be in + * TU_CS_MODE_SUB_STREAM mode. + * + * Return \a sub_cs which is in TU_CS_MODE_EXTERNAL mode. + */ +VkResult +tu_cs_begin_sub_stream(struct tu_device *dev, + struct tu_cs *cs, + uint32_t size, + struct tu_cs *sub_cs) +{ + assert(cs->mode == TU_CS_MODE_SUB_STREAM); + assert(size); + + VkResult result = tu_cs_reserve_space(dev, cs, size); + if (result != VK_SUCCESS) + return result; + + tu_cs_init_external(sub_cs, cs->cur, cs->reserved_end); + + return VK_SUCCESS; +} + +/** + * End command packet emission to a sub-stream. \a sub_cs becomes invalid + * after this call. + * + * Return an IB entry for the sub-stream. The entry has the same lifetime as + * \a cs. + */ +struct tu_cs_entry +tu_cs_end_sub_stream(struct tu_cs *cs, struct tu_cs *sub_cs) +{ + assert(cs->mode == TU_CS_MODE_SUB_STREAM); + assert(cs->bo_count); + assert(sub_cs->cur >= cs->start && sub_cs->cur <= cs->reserved_end); + + cs->cur = sub_cs->cur; + + return (struct tu_cs_entry) { + .bo = cs->bos[cs->bo_count - 1], + .size = tu_cs_get_size(cs) * sizeof(uint32_t), + .offset = tu_cs_get_offset(cs) * sizeof(uint32_t), + }; +} + /** * Reserve space from a command stream for \a reserved_size uint32_t values. * This never fails when \a cs has mode TU_CS_MODE_EXTERNAL. @@ -243,8 +295,12 @@ tu_cs_reserve_space(struct tu_device *dev, } /* add an entry for the exiting command packets */ - if (!tu_cs_is_empty(cs)) + if (!tu_cs_is_empty(cs)) { + /* no direct command packet for TU_CS_MODE_SUB_STREAM */ + assert(cs->mode != TU_CS_MODE_SUB_STREAM); + tu_cs_add_entry(cs); + } /* switch to a new BO */ uint32_t new_size = MAX2(cs->next_bo_size, reserved_size); diff --git a/src/freedreno/vulkan/tu_cs.h b/src/freedreno/vulkan/tu_cs.h index e7c8a11617a..05e07718504 100644 --- a/src/freedreno/vulkan/tu_cs.h +++ b/src/freedreno/vulkan/tu_cs.h @@ -28,7 +28,7 @@ #include "registers/adreno_pm4.xml.h" void -tu_cs_init(struct tu_cs *cs, uint32_t initial_size); +tu_cs_init(struct tu_cs *cs, enum tu_cs_mode mode, uint32_t initial_size); void tu_cs_init_external(struct tu_cs *cs, uint32_t *start, uint32_t *end); @@ -42,6 +42,15 @@ tu_cs_begin(struct tu_cs *cs); void tu_cs_end(struct tu_cs *cs); +VkResult +tu_cs_begin_sub_stream(struct tu_device *dev, + struct tu_cs *cs, + uint32_t size, + struct tu_cs *sub_cs); + +struct tu_cs_entry +tu_cs_end_sub_stream(struct tu_cs *cs, struct tu_cs *sub_cs); + VkResult tu_cs_reserve_space(struct tu_device *dev, struct tu_cs *cs, diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index af397950a94..5e1835c8ec1 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -477,6 +477,16 @@ enum tu_cs_mode * This mode does not create any entry or any BO. */ TU_CS_MODE_EXTERNAL, + + /* + * A command stream in TU_CS_MODE_SUB_STREAM mode does not support direct + * command packet emission. tu_cs_begin_sub_stream must be called to get a + * sub-stream to emit comamnd packets to. When done with the sub-stream, + * tu_cs_end_sub_stream must be called. + * + * This mode does not create any entry internally. + */ + TU_CS_MODE_SUB_STREAM, }; struct tu_cs -- 2.30.2