1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include "avassert.h"
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "vulkan.h"
22cabdff1aSopenharmony_ci#include "vulkan_loader.h"
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#if CONFIG_LIBGLSLANG
25cabdff1aSopenharmony_ci#include "vulkan_glslang.c"
26cabdff1aSopenharmony_ci#elif CONFIG_LIBSHADERC
27cabdff1aSopenharmony_ci#include "vulkan_shaderc.c"
28cabdff1aSopenharmony_ci#endif
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci/* Generic macro for creating contexts which need to keep their addresses
31cabdff1aSopenharmony_ci * if another context is created. */
32cabdff1aSopenharmony_ci#define FN_CREATING(ctx, type, shortname, array, num)                          \
33cabdff1aSopenharmony_cistatic av_always_inline type *create_ ##shortname(ctx *dctx)                   \
34cabdff1aSopenharmony_ci{                                                                              \
35cabdff1aSopenharmony_ci    type **array, *sctx = av_mallocz(sizeof(*sctx));                           \
36cabdff1aSopenharmony_ci    if (!sctx)                                                                 \
37cabdff1aSopenharmony_ci        return NULL;                                                           \
38cabdff1aSopenharmony_ci                                                                               \
39cabdff1aSopenharmony_ci    array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\
40cabdff1aSopenharmony_ci    if (!array) {                                                              \
41cabdff1aSopenharmony_ci        av_free(sctx);                                                         \
42cabdff1aSopenharmony_ci        return NULL;                                                           \
43cabdff1aSopenharmony_ci    }                                                                          \
44cabdff1aSopenharmony_ci                                                                               \
45cabdff1aSopenharmony_ci    dctx->array = array;                                                       \
46cabdff1aSopenharmony_ci    dctx->array[dctx->num++] = sctx;                                           \
47cabdff1aSopenharmony_ci                                                                               \
48cabdff1aSopenharmony_ci    return sctx;                                                               \
49cabdff1aSopenharmony_ci}
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ciconst VkComponentMapping ff_comp_identity_map = {
52cabdff1aSopenharmony_ci    .r = VK_COMPONENT_SWIZZLE_IDENTITY,
53cabdff1aSopenharmony_ci    .g = VK_COMPONENT_SWIZZLE_IDENTITY,
54cabdff1aSopenharmony_ci    .b = VK_COMPONENT_SWIZZLE_IDENTITY,
55cabdff1aSopenharmony_ci    .a = VK_COMPONENT_SWIZZLE_IDENTITY,
56cabdff1aSopenharmony_ci};
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci/* Converts return values to strings */
59cabdff1aSopenharmony_ciconst char *ff_vk_ret2str(VkResult res)
60cabdff1aSopenharmony_ci{
61cabdff1aSopenharmony_ci#define CASE(VAL) case VAL: return #VAL
62cabdff1aSopenharmony_ci    switch (res) {
63cabdff1aSopenharmony_ci    CASE(VK_SUCCESS);
64cabdff1aSopenharmony_ci    CASE(VK_NOT_READY);
65cabdff1aSopenharmony_ci    CASE(VK_TIMEOUT);
66cabdff1aSopenharmony_ci    CASE(VK_EVENT_SET);
67cabdff1aSopenharmony_ci    CASE(VK_EVENT_RESET);
68cabdff1aSopenharmony_ci    CASE(VK_INCOMPLETE);
69cabdff1aSopenharmony_ci    CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
70cabdff1aSopenharmony_ci    CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
71cabdff1aSopenharmony_ci    CASE(VK_ERROR_INITIALIZATION_FAILED);
72cabdff1aSopenharmony_ci    CASE(VK_ERROR_DEVICE_LOST);
73cabdff1aSopenharmony_ci    CASE(VK_ERROR_MEMORY_MAP_FAILED);
74cabdff1aSopenharmony_ci    CASE(VK_ERROR_LAYER_NOT_PRESENT);
75cabdff1aSopenharmony_ci    CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
76cabdff1aSopenharmony_ci    CASE(VK_ERROR_FEATURE_NOT_PRESENT);
77cabdff1aSopenharmony_ci    CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
78cabdff1aSopenharmony_ci    CASE(VK_ERROR_TOO_MANY_OBJECTS);
79cabdff1aSopenharmony_ci    CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
80cabdff1aSopenharmony_ci    CASE(VK_ERROR_FRAGMENTED_POOL);
81cabdff1aSopenharmony_ci    CASE(VK_ERROR_SURFACE_LOST_KHR);
82cabdff1aSopenharmony_ci    CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
83cabdff1aSopenharmony_ci    CASE(VK_SUBOPTIMAL_KHR);
84cabdff1aSopenharmony_ci    CASE(VK_ERROR_OUT_OF_DATE_KHR);
85cabdff1aSopenharmony_ci    CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
86cabdff1aSopenharmony_ci    CASE(VK_ERROR_VALIDATION_FAILED_EXT);
87cabdff1aSopenharmony_ci    CASE(VK_ERROR_INVALID_SHADER_NV);
88cabdff1aSopenharmony_ci    CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
89cabdff1aSopenharmony_ci    CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
90cabdff1aSopenharmony_ci    CASE(VK_ERROR_NOT_PERMITTED_EXT);
91cabdff1aSopenharmony_ci    default: return "Unknown error";
92cabdff1aSopenharmony_ci    }
93cabdff1aSopenharmony_ci#undef CASE
94cabdff1aSopenharmony_ci}
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_civoid ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
97cabdff1aSopenharmony_ci                   VkQueueFlagBits dev_family, int nb_queues)
98cabdff1aSopenharmony_ci{
99cabdff1aSopenharmony_ci    switch (dev_family) {
100cabdff1aSopenharmony_ci    case VK_QUEUE_GRAPHICS_BIT:
101cabdff1aSopenharmony_ci        qf->queue_family = s->hwctx->queue_family_index;
102cabdff1aSopenharmony_ci        qf->actual_queues = s->hwctx->nb_graphics_queues;
103cabdff1aSopenharmony_ci        break;
104cabdff1aSopenharmony_ci    case VK_QUEUE_COMPUTE_BIT:
105cabdff1aSopenharmony_ci        qf->queue_family = s->hwctx->queue_family_comp_index;
106cabdff1aSopenharmony_ci        qf->actual_queues = s->hwctx->nb_comp_queues;
107cabdff1aSopenharmony_ci        break;
108cabdff1aSopenharmony_ci    case VK_QUEUE_TRANSFER_BIT:
109cabdff1aSopenharmony_ci        qf->queue_family = s->hwctx->queue_family_tx_index;
110cabdff1aSopenharmony_ci        qf->actual_queues = s->hwctx->nb_tx_queues;
111cabdff1aSopenharmony_ci        break;
112cabdff1aSopenharmony_ci    case VK_QUEUE_VIDEO_ENCODE_BIT_KHR:
113cabdff1aSopenharmony_ci        qf->queue_family = s->hwctx->queue_family_encode_index;
114cabdff1aSopenharmony_ci        qf->actual_queues = s->hwctx->nb_encode_queues;
115cabdff1aSopenharmony_ci        break;
116cabdff1aSopenharmony_ci    case VK_QUEUE_VIDEO_DECODE_BIT_KHR:
117cabdff1aSopenharmony_ci        qf->queue_family = s->hwctx->queue_family_decode_index;
118cabdff1aSopenharmony_ci        qf->actual_queues = s->hwctx->nb_decode_queues;
119cabdff1aSopenharmony_ci        break;
120cabdff1aSopenharmony_ci    default:
121cabdff1aSopenharmony_ci        av_assert0(0); /* Should never happen */
122cabdff1aSopenharmony_ci    }
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci    if (!nb_queues)
125cabdff1aSopenharmony_ci        qf->nb_queues = qf->actual_queues;
126cabdff1aSopenharmony_ci    else
127cabdff1aSopenharmony_ci        qf->nb_queues = nb_queues;
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    return;
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_civoid ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf)
133cabdff1aSopenharmony_ci{
134cabdff1aSopenharmony_ci    qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues;
135cabdff1aSopenharmony_ci}
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_cistatic int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
138cabdff1aSopenharmony_ci                        VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
139cabdff1aSopenharmony_ci                        VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
140cabdff1aSopenharmony_ci{
141cabdff1aSopenharmony_ci    VkResult ret;
142cabdff1aSopenharmony_ci    int index = -1;
143cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci    VkMemoryAllocateInfo alloc_info = {
146cabdff1aSopenharmony_ci        .sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
147cabdff1aSopenharmony_ci        .pNext           = alloc_extension,
148cabdff1aSopenharmony_ci    };
149cabdff1aSopenharmony_ci
150cabdff1aSopenharmony_ci    /* Align if we need to */
151cabdff1aSopenharmony_ci    if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
152cabdff1aSopenharmony_ci        req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment);
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_ci    alloc_info.allocationSize = req->size;
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci    /* The vulkan spec requires memory types to be sorted in the "optimal"
157cabdff1aSopenharmony_ci     * order, so the first matching type we find will be the best/fastest one */
158cabdff1aSopenharmony_ci    for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
159cabdff1aSopenharmony_ci        /* The memory type must be supported by the requirements (bitfield) */
160cabdff1aSopenharmony_ci        if (!(req->memoryTypeBits & (1 << i)))
161cabdff1aSopenharmony_ci            continue;
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_ci        /* The memory type flags must include our properties */
164cabdff1aSopenharmony_ci        if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags)
165cabdff1aSopenharmony_ci            continue;
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_ci        /* Found a suitable memory type */
168cabdff1aSopenharmony_ci        index = i;
169cabdff1aSopenharmony_ci        break;
170cabdff1aSopenharmony_ci    }
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_ci    if (index < 0) {
173cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
174cabdff1aSopenharmony_ci               req_flags);
175cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
176cabdff1aSopenharmony_ci    }
177cabdff1aSopenharmony_ci
178cabdff1aSopenharmony_ci    alloc_info.memoryTypeIndex = index;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
181cabdff1aSopenharmony_ci                             s->hwctx->alloc, mem);
182cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
183cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
184cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
185cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
186cabdff1aSopenharmony_ci    }
187cabdff1aSopenharmony_ci
188cabdff1aSopenharmony_ci    *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
189cabdff1aSopenharmony_ci
190cabdff1aSopenharmony_ci    return 0;
191cabdff1aSopenharmony_ci}
192cabdff1aSopenharmony_ci
193cabdff1aSopenharmony_ciint ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
194cabdff1aSopenharmony_ci                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
195cabdff1aSopenharmony_ci{
196cabdff1aSopenharmony_ci    int err;
197cabdff1aSopenharmony_ci    VkResult ret;
198cabdff1aSopenharmony_ci    int use_ded_mem;
199cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci    VkBufferCreateInfo buf_spawn = {
202cabdff1aSopenharmony_ci        .sType       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
203cabdff1aSopenharmony_ci        .pNext       = NULL,
204cabdff1aSopenharmony_ci        .usage       = usage,
205cabdff1aSopenharmony_ci        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
206cabdff1aSopenharmony_ci        .size        = size, /* Gets FFALIGNED during alloc if host visible
207cabdff1aSopenharmony_ci                                but should be ok */
208cabdff1aSopenharmony_ci    };
209cabdff1aSopenharmony_ci
210cabdff1aSopenharmony_ci    VkBufferMemoryRequirementsInfo2 req_desc = {
211cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
212cabdff1aSopenharmony_ci    };
213cabdff1aSopenharmony_ci    VkMemoryDedicatedAllocateInfo ded_alloc = {
214cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
215cabdff1aSopenharmony_ci        .pNext = NULL,
216cabdff1aSopenharmony_ci    };
217cabdff1aSopenharmony_ci    VkMemoryDedicatedRequirements ded_req = {
218cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
219cabdff1aSopenharmony_ci    };
220cabdff1aSopenharmony_ci    VkMemoryRequirements2 req = {
221cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
222cabdff1aSopenharmony_ci        .pNext = &ded_req,
223cabdff1aSopenharmony_ci    };
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci    ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf);
226cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
227cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
228cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
229cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
230cabdff1aSopenharmony_ci    }
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_ci    req_desc.buffer = buf->buf;
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci    vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
235cabdff1aSopenharmony_ci
236cabdff1aSopenharmony_ci    /* In case the implementation prefers/requires dedicated allocation */
237cabdff1aSopenharmony_ci    use_ded_mem = ded_req.prefersDedicatedAllocation |
238cabdff1aSopenharmony_ci                  ded_req.requiresDedicatedAllocation;
239cabdff1aSopenharmony_ci    if (use_ded_mem)
240cabdff1aSopenharmony_ci        ded_alloc.buffer = buf->buf;
241cabdff1aSopenharmony_ci
242cabdff1aSopenharmony_ci    err = vk_alloc_mem(s, &req.memoryRequirements, flags,
243cabdff1aSopenharmony_ci                       use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext,
244cabdff1aSopenharmony_ci                       &buf->flags, &buf->mem);
245cabdff1aSopenharmony_ci    if (err)
246cabdff1aSopenharmony_ci        return err;
247cabdff1aSopenharmony_ci
248cabdff1aSopenharmony_ci    ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
249cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
250cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
251cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
252cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
253cabdff1aSopenharmony_ci    }
254cabdff1aSopenharmony_ci
255cabdff1aSopenharmony_ci    return 0;
256cabdff1aSopenharmony_ci}
257cabdff1aSopenharmony_ci
258cabdff1aSopenharmony_ciint ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[],
259cabdff1aSopenharmony_ci                      int nb_buffers, int invalidate)
260cabdff1aSopenharmony_ci{
261cabdff1aSopenharmony_ci    VkResult ret;
262cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
263cabdff1aSopenharmony_ci    VkMappedMemoryRange *inval_list = NULL;
264cabdff1aSopenharmony_ci    int inval_count = 0;
265cabdff1aSopenharmony_ci
266cabdff1aSopenharmony_ci    for (int i = 0; i < nb_buffers; i++) {
267cabdff1aSopenharmony_ci        ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0,
268cabdff1aSopenharmony_ci                            VK_WHOLE_SIZE, 0, (void **)&mem[i]);
269cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
270cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
271cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
272cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
273cabdff1aSopenharmony_ci        }
274cabdff1aSopenharmony_ci    }
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_ci    if (!invalidate)
277cabdff1aSopenharmony_ci        return 0;
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci    for (int i = 0; i < nb_buffers; i++) {
280cabdff1aSopenharmony_ci        const VkMappedMemoryRange ival_buf = {
281cabdff1aSopenharmony_ci            .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
282cabdff1aSopenharmony_ci            .memory = buf[i].mem,
283cabdff1aSopenharmony_ci            .size   = VK_WHOLE_SIZE,
284cabdff1aSopenharmony_ci        };
285cabdff1aSopenharmony_ci        if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
286cabdff1aSopenharmony_ci            continue;
287cabdff1aSopenharmony_ci        inval_list = av_fast_realloc(s->scratch, &s->scratch_size,
288cabdff1aSopenharmony_ci                                     (++inval_count)*sizeof(*inval_list));
289cabdff1aSopenharmony_ci        if (!inval_list)
290cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
291cabdff1aSopenharmony_ci        inval_list[inval_count - 1] = ival_buf;
292cabdff1aSopenharmony_ci    }
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ci    if (inval_count) {
295cabdff1aSopenharmony_ci        ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
296cabdff1aSopenharmony_ci                                               inval_list);
297cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
298cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
299cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
300cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
301cabdff1aSopenharmony_ci        }
302cabdff1aSopenharmony_ci    }
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_ci    return 0;
305cabdff1aSopenharmony_ci}
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ciint ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
308cabdff1aSopenharmony_ci                        int flush)
309cabdff1aSopenharmony_ci{
310cabdff1aSopenharmony_ci    int err = 0;
311cabdff1aSopenharmony_ci    VkResult ret;
312cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
313cabdff1aSopenharmony_ci    VkMappedMemoryRange *flush_list = NULL;
314cabdff1aSopenharmony_ci    int flush_count = 0;
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci    if (flush) {
317cabdff1aSopenharmony_ci        for (int i = 0; i < nb_buffers; i++) {
318cabdff1aSopenharmony_ci            const VkMappedMemoryRange flush_buf = {
319cabdff1aSopenharmony_ci                .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
320cabdff1aSopenharmony_ci                .memory = buf[i].mem,
321cabdff1aSopenharmony_ci                .size   = VK_WHOLE_SIZE,
322cabdff1aSopenharmony_ci            };
323cabdff1aSopenharmony_ci            if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
324cabdff1aSopenharmony_ci                continue;
325cabdff1aSopenharmony_ci            flush_list = av_fast_realloc(s->scratch, &s->scratch_size,
326cabdff1aSopenharmony_ci                                         (++flush_count)*sizeof(*flush_list));
327cabdff1aSopenharmony_ci            if (!flush_list)
328cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
329cabdff1aSopenharmony_ci            flush_list[flush_count - 1] = flush_buf;
330cabdff1aSopenharmony_ci        }
331cabdff1aSopenharmony_ci    }
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_ci    if (flush_count) {
334cabdff1aSopenharmony_ci        ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
335cabdff1aSopenharmony_ci                                          flush_list);
336cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
337cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
338cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
339cabdff1aSopenharmony_ci            err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
340cabdff1aSopenharmony_ci        }
341cabdff1aSopenharmony_ci    }
342cabdff1aSopenharmony_ci
343cabdff1aSopenharmony_ci    for (int i = 0; i < nb_buffers; i++)
344cabdff1aSopenharmony_ci        vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem);
345cabdff1aSopenharmony_ci
346cabdff1aSopenharmony_ci    return err;
347cabdff1aSopenharmony_ci}
348cabdff1aSopenharmony_ci
349cabdff1aSopenharmony_civoid ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
350cabdff1aSopenharmony_ci{
351cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
352cabdff1aSopenharmony_ci
353cabdff1aSopenharmony_ci    if (!buf || !s->hwctx)
354cabdff1aSopenharmony_ci        return;
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    vk->DeviceWaitIdle(s->hwctx->act_dev);
357cabdff1aSopenharmony_ci
358cabdff1aSopenharmony_ci    if (buf->buf != VK_NULL_HANDLE)
359cabdff1aSopenharmony_ci        vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
360cabdff1aSopenharmony_ci    if (buf->mem != VK_NULL_HANDLE)
361cabdff1aSopenharmony_ci        vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
362cabdff1aSopenharmony_ci}
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_ciint ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size,
365cabdff1aSopenharmony_ci                            VkShaderStageFlagBits stage)
366cabdff1aSopenharmony_ci{
367cabdff1aSopenharmony_ci    VkPushConstantRange *pc;
368cabdff1aSopenharmony_ci
369cabdff1aSopenharmony_ci    pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts),
370cabdff1aSopenharmony_ci                                       pl->push_consts_num + 1);
371cabdff1aSopenharmony_ci    if (!pl->push_consts)
372cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ci    pc = &pl->push_consts[pl->push_consts_num++];
375cabdff1aSopenharmony_ci    memset(pc, 0, sizeof(*pc));
376cabdff1aSopenharmony_ci
377cabdff1aSopenharmony_ci    pc->stageFlags = stage;
378cabdff1aSopenharmony_ci    pc->offset = offset;
379cabdff1aSopenharmony_ci    pc->size = size;
380cabdff1aSopenharmony_ci
381cabdff1aSopenharmony_ci    return 0;
382cabdff1aSopenharmony_ci}
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ciFN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num)
385cabdff1aSopenharmony_ciint ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx,
386cabdff1aSopenharmony_ci                          FFVkQueueFamilyCtx *qf)
387cabdff1aSopenharmony_ci{
388cabdff1aSopenharmony_ci    VkResult ret;
389cabdff1aSopenharmony_ci    FFVkExecContext *e;
390cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci    VkCommandPoolCreateInfo cqueue_create = {
393cabdff1aSopenharmony_ci        .sType              = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
394cabdff1aSopenharmony_ci        .flags              = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
395cabdff1aSopenharmony_ci        .queueFamilyIndex   = qf->queue_family,
396cabdff1aSopenharmony_ci    };
397cabdff1aSopenharmony_ci    VkCommandBufferAllocateInfo cbuf_create = {
398cabdff1aSopenharmony_ci        .sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
399cabdff1aSopenharmony_ci        .level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
400cabdff1aSopenharmony_ci        .commandBufferCount = qf->nb_queues,
401cabdff1aSopenharmony_ci    };
402cabdff1aSopenharmony_ci
403cabdff1aSopenharmony_ci    e = create_exec_ctx(s);
404cabdff1aSopenharmony_ci    if (!e)
405cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
406cabdff1aSopenharmony_ci
407cabdff1aSopenharmony_ci    e->qf = qf;
408cabdff1aSopenharmony_ci
409cabdff1aSopenharmony_ci    e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues));
410cabdff1aSopenharmony_ci    if (!e->queues)
411cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
412cabdff1aSopenharmony_ci
413cabdff1aSopenharmony_ci    e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs));
414cabdff1aSopenharmony_ci    if (!e->bufs)
415cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
416cabdff1aSopenharmony_ci
417cabdff1aSopenharmony_ci    /* Create command pool */
418cabdff1aSopenharmony_ci    ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
419cabdff1aSopenharmony_ci                              s->hwctx->alloc, &e->pool);
420cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
421cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
422cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
423cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
424cabdff1aSopenharmony_ci    }
425cabdff1aSopenharmony_ci
426cabdff1aSopenharmony_ci    cbuf_create.commandPool = e->pool;
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    /* Allocate command buffer */
429cabdff1aSopenharmony_ci    ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs);
430cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
431cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
432cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
433cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
434cabdff1aSopenharmony_ci    }
435cabdff1aSopenharmony_ci
436cabdff1aSopenharmony_ci    for (int i = 0; i < qf->nb_queues; i++) {
437cabdff1aSopenharmony_ci        FFVkQueueCtx *q = &e->queues[i];
438cabdff1aSopenharmony_ci        vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family,
439cabdff1aSopenharmony_ci                           i % qf->actual_queues, &q->queue);
440cabdff1aSopenharmony_ci    }
441cabdff1aSopenharmony_ci
442cabdff1aSopenharmony_ci    *ctx = e;
443cabdff1aSopenharmony_ci
444cabdff1aSopenharmony_ci    return 0;
445cabdff1aSopenharmony_ci}
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_civoid ff_vk_discard_exec_deps(FFVkExecContext *e)
448cabdff1aSopenharmony_ci{
449cabdff1aSopenharmony_ci    FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
450cabdff1aSopenharmony_ci
451cabdff1aSopenharmony_ci    for (int j = 0; j < q->nb_buf_deps; j++)
452cabdff1aSopenharmony_ci        av_buffer_unref(&q->buf_deps[j]);
453cabdff1aSopenharmony_ci    q->nb_buf_deps = 0;
454cabdff1aSopenharmony_ci
455cabdff1aSopenharmony_ci    for (int j = 0; j < q->nb_frame_deps; j++)
456cabdff1aSopenharmony_ci        av_frame_free(&q->frame_deps[j]);
457cabdff1aSopenharmony_ci    q->nb_frame_deps = 0;
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_ci    e->sem_wait_cnt = 0;
460cabdff1aSopenharmony_ci    e->sem_sig_cnt = 0;
461cabdff1aSopenharmony_ci}
462cabdff1aSopenharmony_ci
463cabdff1aSopenharmony_ciint ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e)
464cabdff1aSopenharmony_ci{
465cabdff1aSopenharmony_ci    VkResult ret;
466cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
467cabdff1aSopenharmony_ci    FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
468cabdff1aSopenharmony_ci
469cabdff1aSopenharmony_ci    VkCommandBufferBeginInfo cmd_start = {
470cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
471cabdff1aSopenharmony_ci        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
472cabdff1aSopenharmony_ci    };
473cabdff1aSopenharmony_ci
474cabdff1aSopenharmony_ci    /* Create the fence and don't wait for it initially */
475cabdff1aSopenharmony_ci    if (!q->fence) {
476cabdff1aSopenharmony_ci        VkFenceCreateInfo fence_spawn = {
477cabdff1aSopenharmony_ci            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
478cabdff1aSopenharmony_ci        };
479cabdff1aSopenharmony_ci        ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc,
480cabdff1aSopenharmony_ci                              &q->fence);
481cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
482cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Failed to queue frame fence: %s\n",
483cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
484cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
485cabdff1aSopenharmony_ci        }
486cabdff1aSopenharmony_ci    } else {
487cabdff1aSopenharmony_ci        vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
488cabdff1aSopenharmony_ci        vk->ResetFences(s->hwctx->act_dev, 1, &q->fence);
489cabdff1aSopenharmony_ci    }
490cabdff1aSopenharmony_ci
491cabdff1aSopenharmony_ci    /* Discard queue dependencies */
492cabdff1aSopenharmony_ci    ff_vk_discard_exec_deps(e);
493cabdff1aSopenharmony_ci
494cabdff1aSopenharmony_ci    ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start);
495cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
496cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
497cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
498cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
499cabdff1aSopenharmony_ci    }
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    return 0;
502cabdff1aSopenharmony_ci}
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ciVkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e)
505cabdff1aSopenharmony_ci{
506cabdff1aSopenharmony_ci    return e->bufs[e->qf->cur_queue];
507cabdff1aSopenharmony_ci}
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ciint ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame,
510cabdff1aSopenharmony_ci                       VkPipelineStageFlagBits in_wait_dst_flag)
511cabdff1aSopenharmony_ci{
512cabdff1aSopenharmony_ci    AVFrame **dst;
513cabdff1aSopenharmony_ci    AVVkFrame *f = (AVVkFrame *)frame->data[0];
514cabdff1aSopenharmony_ci    FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
515cabdff1aSopenharmony_ci    AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data;
516cabdff1aSopenharmony_ci    int planes = av_pix_fmt_count_planes(fc->sw_format);
517cabdff1aSopenharmony_ci
518cabdff1aSopenharmony_ci    for (int i = 0; i < planes; i++) {
519cabdff1aSopenharmony_ci        e->sem_wait = av_fast_realloc(e->sem_wait, &e->sem_wait_alloc,
520cabdff1aSopenharmony_ci                                      (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait));
521cabdff1aSopenharmony_ci        if (!e->sem_wait) {
522cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
523cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
524cabdff1aSopenharmony_ci        }
525cabdff1aSopenharmony_ci
526cabdff1aSopenharmony_ci        e->sem_wait_dst = av_fast_realloc(e->sem_wait_dst, &e->sem_wait_dst_alloc,
527cabdff1aSopenharmony_ci                                          (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst));
528cabdff1aSopenharmony_ci        if (!e->sem_wait_dst) {
529cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
530cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
531cabdff1aSopenharmony_ci        }
532cabdff1aSopenharmony_ci
533cabdff1aSopenharmony_ci        e->sem_wait_val = av_fast_realloc(e->sem_wait_val, &e->sem_wait_val_alloc,
534cabdff1aSopenharmony_ci                                          (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val));
535cabdff1aSopenharmony_ci        if (!e->sem_wait_val) {
536cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
537cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
538cabdff1aSopenharmony_ci        }
539cabdff1aSopenharmony_ci
540cabdff1aSopenharmony_ci        e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc,
541cabdff1aSopenharmony_ci                                     (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig));
542cabdff1aSopenharmony_ci        if (!e->sem_sig) {
543cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
544cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
545cabdff1aSopenharmony_ci        }
546cabdff1aSopenharmony_ci
547cabdff1aSopenharmony_ci        e->sem_sig_val = av_fast_realloc(e->sem_sig_val, &e->sem_sig_val_alloc,
548cabdff1aSopenharmony_ci                                         (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val));
549cabdff1aSopenharmony_ci        if (!e->sem_sig_val) {
550cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
551cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
552cabdff1aSopenharmony_ci        }
553cabdff1aSopenharmony_ci
554cabdff1aSopenharmony_ci        e->sem_sig_val_dst = av_fast_realloc(e->sem_sig_val_dst, &e->sem_sig_val_dst_alloc,
555cabdff1aSopenharmony_ci                                             (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst));
556cabdff1aSopenharmony_ci        if (!e->sem_sig_val_dst) {
557cabdff1aSopenharmony_ci            ff_vk_discard_exec_deps(e);
558cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
559cabdff1aSopenharmony_ci        }
560cabdff1aSopenharmony_ci
561cabdff1aSopenharmony_ci        e->sem_wait[e->sem_wait_cnt] = f->sem[i];
562cabdff1aSopenharmony_ci        e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag;
563cabdff1aSopenharmony_ci        e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i];
564cabdff1aSopenharmony_ci        e->sem_wait_cnt++;
565cabdff1aSopenharmony_ci
566cabdff1aSopenharmony_ci        e->sem_sig[e->sem_sig_cnt] = f->sem[i];
567cabdff1aSopenharmony_ci        e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1;
568cabdff1aSopenharmony_ci        e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i];
569cabdff1aSopenharmony_ci        e->sem_sig_cnt++;
570cabdff1aSopenharmony_ci    }
571cabdff1aSopenharmony_ci
572cabdff1aSopenharmony_ci    dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size,
573cabdff1aSopenharmony_ci                          (q->nb_frame_deps + 1) * sizeof(*dst));
574cabdff1aSopenharmony_ci    if (!dst) {
575cabdff1aSopenharmony_ci        ff_vk_discard_exec_deps(e);
576cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
577cabdff1aSopenharmony_ci    }
578cabdff1aSopenharmony_ci
579cabdff1aSopenharmony_ci    q->frame_deps = dst;
580cabdff1aSopenharmony_ci    q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame);
581cabdff1aSopenharmony_ci    if (!q->frame_deps[q->nb_frame_deps]) {
582cabdff1aSopenharmony_ci        ff_vk_discard_exec_deps(e);
583cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
584cabdff1aSopenharmony_ci    }
585cabdff1aSopenharmony_ci    q->nb_frame_deps++;
586cabdff1aSopenharmony_ci
587cabdff1aSopenharmony_ci    return 0;
588cabdff1aSopenharmony_ci}
589cabdff1aSopenharmony_ci
590cabdff1aSopenharmony_ciint ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e)
591cabdff1aSopenharmony_ci{
592cabdff1aSopenharmony_ci    VkResult ret;
593cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
594cabdff1aSopenharmony_ci    FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
595cabdff1aSopenharmony_ci
596cabdff1aSopenharmony_ci    VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = {
597cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
598cabdff1aSopenharmony_ci        .pWaitSemaphoreValues = e->sem_wait_val,
599cabdff1aSopenharmony_ci        .pSignalSemaphoreValues = e->sem_sig_val,
600cabdff1aSopenharmony_ci        .waitSemaphoreValueCount = e->sem_wait_cnt,
601cabdff1aSopenharmony_ci        .signalSemaphoreValueCount = e->sem_sig_cnt,
602cabdff1aSopenharmony_ci    };
603cabdff1aSopenharmony_ci
604cabdff1aSopenharmony_ci    VkSubmitInfo s_info = {
605cabdff1aSopenharmony_ci        .sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO,
606cabdff1aSopenharmony_ci        .pNext                = &s_timeline_sem_info,
607cabdff1aSopenharmony_ci
608cabdff1aSopenharmony_ci        .commandBufferCount   = 1,
609cabdff1aSopenharmony_ci        .pCommandBuffers      = &e->bufs[e->qf->cur_queue],
610cabdff1aSopenharmony_ci
611cabdff1aSopenharmony_ci        .pWaitSemaphores      = e->sem_wait,
612cabdff1aSopenharmony_ci        .pWaitDstStageMask    = e->sem_wait_dst,
613cabdff1aSopenharmony_ci        .waitSemaphoreCount   = e->sem_wait_cnt,
614cabdff1aSopenharmony_ci
615cabdff1aSopenharmony_ci        .pSignalSemaphores    = e->sem_sig,
616cabdff1aSopenharmony_ci        .signalSemaphoreCount = e->sem_sig_cnt,
617cabdff1aSopenharmony_ci    };
618cabdff1aSopenharmony_ci
619cabdff1aSopenharmony_ci    ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]);
620cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
621cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
622cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
623cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
624cabdff1aSopenharmony_ci    }
625cabdff1aSopenharmony_ci
626cabdff1aSopenharmony_ci    ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence);
627cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
628cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
629cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
630cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
631cabdff1aSopenharmony_ci    }
632cabdff1aSopenharmony_ci
633cabdff1aSopenharmony_ci    for (int i = 0; i < e->sem_sig_cnt; i++)
634cabdff1aSopenharmony_ci        *e->sem_sig_val_dst[i] += 1;
635cabdff1aSopenharmony_ci
636cabdff1aSopenharmony_ci    return 0;
637cabdff1aSopenharmony_ci}
638cabdff1aSopenharmony_ci
639cabdff1aSopenharmony_ciint ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e,
640cabdff1aSopenharmony_ci                           AVBufferRef **deps, int nb_deps)
641cabdff1aSopenharmony_ci{
642cabdff1aSopenharmony_ci    AVBufferRef **dst;
643cabdff1aSopenharmony_ci    FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
644cabdff1aSopenharmony_ci
645cabdff1aSopenharmony_ci    if (!deps || !nb_deps)
646cabdff1aSopenharmony_ci        return 0;
647cabdff1aSopenharmony_ci
648cabdff1aSopenharmony_ci    dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size,
649cabdff1aSopenharmony_ci                          (q->nb_buf_deps + nb_deps) * sizeof(*dst));
650cabdff1aSopenharmony_ci    if (!dst)
651cabdff1aSopenharmony_ci        goto err;
652cabdff1aSopenharmony_ci
653cabdff1aSopenharmony_ci    q->buf_deps = dst;
654cabdff1aSopenharmony_ci
655cabdff1aSopenharmony_ci    for (int i = 0; i < nb_deps; i++) {
656cabdff1aSopenharmony_ci        q->buf_deps[q->nb_buf_deps] = deps[i];
657cabdff1aSopenharmony_ci        if (!q->buf_deps[q->nb_buf_deps])
658cabdff1aSopenharmony_ci            goto err;
659cabdff1aSopenharmony_ci        q->nb_buf_deps++;
660cabdff1aSopenharmony_ci    }
661cabdff1aSopenharmony_ci
662cabdff1aSopenharmony_ci    return 0;
663cabdff1aSopenharmony_ci
664cabdff1aSopenharmony_cierr:
665cabdff1aSopenharmony_ci    ff_vk_discard_exec_deps(e);
666cabdff1aSopenharmony_ci    return AVERROR(ENOMEM);
667cabdff1aSopenharmony_ci}
668cabdff1aSopenharmony_ci
669cabdff1aSopenharmony_ciFN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num)
670cabdff1aSopenharmony_ciFFVkSampler *ff_vk_init_sampler(FFVulkanContext *s,
671cabdff1aSopenharmony_ci                                int unnorm_coords, VkFilter filt)
672cabdff1aSopenharmony_ci{
673cabdff1aSopenharmony_ci    VkResult ret;
674cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
675cabdff1aSopenharmony_ci
676cabdff1aSopenharmony_ci    VkSamplerCreateInfo sampler_info = {
677cabdff1aSopenharmony_ci        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
678cabdff1aSopenharmony_ci        .magFilter = filt,
679cabdff1aSopenharmony_ci        .minFilter = sampler_info.magFilter,
680cabdff1aSopenharmony_ci        .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
681cabdff1aSopenharmony_ci                                      VK_SAMPLER_MIPMAP_MODE_LINEAR,
682cabdff1aSopenharmony_ci        .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
683cabdff1aSopenharmony_ci        .addressModeV = sampler_info.addressModeU,
684cabdff1aSopenharmony_ci        .addressModeW = sampler_info.addressModeU,
685cabdff1aSopenharmony_ci        .anisotropyEnable = VK_FALSE,
686cabdff1aSopenharmony_ci        .compareOp = VK_COMPARE_OP_NEVER,
687cabdff1aSopenharmony_ci        .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
688cabdff1aSopenharmony_ci        .unnormalizedCoordinates = unnorm_coords,
689cabdff1aSopenharmony_ci    };
690cabdff1aSopenharmony_ci
691cabdff1aSopenharmony_ci    FFVkSampler *sctx = create_sampler(s);
692cabdff1aSopenharmony_ci    if (!sctx)
693cabdff1aSopenharmony_ci        return NULL;
694cabdff1aSopenharmony_ci
695cabdff1aSopenharmony_ci    ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
696cabdff1aSopenharmony_ci                            s->hwctx->alloc, &sctx->sampler[0]);
697cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
698cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
699cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
700cabdff1aSopenharmony_ci        return NULL;
701cabdff1aSopenharmony_ci    }
702cabdff1aSopenharmony_ci
703cabdff1aSopenharmony_ci    for (int i = 1; i < 4; i++)
704cabdff1aSopenharmony_ci        sctx->sampler[i] = sctx->sampler[0];
705cabdff1aSopenharmony_ci
706cabdff1aSopenharmony_ci    return sctx;
707cabdff1aSopenharmony_ci}
708cabdff1aSopenharmony_ci
709cabdff1aSopenharmony_ciint ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
710cabdff1aSopenharmony_ci{
711cabdff1aSopenharmony_ci    if (pix_fmt == AV_PIX_FMT_ABGR   || pix_fmt == AV_PIX_FMT_BGRA   ||
712cabdff1aSopenharmony_ci        pix_fmt == AV_PIX_FMT_RGBA   || pix_fmt == AV_PIX_FMT_RGB24  ||
713cabdff1aSopenharmony_ci        pix_fmt == AV_PIX_FMT_BGR24  || pix_fmt == AV_PIX_FMT_RGB48  ||
714cabdff1aSopenharmony_ci        pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 ||
715cabdff1aSopenharmony_ci        pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0   ||
716cabdff1aSopenharmony_ci        pix_fmt == AV_PIX_FMT_0BGR   || pix_fmt == AV_PIX_FMT_RGB0)
717cabdff1aSopenharmony_ci        return 1;
718cabdff1aSopenharmony_ci    return 0;
719cabdff1aSopenharmony_ci}
720cabdff1aSopenharmony_ci
721cabdff1aSopenharmony_ciconst char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt)
722cabdff1aSopenharmony_ci{
723cabdff1aSopenharmony_ci    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixfmt);
724cabdff1aSopenharmony_ci    const int high = desc->comp[0].depth > 8;
725cabdff1aSopenharmony_ci    return high ? "rgba16f" : "rgba8";
726cabdff1aSopenharmony_ci}
727cabdff1aSopenharmony_ci
728cabdff1aSopenharmony_citypedef struct ImageViewCtx {
729cabdff1aSopenharmony_ci    VkImageView view;
730cabdff1aSopenharmony_ci} ImageViewCtx;
731cabdff1aSopenharmony_ci
732cabdff1aSopenharmony_cistatic void destroy_imageview(void *opaque, uint8_t *data)
733cabdff1aSopenharmony_ci{
734cabdff1aSopenharmony_ci    FFVulkanContext *s = opaque;
735cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
736cabdff1aSopenharmony_ci    ImageViewCtx *iv = (ImageViewCtx *)data;
737cabdff1aSopenharmony_ci
738cabdff1aSopenharmony_ci    vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc);
739cabdff1aSopenharmony_ci    av_free(iv);
740cabdff1aSopenharmony_ci}
741cabdff1aSopenharmony_ci
742cabdff1aSopenharmony_ciint ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e,
743cabdff1aSopenharmony_ci                           VkImageView *v, VkImage img, VkFormat fmt,
744cabdff1aSopenharmony_ci                           const VkComponentMapping map)
745cabdff1aSopenharmony_ci{
746cabdff1aSopenharmony_ci    int err;
747cabdff1aSopenharmony_ci    AVBufferRef *buf;
748cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_ci    VkImageViewCreateInfo imgview_spawn = {
751cabdff1aSopenharmony_ci        .sType      = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
752cabdff1aSopenharmony_ci        .pNext      = NULL,
753cabdff1aSopenharmony_ci        .image      = img,
754cabdff1aSopenharmony_ci        .viewType   = VK_IMAGE_VIEW_TYPE_2D,
755cabdff1aSopenharmony_ci        .format     = fmt,
756cabdff1aSopenharmony_ci        .components = map,
757cabdff1aSopenharmony_ci        .subresourceRange = {
758cabdff1aSopenharmony_ci            .aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT,
759cabdff1aSopenharmony_ci            .baseMipLevel   = 0,
760cabdff1aSopenharmony_ci            .levelCount     = 1,
761cabdff1aSopenharmony_ci            .baseArrayLayer = 0,
762cabdff1aSopenharmony_ci            .layerCount     = 1,
763cabdff1aSopenharmony_ci        },
764cabdff1aSopenharmony_ci    };
765cabdff1aSopenharmony_ci
766cabdff1aSopenharmony_ci    ImageViewCtx *iv = av_mallocz(sizeof(*iv));
767cabdff1aSopenharmony_ci
768cabdff1aSopenharmony_ci    VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn,
769cabdff1aSopenharmony_ci                                       s->hwctx->alloc, &iv->view);
770cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
771cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
772cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
773cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
774cabdff1aSopenharmony_ci    }
775cabdff1aSopenharmony_ci
776cabdff1aSopenharmony_ci    buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0);
777cabdff1aSopenharmony_ci    if (!buf) {
778cabdff1aSopenharmony_ci        destroy_imageview(s, (uint8_t *)iv);
779cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
780cabdff1aSopenharmony_ci    }
781cabdff1aSopenharmony_ci
782cabdff1aSopenharmony_ci    /* Add to queue dependencies */
783cabdff1aSopenharmony_ci    err = ff_vk_add_dep_exec_ctx(s, e, &buf, 1);
784cabdff1aSopenharmony_ci    if (err) {
785cabdff1aSopenharmony_ci        av_buffer_unref(&buf);
786cabdff1aSopenharmony_ci        return err;
787cabdff1aSopenharmony_ci    }
788cabdff1aSopenharmony_ci
789cabdff1aSopenharmony_ci    *v = iv->view;
790cabdff1aSopenharmony_ci
791cabdff1aSopenharmony_ci    return 0;
792cabdff1aSopenharmony_ci}
793cabdff1aSopenharmony_ci
794cabdff1aSopenharmony_ciFN_CREATING(FFVulkanPipeline, FFVkSPIRVShader, shader, shaders, shaders_num)
795cabdff1aSopenharmony_ciFFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name,
796cabdff1aSopenharmony_ci                                   VkShaderStageFlags stage)
797cabdff1aSopenharmony_ci{
798cabdff1aSopenharmony_ci    FFVkSPIRVShader *shd = create_shader(pl);
799cabdff1aSopenharmony_ci    if (!shd)
800cabdff1aSopenharmony_ci        return NULL;
801cabdff1aSopenharmony_ci
802cabdff1aSopenharmony_ci    av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED);
803cabdff1aSopenharmony_ci
804cabdff1aSopenharmony_ci    shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
805cabdff1aSopenharmony_ci    shd->shader.stage = stage;
806cabdff1aSopenharmony_ci
807cabdff1aSopenharmony_ci    shd->name = name;
808cabdff1aSopenharmony_ci
809cabdff1aSopenharmony_ci    GLSLF(0, #version %i                                                  ,460);
810cabdff1aSopenharmony_ci    GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y))       );
811cabdff1aSopenharmony_ci    GLSLC(0,                                                                  );
812cabdff1aSopenharmony_ci
813cabdff1aSopenharmony_ci    return shd;
814cabdff1aSopenharmony_ci}
815cabdff1aSopenharmony_ci
816cabdff1aSopenharmony_civoid ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3])
817cabdff1aSopenharmony_ci{
818cabdff1aSopenharmony_ci    shd->local_size[0] = local_size[0];
819cabdff1aSopenharmony_ci    shd->local_size[1] = local_size[1];
820cabdff1aSopenharmony_ci    shd->local_size[2] = local_size[2];
821cabdff1aSopenharmony_ci
822cabdff1aSopenharmony_ci    av_bprintf(&shd->src, "layout (local_size_x = %i, "
823cabdff1aSopenharmony_ci               "local_size_y = %i, local_size_z = %i) in;\n\n",
824cabdff1aSopenharmony_ci               shd->local_size[0], shd->local_size[1], shd->local_size[2]);
825cabdff1aSopenharmony_ci}
826cabdff1aSopenharmony_ci
827cabdff1aSopenharmony_civoid ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio)
828cabdff1aSopenharmony_ci{
829cabdff1aSopenharmony_ci    int line = 0;
830cabdff1aSopenharmony_ci    const char *p = shd->src.str;
831cabdff1aSopenharmony_ci    const char *start = p;
832cabdff1aSopenharmony_ci    const size_t len = strlen(p);
833cabdff1aSopenharmony_ci
834cabdff1aSopenharmony_ci    AVBPrint buf;
835cabdff1aSopenharmony_ci    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
836cabdff1aSopenharmony_ci
837cabdff1aSopenharmony_ci    for (int i = 0; i < len; i++) {
838cabdff1aSopenharmony_ci        if (p[i] == '\n') {
839cabdff1aSopenharmony_ci            av_bprintf(&buf, "%i\t", ++line);
840cabdff1aSopenharmony_ci            av_bprint_append_data(&buf, start, &p[i] - start + 1);
841cabdff1aSopenharmony_ci            start = &p[i + 1];
842cabdff1aSopenharmony_ci        }
843cabdff1aSopenharmony_ci    }
844cabdff1aSopenharmony_ci
845cabdff1aSopenharmony_ci    av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
846cabdff1aSopenharmony_ci    av_bprint_finalize(&buf, NULL);
847cabdff1aSopenharmony_ci}
848cabdff1aSopenharmony_ci
849cabdff1aSopenharmony_ciint ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
850cabdff1aSopenharmony_ci                         const char *entrypoint)
851cabdff1aSopenharmony_ci{
852cabdff1aSopenharmony_ci    int err;
853cabdff1aSopenharmony_ci    VkResult ret;
854cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
855cabdff1aSopenharmony_ci    VkShaderModuleCreateInfo shader_create;
856cabdff1aSopenharmony_ci    uint8_t *spirv;
857cabdff1aSopenharmony_ci    size_t spirv_size;
858cabdff1aSopenharmony_ci    void *priv;
859cabdff1aSopenharmony_ci
860cabdff1aSopenharmony_ci    shd->shader.pName = entrypoint;
861cabdff1aSopenharmony_ci
862cabdff1aSopenharmony_ci    if (!s->spirv_compiler) {
863cabdff1aSopenharmony_ci#if CONFIG_LIBGLSLANG
864cabdff1aSopenharmony_ci        s->spirv_compiler = ff_vk_glslang_init();
865cabdff1aSopenharmony_ci#elif CONFIG_LIBSHADERC
866cabdff1aSopenharmony_ci        s->spirv_compiler = ff_vk_shaderc_init();
867cabdff1aSopenharmony_ci#else
868cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
869cabdff1aSopenharmony_ci#endif
870cabdff1aSopenharmony_ci        if (!s->spirv_compiler)
871cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
872cabdff1aSopenharmony_ci    }
873cabdff1aSopenharmony_ci
874cabdff1aSopenharmony_ci    err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv,
875cabdff1aSopenharmony_ci                                            &spirv_size, entrypoint, &priv);
876cabdff1aSopenharmony_ci    if (err < 0)
877cabdff1aSopenharmony_ci        return err;
878cabdff1aSopenharmony_ci
879cabdff1aSopenharmony_ci    av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
880cabdff1aSopenharmony_ci           shd->name, spirv_size);
881cabdff1aSopenharmony_ci
882cabdff1aSopenharmony_ci    shader_create.sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
883cabdff1aSopenharmony_ci    shader_create.pNext    = NULL;
884cabdff1aSopenharmony_ci    shader_create.codeSize = spirv_size;
885cabdff1aSopenharmony_ci    shader_create.flags    = 0;
886cabdff1aSopenharmony_ci    shader_create.pCode    = (void *)spirv;
887cabdff1aSopenharmony_ci
888cabdff1aSopenharmony_ci    ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
889cabdff1aSopenharmony_ci                                 &shd->shader.module);
890cabdff1aSopenharmony_ci
891cabdff1aSopenharmony_ci    s->spirv_compiler->free_shader(s->spirv_compiler, &priv);
892cabdff1aSopenharmony_ci
893cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
894cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n",
895cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
896cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
897cabdff1aSopenharmony_ci    }
898cabdff1aSopenharmony_ci
899cabdff1aSopenharmony_ci    return 0;
900cabdff1aSopenharmony_ci}
901cabdff1aSopenharmony_ci
902cabdff1aSopenharmony_cistatic const struct descriptor_props {
903cabdff1aSopenharmony_ci    size_t struct_size; /* Size of the opaque which updates the descriptor */
904cabdff1aSopenharmony_ci    const char *type;
905cabdff1aSopenharmony_ci    int is_uniform;
906cabdff1aSopenharmony_ci    int mem_quali;      /* Can use a memory qualifier */
907cabdff1aSopenharmony_ci    int dim_needed;     /* Must indicate dimension */
908cabdff1aSopenharmony_ci    int buf_content;    /* Must indicate buffer contents */
909cabdff1aSopenharmony_ci} descriptor_props[] = {
910cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_SAMPLER]                = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 0, 0, },
911cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "texture",       1, 0, 1, 0, },
912cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "image",         1, 1, 1, 0, },
913cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]       = { sizeof(VkDescriptorImageInfo),  "subpassInput",  1, 0, 0, 0, },
914cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 1, 0, },
915cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER]         = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
916cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER]         = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
917cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
918cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
919cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "samplerBuffer", 1, 0, 0, 0, },
920cabdff1aSopenharmony_ci    [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "imageBuffer",   1, 0, 0, 0, },
921cabdff1aSopenharmony_ci};
922cabdff1aSopenharmony_ci
923cabdff1aSopenharmony_ciint ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
924cabdff1aSopenharmony_ci                             FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc,
925cabdff1aSopenharmony_ci                             int num, int only_print_to_shader)
926cabdff1aSopenharmony_ci{
927cabdff1aSopenharmony_ci    VkResult ret;
928cabdff1aSopenharmony_ci    VkDescriptorSetLayout *layout;
929cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
930cabdff1aSopenharmony_ci
931cabdff1aSopenharmony_ci    if (only_print_to_shader)
932cabdff1aSopenharmony_ci        goto print;
933cabdff1aSopenharmony_ci
934cabdff1aSopenharmony_ci    pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout),
935cabdff1aSopenharmony_ci                                       pl->desc_layout_num + pl->qf->nb_queues);
936cabdff1aSopenharmony_ci    if (!pl->desc_layout)
937cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
938cabdff1aSopenharmony_ci
939cabdff1aSopenharmony_ci    pl->desc_set_initialized = av_realloc_array(pl->desc_set_initialized,
940cabdff1aSopenharmony_ci                                                sizeof(*pl->desc_set_initialized),
941cabdff1aSopenharmony_ci                                                pl->descriptor_sets_num + 1);
942cabdff1aSopenharmony_ci    if (!pl->desc_set_initialized)
943cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
944cabdff1aSopenharmony_ci
945cabdff1aSopenharmony_ci    pl->desc_set_initialized[pl->descriptor_sets_num] = 0;
946cabdff1aSopenharmony_ci    layout = &pl->desc_layout[pl->desc_layout_num];
947cabdff1aSopenharmony_ci
948cabdff1aSopenharmony_ci    { /* Create descriptor set layout descriptions */
949cabdff1aSopenharmony_ci        VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 };
950cabdff1aSopenharmony_ci        VkDescriptorSetLayoutBinding *desc_binding;
951cabdff1aSopenharmony_ci
952cabdff1aSopenharmony_ci        desc_binding = av_mallocz(sizeof(*desc_binding)*num);
953cabdff1aSopenharmony_ci        if (!desc_binding)
954cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
955cabdff1aSopenharmony_ci
956cabdff1aSopenharmony_ci        for (int i = 0; i < num; i++) {
957cabdff1aSopenharmony_ci            desc_binding[i].binding            = i;
958cabdff1aSopenharmony_ci            desc_binding[i].descriptorType     = desc[i].type;
959cabdff1aSopenharmony_ci            desc_binding[i].descriptorCount    = FFMAX(desc[i].elems, 1);
960cabdff1aSopenharmony_ci            desc_binding[i].stageFlags         = desc[i].stages;
961cabdff1aSopenharmony_ci            desc_binding[i].pImmutableSamplers = desc[i].sampler ?
962cabdff1aSopenharmony_ci                                                 desc[i].sampler->sampler :
963cabdff1aSopenharmony_ci                                                 NULL;
964cabdff1aSopenharmony_ci        }
965cabdff1aSopenharmony_ci
966cabdff1aSopenharmony_ci        desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
967cabdff1aSopenharmony_ci        desc_create_layout.pBindings = desc_binding;
968cabdff1aSopenharmony_ci        desc_create_layout.bindingCount = num;
969cabdff1aSopenharmony_ci
970cabdff1aSopenharmony_ci        for (int i = 0; i < pl->qf->nb_queues; i++) {
971cabdff1aSopenharmony_ci            ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout,
972cabdff1aSopenharmony_ci                                                s->hwctx->alloc, &layout[i]);
973cabdff1aSopenharmony_ci            if (ret != VK_SUCCESS) {
974cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Unable to init descriptor set "
975cabdff1aSopenharmony_ci                       "layout: %s\n", ff_vk_ret2str(ret));
976cabdff1aSopenharmony_ci                av_free(desc_binding);
977cabdff1aSopenharmony_ci                return AVERROR_EXTERNAL;
978cabdff1aSopenharmony_ci            }
979cabdff1aSopenharmony_ci        }
980cabdff1aSopenharmony_ci
981cabdff1aSopenharmony_ci        av_free(desc_binding);
982cabdff1aSopenharmony_ci    }
983cabdff1aSopenharmony_ci
984cabdff1aSopenharmony_ci    { /* Pool each descriptor by type and update pool counts */
985cabdff1aSopenharmony_ci        for (int i = 0; i < num; i++) {
986cabdff1aSopenharmony_ci            int j;
987cabdff1aSopenharmony_ci            for (j = 0; j < pl->pool_size_desc_num; j++)
988cabdff1aSopenharmony_ci                if (pl->pool_size_desc[j].type == desc[i].type)
989cabdff1aSopenharmony_ci                    break;
990cabdff1aSopenharmony_ci            if (j >= pl->pool_size_desc_num) {
991cabdff1aSopenharmony_ci                pl->pool_size_desc = av_realloc_array(pl->pool_size_desc,
992cabdff1aSopenharmony_ci                                                      sizeof(*pl->pool_size_desc),
993cabdff1aSopenharmony_ci                                                      ++pl->pool_size_desc_num);
994cabdff1aSopenharmony_ci                if (!pl->pool_size_desc)
995cabdff1aSopenharmony_ci                    return AVERROR(ENOMEM);
996cabdff1aSopenharmony_ci                memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize));
997cabdff1aSopenharmony_ci            }
998cabdff1aSopenharmony_ci            pl->pool_size_desc[j].type             = desc[i].type;
999cabdff1aSopenharmony_ci            pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues;
1000cabdff1aSopenharmony_ci        }
1001cabdff1aSopenharmony_ci    }
1002cabdff1aSopenharmony_ci
1003cabdff1aSopenharmony_ci    { /* Create template creation struct */
1004cabdff1aSopenharmony_ci        VkDescriptorUpdateTemplateCreateInfo *dt;
1005cabdff1aSopenharmony_ci        VkDescriptorUpdateTemplateEntry *des_entries;
1006cabdff1aSopenharmony_ci
1007cabdff1aSopenharmony_ci        /* Freed after descriptor set initialization */
1008cabdff1aSopenharmony_ci        des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry));
1009cabdff1aSopenharmony_ci        if (!des_entries)
1010cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1011cabdff1aSopenharmony_ci
1012cabdff1aSopenharmony_ci        for (int i = 0; i < num; i++) {
1013cabdff1aSopenharmony_ci            des_entries[i].dstBinding      = i;
1014cabdff1aSopenharmony_ci            des_entries[i].descriptorType  = desc[i].type;
1015cabdff1aSopenharmony_ci            des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1);
1016cabdff1aSopenharmony_ci            des_entries[i].dstArrayElement = 0;
1017cabdff1aSopenharmony_ci            des_entries[i].offset          = ((uint8_t *)desc[i].updater) - (uint8_t *)s;
1018cabdff1aSopenharmony_ci            des_entries[i].stride          = descriptor_props[desc[i].type].struct_size;
1019cabdff1aSopenharmony_ci        }
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_ci        pl->desc_template_info = av_realloc_array(pl->desc_template_info,
1022cabdff1aSopenharmony_ci                                                  sizeof(*pl->desc_template_info),
1023cabdff1aSopenharmony_ci                                                  pl->total_descriptor_sets + pl->qf->nb_queues);
1024cabdff1aSopenharmony_ci        if (!pl->desc_template_info)
1025cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1026cabdff1aSopenharmony_ci
1027cabdff1aSopenharmony_ci        dt = &pl->desc_template_info[pl->total_descriptor_sets];
1028cabdff1aSopenharmony_ci        memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues);
1029cabdff1aSopenharmony_ci
1030cabdff1aSopenharmony_ci        for (int i = 0; i < pl->qf->nb_queues; i++) {
1031cabdff1aSopenharmony_ci            dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
1032cabdff1aSopenharmony_ci            dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
1033cabdff1aSopenharmony_ci            dt[i].descriptorSetLayout = layout[i];
1034cabdff1aSopenharmony_ci            dt[i].pDescriptorUpdateEntries = des_entries;
1035cabdff1aSopenharmony_ci            dt[i].descriptorUpdateEntryCount = num;
1036cabdff1aSopenharmony_ci        }
1037cabdff1aSopenharmony_ci    }
1038cabdff1aSopenharmony_ci
1039cabdff1aSopenharmony_ci    pl->descriptor_sets_num++;
1040cabdff1aSopenharmony_ci
1041cabdff1aSopenharmony_ci    pl->desc_layout_num += pl->qf->nb_queues;
1042cabdff1aSopenharmony_ci    pl->total_descriptor_sets += pl->qf->nb_queues;
1043cabdff1aSopenharmony_ci
1044cabdff1aSopenharmony_ciprint:
1045cabdff1aSopenharmony_ci    /* Write shader info */
1046cabdff1aSopenharmony_ci    for (int i = 0; i < num; i++) {
1047cabdff1aSopenharmony_ci        const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1048cabdff1aSopenharmony_ci        GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i);
1049cabdff1aSopenharmony_ci
1050cabdff1aSopenharmony_ci        if (desc[i].mem_layout)
1051cabdff1aSopenharmony_ci            GLSLA(", %s", desc[i].mem_layout);
1052cabdff1aSopenharmony_ci        GLSLA(")");
1053cabdff1aSopenharmony_ci
1054cabdff1aSopenharmony_ci        if (prop->is_uniform)
1055cabdff1aSopenharmony_ci            GLSLA(" uniform");
1056cabdff1aSopenharmony_ci
1057cabdff1aSopenharmony_ci        if (prop->mem_quali && desc[i].mem_quali)
1058cabdff1aSopenharmony_ci            GLSLA(" %s", desc[i].mem_quali);
1059cabdff1aSopenharmony_ci
1060cabdff1aSopenharmony_ci        if (prop->type)
1061cabdff1aSopenharmony_ci            GLSLA(" %s", prop->type);
1062cabdff1aSopenharmony_ci
1063cabdff1aSopenharmony_ci        if (prop->dim_needed)
1064cabdff1aSopenharmony_ci            GLSLA("%iD", desc[i].dimensions);
1065cabdff1aSopenharmony_ci
1066cabdff1aSopenharmony_ci        GLSLA(" %s", desc[i].name);
1067cabdff1aSopenharmony_ci
1068cabdff1aSopenharmony_ci        if (prop->buf_content)
1069cabdff1aSopenharmony_ci            GLSLA(" {\n    %s\n}", desc[i].buf_content);
1070cabdff1aSopenharmony_ci        else if (desc[i].elems > 0)
1071cabdff1aSopenharmony_ci            GLSLA("[%i]", desc[i].elems);
1072cabdff1aSopenharmony_ci
1073cabdff1aSopenharmony_ci        GLSLA(";\n");
1074cabdff1aSopenharmony_ci    }
1075cabdff1aSopenharmony_ci    GLSLA("\n");
1076cabdff1aSopenharmony_ci
1077cabdff1aSopenharmony_ci    return 0;
1078cabdff1aSopenharmony_ci}
1079cabdff1aSopenharmony_ci
1080cabdff1aSopenharmony_civoid ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
1081cabdff1aSopenharmony_ci                                 int set_id)
1082cabdff1aSopenharmony_ci{
1083cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1084cabdff1aSopenharmony_ci
1085cabdff1aSopenharmony_ci    /* If a set has never been updated, update all queues' sets. */
1086cabdff1aSopenharmony_ci    if (!pl->desc_set_initialized[set_id]) {
1087cabdff1aSopenharmony_ci        for (int i = 0; i < pl->qf->nb_queues; i++) {
1088cabdff1aSopenharmony_ci            int idx = set_id*pl->qf->nb_queues + i;
1089cabdff1aSopenharmony_ci            vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev,
1090cabdff1aSopenharmony_ci                                                pl->desc_set[idx],
1091cabdff1aSopenharmony_ci                                                pl->desc_template[idx],
1092cabdff1aSopenharmony_ci                                                s);
1093cabdff1aSopenharmony_ci        }
1094cabdff1aSopenharmony_ci        pl->desc_set_initialized[set_id] = 1;
1095cabdff1aSopenharmony_ci        return;
1096cabdff1aSopenharmony_ci    }
1097cabdff1aSopenharmony_ci
1098cabdff1aSopenharmony_ci    set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue;
1099cabdff1aSopenharmony_ci
1100cabdff1aSopenharmony_ci    vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev,
1101cabdff1aSopenharmony_ci                                        pl->desc_set[set_id],
1102cabdff1aSopenharmony_ci                                        pl->desc_template[set_id],
1103cabdff1aSopenharmony_ci                                        s);
1104cabdff1aSopenharmony_ci}
1105cabdff1aSopenharmony_ci
1106cabdff1aSopenharmony_civoid ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e,
1107cabdff1aSopenharmony_ci                            VkShaderStageFlagBits stage, int offset,
1108cabdff1aSopenharmony_ci                            size_t size, void *src)
1109cabdff1aSopenharmony_ci{
1110cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1111cabdff1aSopenharmony_ci
1112cabdff1aSopenharmony_ci    vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout,
1113cabdff1aSopenharmony_ci                         stage, offset, size, src);
1114cabdff1aSopenharmony_ci}
1115cabdff1aSopenharmony_ci
1116cabdff1aSopenharmony_ciint ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl)
1117cabdff1aSopenharmony_ci{
1118cabdff1aSopenharmony_ci    VkResult ret;
1119cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1120cabdff1aSopenharmony_ci
1121cabdff1aSopenharmony_ci    pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging));
1122cabdff1aSopenharmony_ci    if (!pl->desc_staging)
1123cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1124cabdff1aSopenharmony_ci
1125cabdff1aSopenharmony_ci    { /* Init descriptor set pool */
1126cabdff1aSopenharmony_ci        VkDescriptorPoolCreateInfo pool_create_info = {
1127cabdff1aSopenharmony_ci            .sType         = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1128cabdff1aSopenharmony_ci            .poolSizeCount = pl->pool_size_desc_num,
1129cabdff1aSopenharmony_ci            .pPoolSizes    = pl->pool_size_desc,
1130cabdff1aSopenharmony_ci            .maxSets       = pl->total_descriptor_sets,
1131cabdff1aSopenharmony_ci        };
1132cabdff1aSopenharmony_ci
1133cabdff1aSopenharmony_ci        ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
1134cabdff1aSopenharmony_ci                                       s->hwctx->alloc, &pl->desc_pool);
1135cabdff1aSopenharmony_ci        av_freep(&pl->pool_size_desc);
1136cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
1137cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Unable to init descriptor set "
1138cabdff1aSopenharmony_ci                   "pool: %s\n", ff_vk_ret2str(ret));
1139cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
1140cabdff1aSopenharmony_ci        }
1141cabdff1aSopenharmony_ci    }
1142cabdff1aSopenharmony_ci
1143cabdff1aSopenharmony_ci    { /* Allocate descriptor sets */
1144cabdff1aSopenharmony_ci        VkDescriptorSetAllocateInfo alloc_info = {
1145cabdff1aSopenharmony_ci            .sType              = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1146cabdff1aSopenharmony_ci            .descriptorPool     = pl->desc_pool,
1147cabdff1aSopenharmony_ci            .descriptorSetCount = pl->total_descriptor_sets,
1148cabdff1aSopenharmony_ci            .pSetLayouts        = pl->desc_layout,
1149cabdff1aSopenharmony_ci        };
1150cabdff1aSopenharmony_ci
1151cabdff1aSopenharmony_ci        pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set));
1152cabdff1aSopenharmony_ci        if (!pl->desc_set)
1153cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1154cabdff1aSopenharmony_ci
1155cabdff1aSopenharmony_ci        ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info,
1156cabdff1aSopenharmony_ci                                         pl->desc_set);
1157cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
1158cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
1159cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
1160cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
1161cabdff1aSopenharmony_ci        }
1162cabdff1aSopenharmony_ci    }
1163cabdff1aSopenharmony_ci
1164cabdff1aSopenharmony_ci    { /* Finally create the pipeline layout */
1165cabdff1aSopenharmony_ci        VkPipelineLayoutCreateInfo spawn_pipeline_layout = {
1166cabdff1aSopenharmony_ci            .sType                  = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1167cabdff1aSopenharmony_ci            .pSetLayouts            = (VkDescriptorSetLayout *)pl->desc_staging,
1168cabdff1aSopenharmony_ci            .pushConstantRangeCount = pl->push_consts_num,
1169cabdff1aSopenharmony_ci            .pPushConstantRanges    = pl->push_consts,
1170cabdff1aSopenharmony_ci        };
1171cabdff1aSopenharmony_ci
1172cabdff1aSopenharmony_ci        for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues)
1173cabdff1aSopenharmony_ci            pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i];
1174cabdff1aSopenharmony_ci
1175cabdff1aSopenharmony_ci        ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout,
1176cabdff1aSopenharmony_ci                                       s->hwctx->alloc, &pl->pipeline_layout);
1177cabdff1aSopenharmony_ci        av_freep(&pl->push_consts);
1178cabdff1aSopenharmony_ci        pl->push_consts_num = 0;
1179cabdff1aSopenharmony_ci        if (ret != VK_SUCCESS) {
1180cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1181cabdff1aSopenharmony_ci                   ff_vk_ret2str(ret));
1182cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
1183cabdff1aSopenharmony_ci        }
1184cabdff1aSopenharmony_ci    }
1185cabdff1aSopenharmony_ci
1186cabdff1aSopenharmony_ci    { /* Descriptor template (for tightly packed descriptors) */
1187cabdff1aSopenharmony_ci        VkDescriptorUpdateTemplateCreateInfo *dt;
1188cabdff1aSopenharmony_ci
1189cabdff1aSopenharmony_ci        pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template));
1190cabdff1aSopenharmony_ci        if (!pl->desc_template)
1191cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1192cabdff1aSopenharmony_ci
1193cabdff1aSopenharmony_ci        /* Create update templates for the descriptor sets */
1194cabdff1aSopenharmony_ci        for (int i = 0; i < pl->total_descriptor_sets; i++) {
1195cabdff1aSopenharmony_ci            dt = &pl->desc_template_info[i];
1196cabdff1aSopenharmony_ci            dt->pipelineLayout = pl->pipeline_layout;
1197cabdff1aSopenharmony_ci            ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev,
1198cabdff1aSopenharmony_ci                                                     dt, s->hwctx->alloc,
1199cabdff1aSopenharmony_ci                                                     &pl->desc_template[i]);
1200cabdff1aSopenharmony_ci            if (ret != VK_SUCCESS) {
1201cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Unable to init descriptor "
1202cabdff1aSopenharmony_ci                       "template: %s\n", ff_vk_ret2str(ret));
1203cabdff1aSopenharmony_ci                return AVERROR_EXTERNAL;
1204cabdff1aSopenharmony_ci            }
1205cabdff1aSopenharmony_ci        }
1206cabdff1aSopenharmony_ci
1207cabdff1aSopenharmony_ci        /* Free the duplicated memory used for the template entries */
1208cabdff1aSopenharmony_ci        for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) {
1209cabdff1aSopenharmony_ci            dt = &pl->desc_template_info[i];
1210cabdff1aSopenharmony_ci            av_free((void *)dt->pDescriptorUpdateEntries);
1211cabdff1aSopenharmony_ci        }
1212cabdff1aSopenharmony_ci
1213cabdff1aSopenharmony_ci        av_freep(&pl->desc_template_info);
1214cabdff1aSopenharmony_ci    }
1215cabdff1aSopenharmony_ci
1216cabdff1aSopenharmony_ci    return 0;
1217cabdff1aSopenharmony_ci}
1218cabdff1aSopenharmony_ci
1219cabdff1aSopenharmony_ciFN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num)
1220cabdff1aSopenharmony_ciFFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf)
1221cabdff1aSopenharmony_ci{
1222cabdff1aSopenharmony_ci    FFVulkanPipeline *pl = create_pipeline(s);
1223cabdff1aSopenharmony_ci    if (pl)
1224cabdff1aSopenharmony_ci        pl->qf = qf;
1225cabdff1aSopenharmony_ci
1226cabdff1aSopenharmony_ci    return pl;
1227cabdff1aSopenharmony_ci}
1228cabdff1aSopenharmony_ci
1229cabdff1aSopenharmony_ciint ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl)
1230cabdff1aSopenharmony_ci{
1231cabdff1aSopenharmony_ci    int i;
1232cabdff1aSopenharmony_ci    VkResult ret;
1233cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1234cabdff1aSopenharmony_ci
1235cabdff1aSopenharmony_ci    VkComputePipelineCreateInfo pipe = {
1236cabdff1aSopenharmony_ci        .sType  = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1237cabdff1aSopenharmony_ci        .layout = pl->pipeline_layout,
1238cabdff1aSopenharmony_ci    };
1239cabdff1aSopenharmony_ci
1240cabdff1aSopenharmony_ci    for (i = 0; i < pl->shaders_num; i++) {
1241cabdff1aSopenharmony_ci        if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) {
1242cabdff1aSopenharmony_ci            pipe.stage = pl->shaders[i]->shader;
1243cabdff1aSopenharmony_ci            break;
1244cabdff1aSopenharmony_ci        }
1245cabdff1aSopenharmony_ci    }
1246cabdff1aSopenharmony_ci    if (i == pl->shaders_num) {
1247cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n");
1248cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
1249cabdff1aSopenharmony_ci    }
1250cabdff1aSopenharmony_ci
1251cabdff1aSopenharmony_ci    ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe,
1252cabdff1aSopenharmony_ci                                     s->hwctx->alloc, &pl->pipeline);
1253cabdff1aSopenharmony_ci    if (ret != VK_SUCCESS) {
1254cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1255cabdff1aSopenharmony_ci               ff_vk_ret2str(ret));
1256cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
1257cabdff1aSopenharmony_ci    }
1258cabdff1aSopenharmony_ci
1259cabdff1aSopenharmony_ci    pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1260cabdff1aSopenharmony_ci
1261cabdff1aSopenharmony_ci    return 0;
1262cabdff1aSopenharmony_ci}
1263cabdff1aSopenharmony_ci
1264cabdff1aSopenharmony_civoid ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e,
1265cabdff1aSopenharmony_ci                              FFVulkanPipeline *pl)
1266cabdff1aSopenharmony_ci{
1267cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1268cabdff1aSopenharmony_ci
1269cabdff1aSopenharmony_ci    vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline);
1270cabdff1aSopenharmony_ci
1271cabdff1aSopenharmony_ci    for (int i = 0; i < pl->descriptor_sets_num; i++)
1272cabdff1aSopenharmony_ci        pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue];
1273cabdff1aSopenharmony_ci
1274cabdff1aSopenharmony_ci    vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point,
1275cabdff1aSopenharmony_ci                              pl->pipeline_layout, 0,
1276cabdff1aSopenharmony_ci                              pl->descriptor_sets_num,
1277cabdff1aSopenharmony_ci                              (VkDescriptorSet *)pl->desc_staging,
1278cabdff1aSopenharmony_ci                              0, NULL);
1279cabdff1aSopenharmony_ci
1280cabdff1aSopenharmony_ci    e->bound_pl = pl;
1281cabdff1aSopenharmony_ci}
1282cabdff1aSopenharmony_ci
1283cabdff1aSopenharmony_cistatic void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e)
1284cabdff1aSopenharmony_ci{
1285cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1286cabdff1aSopenharmony_ci
1287cabdff1aSopenharmony_ci    /* Make sure all queues have finished executing */
1288cabdff1aSopenharmony_ci    for (int i = 0; i < e->qf->nb_queues; i++) {
1289cabdff1aSopenharmony_ci        FFVkQueueCtx *q = &e->queues[i];
1290cabdff1aSopenharmony_ci
1291cabdff1aSopenharmony_ci        if (q->fence) {
1292cabdff1aSopenharmony_ci            vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
1293cabdff1aSopenharmony_ci            vk->ResetFences(s->hwctx->act_dev, 1, &q->fence);
1294cabdff1aSopenharmony_ci        }
1295cabdff1aSopenharmony_ci
1296cabdff1aSopenharmony_ci        /* Free the fence */
1297cabdff1aSopenharmony_ci        if (q->fence)
1298cabdff1aSopenharmony_ci            vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc);
1299cabdff1aSopenharmony_ci
1300cabdff1aSopenharmony_ci        /* Free buffer dependencies */
1301cabdff1aSopenharmony_ci        for (int j = 0; j < q->nb_buf_deps; j++)
1302cabdff1aSopenharmony_ci            av_buffer_unref(&q->buf_deps[j]);
1303cabdff1aSopenharmony_ci        av_free(q->buf_deps);
1304cabdff1aSopenharmony_ci
1305cabdff1aSopenharmony_ci        /* Free frame dependencies */
1306cabdff1aSopenharmony_ci        for (int j = 0; j < q->nb_frame_deps; j++)
1307cabdff1aSopenharmony_ci            av_frame_free(&q->frame_deps[j]);
1308cabdff1aSopenharmony_ci        av_free(q->frame_deps);
1309cabdff1aSopenharmony_ci    }
1310cabdff1aSopenharmony_ci
1311cabdff1aSopenharmony_ci    if (e->bufs)
1312cabdff1aSopenharmony_ci        vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs);
1313cabdff1aSopenharmony_ci    if (e->pool)
1314cabdff1aSopenharmony_ci        vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc);
1315cabdff1aSopenharmony_ci
1316cabdff1aSopenharmony_ci    av_freep(&e->bufs);
1317cabdff1aSopenharmony_ci    av_freep(&e->queues);
1318cabdff1aSopenharmony_ci    av_freep(&e->sem_sig);
1319cabdff1aSopenharmony_ci    av_freep(&e->sem_sig_val);
1320cabdff1aSopenharmony_ci    av_freep(&e->sem_sig_val_dst);
1321cabdff1aSopenharmony_ci    av_freep(&e->sem_wait);
1322cabdff1aSopenharmony_ci    av_freep(&e->sem_wait_dst);
1323cabdff1aSopenharmony_ci    av_freep(&e->sem_wait_val);
1324cabdff1aSopenharmony_ci    av_free(e);
1325cabdff1aSopenharmony_ci}
1326cabdff1aSopenharmony_ci
1327cabdff1aSopenharmony_cistatic void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl)
1328cabdff1aSopenharmony_ci{
1329cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1330cabdff1aSopenharmony_ci
1331cabdff1aSopenharmony_ci    for (int i = 0; i < pl->shaders_num; i++) {
1332cabdff1aSopenharmony_ci        FFVkSPIRVShader *shd = pl->shaders[i];
1333cabdff1aSopenharmony_ci        av_bprint_finalize(&shd->src, NULL);
1334cabdff1aSopenharmony_ci        vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
1335cabdff1aSopenharmony_ci                                s->hwctx->alloc);
1336cabdff1aSopenharmony_ci        av_free(shd);
1337cabdff1aSopenharmony_ci    }
1338cabdff1aSopenharmony_ci
1339cabdff1aSopenharmony_ci    vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc);
1340cabdff1aSopenharmony_ci    vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout,
1341cabdff1aSopenharmony_ci                              s->hwctx->alloc);
1342cabdff1aSopenharmony_ci
1343cabdff1aSopenharmony_ci    for (int i = 0; i < pl->desc_layout_num; i++) {
1344cabdff1aSopenharmony_ci        if (pl->desc_template && pl->desc_template[i])
1345cabdff1aSopenharmony_ci            vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i],
1346cabdff1aSopenharmony_ci                                                s->hwctx->alloc);
1347cabdff1aSopenharmony_ci        if (pl->desc_layout && pl->desc_layout[i])
1348cabdff1aSopenharmony_ci            vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i],
1349cabdff1aSopenharmony_ci                                           s->hwctx->alloc);
1350cabdff1aSopenharmony_ci    }
1351cabdff1aSopenharmony_ci
1352cabdff1aSopenharmony_ci    /* Also frees the descriptor sets */
1353cabdff1aSopenharmony_ci    if (pl->desc_pool)
1354cabdff1aSopenharmony_ci        vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool,
1355cabdff1aSopenharmony_ci                                  s->hwctx->alloc);
1356cabdff1aSopenharmony_ci
1357cabdff1aSopenharmony_ci    av_freep(&pl->desc_staging);
1358cabdff1aSopenharmony_ci    av_freep(&pl->desc_set);
1359cabdff1aSopenharmony_ci    av_freep(&pl->shaders);
1360cabdff1aSopenharmony_ci    av_freep(&pl->desc_layout);
1361cabdff1aSopenharmony_ci    av_freep(&pl->desc_template);
1362cabdff1aSopenharmony_ci    av_freep(&pl->desc_set_initialized);
1363cabdff1aSopenharmony_ci    av_freep(&pl->push_consts);
1364cabdff1aSopenharmony_ci    pl->push_consts_num = 0;
1365cabdff1aSopenharmony_ci
1366cabdff1aSopenharmony_ci    /* Only freed in case of failure */
1367cabdff1aSopenharmony_ci    av_freep(&pl->pool_size_desc);
1368cabdff1aSopenharmony_ci    if (pl->desc_template_info) {
1369cabdff1aSopenharmony_ci        for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) {
1370cabdff1aSopenharmony_ci            VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i];
1371cabdff1aSopenharmony_ci            av_free((void *)dt->pDescriptorUpdateEntries);
1372cabdff1aSopenharmony_ci        }
1373cabdff1aSopenharmony_ci        av_freep(&pl->desc_template_info);
1374cabdff1aSopenharmony_ci    }
1375cabdff1aSopenharmony_ci
1376cabdff1aSopenharmony_ci    av_free(pl);
1377cabdff1aSopenharmony_ci}
1378cabdff1aSopenharmony_ci
1379cabdff1aSopenharmony_civoid ff_vk_uninit(FFVulkanContext *s)
1380cabdff1aSopenharmony_ci{
1381cabdff1aSopenharmony_ci    FFVulkanFunctions *vk = &s->vkfn;
1382cabdff1aSopenharmony_ci
1383cabdff1aSopenharmony_ci    if (s->spirv_compiler)
1384cabdff1aSopenharmony_ci        s->spirv_compiler->uninit(&s->spirv_compiler);
1385cabdff1aSopenharmony_ci
1386cabdff1aSopenharmony_ci    for (int i = 0; i < s->exec_ctx_num; i++)
1387cabdff1aSopenharmony_ci        free_exec_ctx(s, s->exec_ctx[i]);
1388cabdff1aSopenharmony_ci    av_freep(&s->exec_ctx);
1389cabdff1aSopenharmony_ci
1390cabdff1aSopenharmony_ci    for (int i = 0; i < s->samplers_num; i++) {
1391cabdff1aSopenharmony_ci        vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0],
1392cabdff1aSopenharmony_ci                           s->hwctx->alloc);
1393cabdff1aSopenharmony_ci        av_free(s->samplers[i]);
1394cabdff1aSopenharmony_ci    }
1395cabdff1aSopenharmony_ci    av_freep(&s->samplers);
1396cabdff1aSopenharmony_ci
1397cabdff1aSopenharmony_ci    for (int i = 0; i < s->pipelines_num; i++)
1398cabdff1aSopenharmony_ci        free_pipeline(s, s->pipelines[i]);
1399cabdff1aSopenharmony_ci    av_freep(&s->pipelines);
1400cabdff1aSopenharmony_ci
1401cabdff1aSopenharmony_ci    av_freep(&s->scratch);
1402cabdff1aSopenharmony_ci    s->scratch_size = 0;
1403cabdff1aSopenharmony_ci
1404cabdff1aSopenharmony_ci    av_buffer_unref(&s->device_ref);
1405cabdff1aSopenharmony_ci    av_buffer_unref(&s->frames_ref);
1406cabdff1aSopenharmony_ci}
1407