17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2019 Google LLC
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg *
57ec681f3Smrg * based in part on anv and radv which are:
67ec681f3Smrg * Copyright © 2015 Intel Corporation
77ec681f3Smrg * Copyright © 2016 Red Hat.
87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
97ec681f3Smrg */
107ec681f3Smrg
117ec681f3Smrg#include "vn_pipeline.h"
127ec681f3Smrg
137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_pipeline.h"
147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_pipeline_cache.h"
157ec681f3Smrg#include "venus-protocol/vn_protocol_driver_pipeline_layout.h"
167ec681f3Smrg#include "venus-protocol/vn_protocol_driver_shader_module.h"
177ec681f3Smrg
187ec681f3Smrg#include "vn_device.h"
197ec681f3Smrg#include "vn_physical_device.h"
207ec681f3Smrg
217ec681f3Smrg/* shader module commands */
227ec681f3Smrg
237ec681f3SmrgVkResult
247ec681f3Smrgvn_CreateShaderModule(VkDevice device,
257ec681f3Smrg                      const VkShaderModuleCreateInfo *pCreateInfo,
267ec681f3Smrg                      const VkAllocationCallbacks *pAllocator,
277ec681f3Smrg                      VkShaderModule *pShaderModule)
287ec681f3Smrg{
297ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
307ec681f3Smrg   const VkAllocationCallbacks *alloc =
317ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
327ec681f3Smrg
337ec681f3Smrg   struct vn_shader_module *mod =
347ec681f3Smrg      vk_zalloc(alloc, sizeof(*mod), VN_DEFAULT_ALIGN,
357ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
367ec681f3Smrg   if (!mod)
377ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
387ec681f3Smrg
397ec681f3Smrg   vn_object_base_init(&mod->base, VK_OBJECT_TYPE_SHADER_MODULE, &dev->base);
407ec681f3Smrg
417ec681f3Smrg   VkShaderModule mod_handle = vn_shader_module_to_handle(mod);
427ec681f3Smrg   vn_async_vkCreateShaderModule(dev->instance, device, pCreateInfo, NULL,
437ec681f3Smrg                                 &mod_handle);
447ec681f3Smrg
457ec681f3Smrg   *pShaderModule = mod_handle;
467ec681f3Smrg
477ec681f3Smrg   return VK_SUCCESS;
487ec681f3Smrg}
497ec681f3Smrg
507ec681f3Smrgvoid
517ec681f3Smrgvn_DestroyShaderModule(VkDevice device,
527ec681f3Smrg                       VkShaderModule shaderModule,
537ec681f3Smrg                       const VkAllocationCallbacks *pAllocator)
547ec681f3Smrg{
557ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
567ec681f3Smrg   struct vn_shader_module *mod = vn_shader_module_from_handle(shaderModule);
577ec681f3Smrg   const VkAllocationCallbacks *alloc =
587ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
597ec681f3Smrg
607ec681f3Smrg   if (!mod)
617ec681f3Smrg      return;
627ec681f3Smrg
637ec681f3Smrg   vn_async_vkDestroyShaderModule(dev->instance, device, shaderModule, NULL);
647ec681f3Smrg
657ec681f3Smrg   vn_object_base_fini(&mod->base);
667ec681f3Smrg   vk_free(alloc, mod);
677ec681f3Smrg}
687ec681f3Smrg
697ec681f3Smrg/* pipeline layout commands */
707ec681f3Smrg
717ec681f3SmrgVkResult
727ec681f3Smrgvn_CreatePipelineLayout(VkDevice device,
737ec681f3Smrg                        const VkPipelineLayoutCreateInfo *pCreateInfo,
747ec681f3Smrg                        const VkAllocationCallbacks *pAllocator,
757ec681f3Smrg                        VkPipelineLayout *pPipelineLayout)
767ec681f3Smrg{
777ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
787ec681f3Smrg   const VkAllocationCallbacks *alloc =
797ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
807ec681f3Smrg
817ec681f3Smrg   struct vn_pipeline_layout *layout =
827ec681f3Smrg      vk_zalloc(alloc, sizeof(*layout), VN_DEFAULT_ALIGN,
837ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
847ec681f3Smrg   if (!layout)
857ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
867ec681f3Smrg
877ec681f3Smrg   vn_object_base_init(&layout->base, VK_OBJECT_TYPE_PIPELINE_LAYOUT,
887ec681f3Smrg                       &dev->base);
897ec681f3Smrg
907ec681f3Smrg   VkPipelineLayout layout_handle = vn_pipeline_layout_to_handle(layout);
917ec681f3Smrg   vn_async_vkCreatePipelineLayout(dev->instance, device, pCreateInfo, NULL,
927ec681f3Smrg                                   &layout_handle);
937ec681f3Smrg
947ec681f3Smrg   *pPipelineLayout = layout_handle;
957ec681f3Smrg
967ec681f3Smrg   return VK_SUCCESS;
977ec681f3Smrg}
987ec681f3Smrg
997ec681f3Smrgvoid
1007ec681f3Smrgvn_DestroyPipelineLayout(VkDevice device,
1017ec681f3Smrg                         VkPipelineLayout pipelineLayout,
1027ec681f3Smrg                         const VkAllocationCallbacks *pAllocator)
1037ec681f3Smrg{
1047ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1057ec681f3Smrg   struct vn_pipeline_layout *layout =
1067ec681f3Smrg      vn_pipeline_layout_from_handle(pipelineLayout);
1077ec681f3Smrg   const VkAllocationCallbacks *alloc =
1087ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
1097ec681f3Smrg
1107ec681f3Smrg   if (!layout)
1117ec681f3Smrg      return;
1127ec681f3Smrg
1137ec681f3Smrg   vn_async_vkDestroyPipelineLayout(dev->instance, device, pipelineLayout,
1147ec681f3Smrg                                    NULL);
1157ec681f3Smrg
1167ec681f3Smrg   vn_object_base_fini(&layout->base);
1177ec681f3Smrg   vk_free(alloc, layout);
1187ec681f3Smrg}
1197ec681f3Smrg
1207ec681f3Smrg/* pipeline cache commands */
1217ec681f3Smrg
1227ec681f3SmrgVkResult
1237ec681f3Smrgvn_CreatePipelineCache(VkDevice device,
1247ec681f3Smrg                       const VkPipelineCacheCreateInfo *pCreateInfo,
1257ec681f3Smrg                       const VkAllocationCallbacks *pAllocator,
1267ec681f3Smrg                       VkPipelineCache *pPipelineCache)
1277ec681f3Smrg{
1287ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1297ec681f3Smrg   const VkAllocationCallbacks *alloc =
1307ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
1317ec681f3Smrg
1327ec681f3Smrg   struct vn_pipeline_cache *cache =
1337ec681f3Smrg      vk_zalloc(alloc, sizeof(*cache), VN_DEFAULT_ALIGN,
1347ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1357ec681f3Smrg   if (!cache)
1367ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1377ec681f3Smrg
1387ec681f3Smrg   vn_object_base_init(&cache->base, VK_OBJECT_TYPE_PIPELINE_CACHE,
1397ec681f3Smrg                       &dev->base);
1407ec681f3Smrg
1417ec681f3Smrg   VkPipelineCacheCreateInfo local_create_info;
1427ec681f3Smrg   if (pCreateInfo->initialDataSize) {
1437ec681f3Smrg      const struct vk_pipeline_cache_header *header =
1447ec681f3Smrg         pCreateInfo->pInitialData;
1457ec681f3Smrg
1467ec681f3Smrg      local_create_info = *pCreateInfo;
1477ec681f3Smrg      local_create_info.initialDataSize -= header->header_size;
1487ec681f3Smrg      local_create_info.pInitialData += header->header_size;
1497ec681f3Smrg      pCreateInfo = &local_create_info;
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   VkPipelineCache cache_handle = vn_pipeline_cache_to_handle(cache);
1537ec681f3Smrg   vn_async_vkCreatePipelineCache(dev->instance, device, pCreateInfo, NULL,
1547ec681f3Smrg                                  &cache_handle);
1557ec681f3Smrg
1567ec681f3Smrg   *pPipelineCache = cache_handle;
1577ec681f3Smrg
1587ec681f3Smrg   return VK_SUCCESS;
1597ec681f3Smrg}
1607ec681f3Smrg
1617ec681f3Smrgvoid
1627ec681f3Smrgvn_DestroyPipelineCache(VkDevice device,
1637ec681f3Smrg                        VkPipelineCache pipelineCache,
1647ec681f3Smrg                        const VkAllocationCallbacks *pAllocator)
1657ec681f3Smrg{
1667ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1677ec681f3Smrg   struct vn_pipeline_cache *cache =
1687ec681f3Smrg      vn_pipeline_cache_from_handle(pipelineCache);
1697ec681f3Smrg   const VkAllocationCallbacks *alloc =
1707ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
1717ec681f3Smrg
1727ec681f3Smrg   if (!cache)
1737ec681f3Smrg      return;
1747ec681f3Smrg
1757ec681f3Smrg   vn_async_vkDestroyPipelineCache(dev->instance, device, pipelineCache,
1767ec681f3Smrg                                   NULL);
1777ec681f3Smrg
1787ec681f3Smrg   vn_object_base_fini(&cache->base);
1797ec681f3Smrg   vk_free(alloc, cache);
1807ec681f3Smrg}
1817ec681f3Smrg
1827ec681f3SmrgVkResult
1837ec681f3Smrgvn_GetPipelineCacheData(VkDevice device,
1847ec681f3Smrg                        VkPipelineCache pipelineCache,
1857ec681f3Smrg                        size_t *pDataSize,
1867ec681f3Smrg                        void *pData)
1877ec681f3Smrg{
1887ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1897ec681f3Smrg   struct vn_physical_device *physical_dev = dev->physical_device;
1907ec681f3Smrg
1917ec681f3Smrg   struct vk_pipeline_cache_header *header = pData;
1927ec681f3Smrg   VkResult result;
1937ec681f3Smrg   if (!pData) {
1947ec681f3Smrg      result = vn_call_vkGetPipelineCacheData(dev->instance, device,
1957ec681f3Smrg                                              pipelineCache, pDataSize, NULL);
1967ec681f3Smrg      if (result != VK_SUCCESS)
1977ec681f3Smrg         return vn_error(dev->instance, result);
1987ec681f3Smrg
1997ec681f3Smrg      *pDataSize += sizeof(*header);
2007ec681f3Smrg      return VK_SUCCESS;
2017ec681f3Smrg   }
2027ec681f3Smrg
2037ec681f3Smrg   if (*pDataSize <= sizeof(*header)) {
2047ec681f3Smrg      *pDataSize = 0;
2057ec681f3Smrg      return VK_INCOMPLETE;
2067ec681f3Smrg   }
2077ec681f3Smrg
2087ec681f3Smrg   const VkPhysicalDeviceProperties *props =
2097ec681f3Smrg      &physical_dev->properties.properties;
2107ec681f3Smrg   header->header_size = sizeof(*header);
2117ec681f3Smrg   header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
2127ec681f3Smrg   header->vendor_id = props->vendorID;
2137ec681f3Smrg   header->device_id = props->deviceID;
2147ec681f3Smrg   memcpy(header->uuid, props->pipelineCacheUUID, VK_UUID_SIZE);
2157ec681f3Smrg
2167ec681f3Smrg   *pDataSize -= header->header_size;
2177ec681f3Smrg   result =
2187ec681f3Smrg      vn_call_vkGetPipelineCacheData(dev->instance, device, pipelineCache,
2197ec681f3Smrg                                     pDataSize, pData + header->header_size);
2207ec681f3Smrg   if (result < VK_SUCCESS)
2217ec681f3Smrg      return vn_error(dev->instance, result);
2227ec681f3Smrg
2237ec681f3Smrg   *pDataSize += header->header_size;
2247ec681f3Smrg
2257ec681f3Smrg   return result;
2267ec681f3Smrg}
2277ec681f3Smrg
2287ec681f3SmrgVkResult
2297ec681f3Smrgvn_MergePipelineCaches(VkDevice device,
2307ec681f3Smrg                       VkPipelineCache dstCache,
2317ec681f3Smrg                       uint32_t srcCacheCount,
2327ec681f3Smrg                       const VkPipelineCache *pSrcCaches)
2337ec681f3Smrg{
2347ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2357ec681f3Smrg
2367ec681f3Smrg   vn_async_vkMergePipelineCaches(dev->instance, device, dstCache,
2377ec681f3Smrg                                  srcCacheCount, pSrcCaches);
2387ec681f3Smrg
2397ec681f3Smrg   return VK_SUCCESS;
2407ec681f3Smrg}
2417ec681f3Smrg
2427ec681f3Smrg/* pipeline commands */
2437ec681f3Smrg
2447ec681f3Smrgstatic const VkGraphicsPipelineCreateInfo *
2457ec681f3Smrgvn_fix_graphics_pipeline_create_info(
2467ec681f3Smrg   struct vn_device *dev,
2477ec681f3Smrg   uint32_t create_info_count,
2487ec681f3Smrg   const VkGraphicsPipelineCreateInfo *create_infos,
2497ec681f3Smrg   const VkAllocationCallbacks *alloc,
2507ec681f3Smrg   VkGraphicsPipelineCreateInfo **out)
2517ec681f3Smrg{
2527ec681f3Smrg   VkGraphicsPipelineCreateInfo *infos = NULL;
2537ec681f3Smrg   bool has_ignored_state = false;
2547ec681f3Smrg
2557ec681f3Smrg   for (uint32_t i = 0; i < create_info_count; i++) {
2567ec681f3Smrg      if (create_infos[i].pRasterizationState->rasterizerDiscardEnable ==
2577ec681f3Smrg          VK_FALSE)
2587ec681f3Smrg         continue;
2597ec681f3Smrg
2607ec681f3Smrg      if (create_infos[i].pViewportState ||
2617ec681f3Smrg          create_infos[i].pMultisampleState ||
2627ec681f3Smrg          create_infos[i].pDepthStencilState ||
2637ec681f3Smrg          create_infos[i].pColorBlendState) {
2647ec681f3Smrg         has_ignored_state = true;
2657ec681f3Smrg         break;
2667ec681f3Smrg      }
2677ec681f3Smrg   }
2687ec681f3Smrg
2697ec681f3Smrg   if (!has_ignored_state)
2707ec681f3Smrg      return create_infos;
2717ec681f3Smrg
2727ec681f3Smrg   infos = vk_alloc(alloc, sizeof(*infos) * create_info_count,
2737ec681f3Smrg                    VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2747ec681f3Smrg   if (!infos)
2757ec681f3Smrg      return NULL;
2767ec681f3Smrg
2777ec681f3Smrg   memcpy(infos, create_infos, sizeof(*infos) * create_info_count);
2787ec681f3Smrg
2797ec681f3Smrg   for (uint32_t i = 0; i < create_info_count; i++) {
2807ec681f3Smrg      if (infos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE)
2817ec681f3Smrg         continue;
2827ec681f3Smrg
2837ec681f3Smrg      infos[i].pViewportState = NULL;
2847ec681f3Smrg      infos[i].pMultisampleState = NULL;
2857ec681f3Smrg      infos[i].pDepthStencilState = NULL;
2867ec681f3Smrg      infos[i].pColorBlendState = NULL;
2877ec681f3Smrg   }
2887ec681f3Smrg
2897ec681f3Smrg   *out = infos;
2907ec681f3Smrg   return infos;
2917ec681f3Smrg}
2927ec681f3Smrg
2937ec681f3SmrgVkResult
2947ec681f3Smrgvn_CreateGraphicsPipelines(VkDevice device,
2957ec681f3Smrg                           VkPipelineCache pipelineCache,
2967ec681f3Smrg                           uint32_t createInfoCount,
2977ec681f3Smrg                           const VkGraphicsPipelineCreateInfo *pCreateInfos,
2987ec681f3Smrg                           const VkAllocationCallbacks *pAllocator,
2997ec681f3Smrg                           VkPipeline *pPipelines)
3007ec681f3Smrg{
3017ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3027ec681f3Smrg   const VkAllocationCallbacks *alloc =
3037ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
3047ec681f3Smrg   VkGraphicsPipelineCreateInfo *local_infos = NULL;
3057ec681f3Smrg
3067ec681f3Smrg   pCreateInfos = vn_fix_graphics_pipeline_create_info(
3077ec681f3Smrg      dev, createInfoCount, pCreateInfos, alloc, &local_infos);
3087ec681f3Smrg   if (!pCreateInfos)
3097ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
3107ec681f3Smrg
3117ec681f3Smrg   for (uint32_t i = 0; i < createInfoCount; i++) {
3127ec681f3Smrg      struct vn_pipeline *pipeline =
3137ec681f3Smrg         vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN,
3147ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
3157ec681f3Smrg      if (!pipeline) {
3167ec681f3Smrg         for (uint32_t j = 0; j < i; j++)
3177ec681f3Smrg            vk_free(alloc, vn_pipeline_from_handle(pPipelines[j]));
3187ec681f3Smrg
3197ec681f3Smrg         if (local_infos)
3207ec681f3Smrg            vk_free(alloc, local_infos);
3217ec681f3Smrg
3227ec681f3Smrg         memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount);
3237ec681f3Smrg         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
3247ec681f3Smrg      }
3257ec681f3Smrg
3267ec681f3Smrg      vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE,
3277ec681f3Smrg                          &dev->base);
3287ec681f3Smrg
3297ec681f3Smrg      VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline);
3307ec681f3Smrg      pPipelines[i] = pipeline_handle;
3317ec681f3Smrg   }
3327ec681f3Smrg
3337ec681f3Smrg   vn_async_vkCreateGraphicsPipelines(dev->instance, device, pipelineCache,
3347ec681f3Smrg                                      createInfoCount, pCreateInfos, NULL,
3357ec681f3Smrg                                      pPipelines);
3367ec681f3Smrg
3377ec681f3Smrg   if (local_infos)
3387ec681f3Smrg      vk_free(alloc, local_infos);
3397ec681f3Smrg
3407ec681f3Smrg   return VK_SUCCESS;
3417ec681f3Smrg}
3427ec681f3Smrg
3437ec681f3SmrgVkResult
3447ec681f3Smrgvn_CreateComputePipelines(VkDevice device,
3457ec681f3Smrg                          VkPipelineCache pipelineCache,
3467ec681f3Smrg                          uint32_t createInfoCount,
3477ec681f3Smrg                          const VkComputePipelineCreateInfo *pCreateInfos,
3487ec681f3Smrg                          const VkAllocationCallbacks *pAllocator,
3497ec681f3Smrg                          VkPipeline *pPipelines)
3507ec681f3Smrg{
3517ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3527ec681f3Smrg   const VkAllocationCallbacks *alloc =
3537ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
3547ec681f3Smrg
3557ec681f3Smrg   for (uint32_t i = 0; i < createInfoCount; i++) {
3567ec681f3Smrg      struct vn_pipeline *pipeline =
3577ec681f3Smrg         vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN,
3587ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
3597ec681f3Smrg      if (!pipeline) {
3607ec681f3Smrg         for (uint32_t j = 0; j < i; j++)
3617ec681f3Smrg            vk_free(alloc, vn_pipeline_from_handle(pPipelines[j]));
3627ec681f3Smrg         memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount);
3637ec681f3Smrg         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
3647ec681f3Smrg      }
3657ec681f3Smrg
3667ec681f3Smrg      vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE,
3677ec681f3Smrg                          &dev->base);
3687ec681f3Smrg
3697ec681f3Smrg      VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline);
3707ec681f3Smrg      pPipelines[i] = pipeline_handle;
3717ec681f3Smrg   }
3727ec681f3Smrg
3737ec681f3Smrg   vn_async_vkCreateComputePipelines(dev->instance, device, pipelineCache,
3747ec681f3Smrg                                     createInfoCount, pCreateInfos, NULL,
3757ec681f3Smrg                                     pPipelines);
3767ec681f3Smrg
3777ec681f3Smrg   return VK_SUCCESS;
3787ec681f3Smrg}
3797ec681f3Smrg
3807ec681f3Smrgvoid
3817ec681f3Smrgvn_DestroyPipeline(VkDevice device,
3827ec681f3Smrg                   VkPipeline _pipeline,
3837ec681f3Smrg                   const VkAllocationCallbacks *pAllocator)
3847ec681f3Smrg{
3857ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3867ec681f3Smrg   struct vn_pipeline *pipeline = vn_pipeline_from_handle(_pipeline);
3877ec681f3Smrg   const VkAllocationCallbacks *alloc =
3887ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
3897ec681f3Smrg
3907ec681f3Smrg   if (!pipeline)
3917ec681f3Smrg      return;
3927ec681f3Smrg
3937ec681f3Smrg   vn_async_vkDestroyPipeline(dev->instance, device, _pipeline, NULL);
3947ec681f3Smrg
3957ec681f3Smrg   vn_object_base_fini(&pipeline->base);
3967ec681f3Smrg   vk_free(alloc, pipeline);
3977ec681f3Smrg}
398