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