From f59c3814232d5735aba6bed9de506e59321e4170 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 28 Jan 2019 14:33:20 -0800 Subject: [PATCH] turnip: add tu_cs_mode Add tu_cs_mode and TU_CS_MODE_EXTERNAL. When in TU_CS_MODE_EXTERNAL, tu_cs wraps an external buffer and can not grow. This also moves tu_cs* up in tu_private.h, such that other structs can embed tu_cs_entry. --- src/freedreno/vulkan/tu_cs.c | 45 ++++++++++++++++-- src/freedreno/vulkan/tu_cs.h | 5 ++ src/freedreno/vulkan/tu_private.h | 78 ++++++++++++++++++++----------- 3 files changed, 98 insertions(+), 30 deletions(-) diff --git a/src/freedreno/vulkan/tu_cs.c b/src/freedreno/vulkan/tu_cs.c index f4bec106934..226abb05510 100644 --- a/src/freedreno/vulkan/tu_cs.c +++ b/src/freedreno/vulkan/tu_cs.c @@ -31,9 +31,23 @@ tu_cs_init(struct tu_cs *cs, uint32_t initial_size) { memset(cs, 0, sizeof(*cs)); + cs->mode = TU_CS_MODE_GROW; cs->next_bo_size = initial_size; } +/** + * Initialize a command stream as a wrapper to an external buffer. + */ +void +tu_cs_init_external(struct tu_cs *cs, uint32_t *start, uint32_t *end) +{ + memset(cs, 0, sizeof(*cs)); + + cs->mode = TU_CS_MODE_EXTERNAL; + cs->start = cs->reserved_end = cs->cur = start; + cs->end = end; +} + /** * Finish and release all resources owned by a command stream. */ @@ -96,6 +110,9 @@ tu_cs_is_empty(const struct tu_cs *cs) static VkResult tu_cs_add_bo(struct tu_device *dev, struct tu_cs *cs, uint32_t size) { + /* no BO for TU_CS_MODE_EXTERNAL */ + assert(cs->mode != TU_CS_MODE_EXTERNAL); + /* no dangling command packet */ assert(tu_cs_is_empty(cs)); @@ -142,6 +159,9 @@ tu_cs_add_bo(struct tu_device *dev, struct tu_cs *cs, uint32_t size) static VkResult tu_cs_reserve_entry(struct tu_device *dev, struct tu_cs *cs) { + /* entries are only for TU_CS_MODE_GROW */ + assert(cs->mode == TU_CS_MODE_GROW); + /* grow cs->entries if needed */ if (cs->entry_count == cs->entry_capacity) { uint32_t new_capacity = MAX2(4, cs->entry_capacity * 2); @@ -164,6 +184,9 @@ tu_cs_reserve_entry(struct tu_device *dev, struct tu_cs *cs) static void tu_cs_add_entry(struct tu_cs *cs) { + /* entries are only for TU_CS_MODE_GROW */ + assert(cs->mode == TU_CS_MODE_GROW); + /* disallow empty entry */ assert(!tu_cs_is_empty(cs)); @@ -200,12 +223,13 @@ tu_cs_begin(struct tu_cs *cs) void tu_cs_end(struct tu_cs *cs) { - if (!tu_cs_is_empty(cs)) + if (cs->mode == TU_CS_MODE_GROW && !tu_cs_is_empty(cs)) tu_cs_add_entry(cs); } /** * 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. */ VkResult tu_cs_reserve_space(struct tu_device *dev, @@ -213,6 +237,11 @@ tu_cs_reserve_space(struct tu_device *dev, uint32_t reserved_size) { if (tu_cs_get_space(cs) < reserved_size) { + if (cs->mode == TU_CS_MODE_EXTERNAL) { + unreachable("cannot grow external buffer"); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + /* add an entry for the exiting command packets */ if (!tu_cs_is_empty(cs)) tu_cs_add_entry(cs); @@ -228,8 +257,12 @@ tu_cs_reserve_space(struct tu_device *dev, assert(tu_cs_get_space(cs) >= reserved_size); cs->reserved_end = cs->cur + reserved_size; - /* reserve an entry for the next call to this function or tu_cs_end */ - return tu_cs_reserve_entry(dev, cs); + if (cs->mode == TU_CS_MODE_GROW) { + /* reserve an entry for the next call to this function or tu_cs_end */ + return tu_cs_reserve_entry(dev, cs); + } + + return VK_SUCCESS; } /** @@ -239,6 +272,12 @@ tu_cs_reserve_space(struct tu_device *dev, void tu_cs_reset(struct tu_device *dev, struct tu_cs *cs) { + if (cs->mode == TU_CS_MODE_EXTERNAL) { + assert(!cs->bo_count && !cs->entry_count); + cs->reserved_end = cs->cur = cs->start; + return; + } + for (uint32_t i = 0; i + 1 < cs->bo_count; ++i) { tu_bo_finish(dev, cs->bos[i]); free(cs->bos[i]); diff --git a/src/freedreno/vulkan/tu_cs.h b/src/freedreno/vulkan/tu_cs.h index cfac00f200d..e7c8a11617a 100644 --- a/src/freedreno/vulkan/tu_cs.h +++ b/src/freedreno/vulkan/tu_cs.h @@ -30,6 +30,9 @@ void tu_cs_init(struct tu_cs *cs, uint32_t initial_size); +void +tu_cs_init_external(struct tu_cs *cs, uint32_t *start, uint32_t *end); + void tu_cs_finish(struct tu_device *dev, struct tu_cs *cs); @@ -53,6 +56,7 @@ tu_cs_reset(struct tu_device *dev, struct tu_cs *cs); static inline uint32_t tu_cs_get_call_size(const struct tu_cs *cs) { + assert(cs->mode == TU_CS_MODE_GROW); /* each CP_INDIRECT_BUFFER needs 4 dwords */ return cs->entry_count * 4; } @@ -155,6 +159,7 @@ tu_cs_emit_ib(struct tu_cs *cs, const struct tu_cs_entry *entry) static inline void tu_cs_emit_call(struct tu_cs *cs, const struct tu_cs *target) { + assert(target->mode == TU_CS_MODE_GROW); for (uint32_t i = 0; i < target->entry_count; i++) tu_cs_emit_ib(cs, target->entries + i); } diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 205d5c0f13f..af397950a94 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -447,6 +447,57 @@ tu_bo_finish(struct tu_device *dev, struct tu_bo *bo); VkResult tu_bo_map(struct tu_device *dev, struct tu_bo *bo); +struct tu_cs_entry +{ + /* No ownership */ + const struct tu_bo *bo; + + uint32_t size; + uint64_t offset; +}; + +enum tu_cs_mode +{ + + /* + * A command stream in TU_CS_MODE_GROW mode grows automatically whenever it + * is full. tu_cs_begin must be called before command packet emission and + * tu_cs_end must be called after. + * + * This mode may create multiple entries internally. The entries must be + * submitted together. + */ + TU_CS_MODE_GROW, + + /* + * A command stream in TU_CS_MODE_EXTERNAL mode wraps an external, + * fixed-size buffer. tu_cs_begin and tu_cs_end are optional and have no + * effect on it. + * + * This mode does not create any entry or any BO. + */ + TU_CS_MODE_EXTERNAL, +}; + +struct tu_cs +{ + uint32_t *start; + uint32_t *cur; + uint32_t *reserved_end; + uint32_t *end; + + enum tu_cs_mode mode; + uint32_t next_bo_size; + + struct tu_cs_entry *entries; + uint32_t entry_count; + uint32_t entry_capacity; + + struct tu_bo **bos; + uint32_t bo_count; + uint32_t bo_capacity; +}; + struct tu_device_memory { struct tu_bo bo; @@ -768,33 +819,6 @@ tu_bo_list_add(struct tu_bo_list *list, VkResult tu_bo_list_merge(struct tu_bo_list *list, const struct tu_bo_list *other); -struct tu_cs_entry -{ - /* No ownership */ - const struct tu_bo *bo; - - uint32_t size; - uint64_t offset; -}; - -struct tu_cs -{ - uint32_t *start; - uint32_t *cur; - uint32_t *reserved_end; - uint32_t *end; - - uint32_t next_bo_size; - - struct tu_cs_entry *entries; - uint32_t entry_count; - uint32_t entry_capacity; - - struct tu_bo **bos; - uint32_t bo_count; - uint32_t bo_capacity; -}; - struct tu_cmd_buffer { VK_LOADER_DATA _loader_data; -- 2.30.2