1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2019 Google LLC
3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * based in part on anv and radv which are:
6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
9bf215546Sopenharmony_ci */
10bf215546Sopenharmony_ci
11bf215546Sopenharmony_ci#include "vn_pipeline.h"
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_pipeline.h"
14bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_pipeline_cache.h"
15bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_pipeline_layout.h"
16bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_shader_module.h"
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_ci#include "vn_device.h"
19bf215546Sopenharmony_ci#include "vn_physical_device.h"
20bf215546Sopenharmony_ci
21bf215546Sopenharmony_ci/* shader module commands */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ciVkResult
24bf215546Sopenharmony_civn_CreateShaderModule(VkDevice device,
25bf215546Sopenharmony_ci                      const VkShaderModuleCreateInfo *pCreateInfo,
26bf215546Sopenharmony_ci                      const VkAllocationCallbacks *pAllocator,
27bf215546Sopenharmony_ci                      VkShaderModule *pShaderModule)
28bf215546Sopenharmony_ci{
29bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
30bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
31bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci   struct vn_shader_module *mod =
34bf215546Sopenharmony_ci      vk_zalloc(alloc, sizeof(*mod), VN_DEFAULT_ALIGN,
35bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
36bf215546Sopenharmony_ci   if (!mod)
37bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci   vn_object_base_init(&mod->base, VK_OBJECT_TYPE_SHADER_MODULE, &dev->base);
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   VkShaderModule mod_handle = vn_shader_module_to_handle(mod);
42bf215546Sopenharmony_ci   vn_async_vkCreateShaderModule(dev->instance, device, pCreateInfo, NULL,
43bf215546Sopenharmony_ci                                 &mod_handle);
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   *pShaderModule = mod_handle;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   return VK_SUCCESS;
48bf215546Sopenharmony_ci}
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_civoid
51bf215546Sopenharmony_civn_DestroyShaderModule(VkDevice device,
52bf215546Sopenharmony_ci                       VkShaderModule shaderModule,
53bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator)
54bf215546Sopenharmony_ci{
55bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
56bf215546Sopenharmony_ci   struct vn_shader_module *mod = vn_shader_module_from_handle(shaderModule);
57bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
58bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   if (!mod)
61bf215546Sopenharmony_ci      return;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   vn_async_vkDestroyShaderModule(dev->instance, device, shaderModule, NULL);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   vn_object_base_fini(&mod->base);
66bf215546Sopenharmony_ci   vk_free(alloc, mod);
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci/* pipeline layout commands */
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ciVkResult
72bf215546Sopenharmony_civn_CreatePipelineLayout(VkDevice device,
73bf215546Sopenharmony_ci                        const VkPipelineLayoutCreateInfo *pCreateInfo,
74bf215546Sopenharmony_ci                        const VkAllocationCallbacks *pAllocator,
75bf215546Sopenharmony_ci                        VkPipelineLayout *pPipelineLayout)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
78bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
79bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   struct vn_pipeline_layout *layout =
82bf215546Sopenharmony_ci      vk_zalloc(alloc, sizeof(*layout), VN_DEFAULT_ALIGN,
83bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
84bf215546Sopenharmony_ci   if (!layout)
85bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   vn_object_base_init(&layout->base, VK_OBJECT_TYPE_PIPELINE_LAYOUT,
88bf215546Sopenharmony_ci                       &dev->base);
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   VkPipelineLayout layout_handle = vn_pipeline_layout_to_handle(layout);
91bf215546Sopenharmony_ci   vn_async_vkCreatePipelineLayout(dev->instance, device, pCreateInfo, NULL,
92bf215546Sopenharmony_ci                                   &layout_handle);
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   *pPipelineLayout = layout_handle;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   return VK_SUCCESS;
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_civoid
100bf215546Sopenharmony_civn_DestroyPipelineLayout(VkDevice device,
101bf215546Sopenharmony_ci                         VkPipelineLayout pipelineLayout,
102bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator)
103bf215546Sopenharmony_ci{
104bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
105bf215546Sopenharmony_ci   struct vn_pipeline_layout *layout =
106bf215546Sopenharmony_ci      vn_pipeline_layout_from_handle(pipelineLayout);
107bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
108bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   if (!layout)
111bf215546Sopenharmony_ci      return;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   vn_async_vkDestroyPipelineLayout(dev->instance, device, pipelineLayout,
114bf215546Sopenharmony_ci                                    NULL);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   vn_object_base_fini(&layout->base);
117bf215546Sopenharmony_ci   vk_free(alloc, layout);
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci/* pipeline cache commands */
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ciVkResult
123bf215546Sopenharmony_civn_CreatePipelineCache(VkDevice device,
124bf215546Sopenharmony_ci                       const VkPipelineCacheCreateInfo *pCreateInfo,
125bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator,
126bf215546Sopenharmony_ci                       VkPipelineCache *pPipelineCache)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   VN_TRACE_FUNC();
129bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
130bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
131bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   struct vn_pipeline_cache *cache =
134bf215546Sopenharmony_ci      vk_zalloc(alloc, sizeof(*cache), VN_DEFAULT_ALIGN,
135bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
136bf215546Sopenharmony_ci   if (!cache)
137bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   vn_object_base_init(&cache->base, VK_OBJECT_TYPE_PIPELINE_CACHE,
140bf215546Sopenharmony_ci                       &dev->base);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   VkPipelineCacheCreateInfo local_create_info;
143bf215546Sopenharmony_ci   if (pCreateInfo->initialDataSize) {
144bf215546Sopenharmony_ci      const struct vk_pipeline_cache_header *header =
145bf215546Sopenharmony_ci         pCreateInfo->pInitialData;
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci      local_create_info = *pCreateInfo;
148bf215546Sopenharmony_ci      local_create_info.initialDataSize -= header->header_size;
149bf215546Sopenharmony_ci      local_create_info.pInitialData += header->header_size;
150bf215546Sopenharmony_ci      pCreateInfo = &local_create_info;
151bf215546Sopenharmony_ci   }
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   VkPipelineCache cache_handle = vn_pipeline_cache_to_handle(cache);
154bf215546Sopenharmony_ci   vn_async_vkCreatePipelineCache(dev->instance, device, pCreateInfo, NULL,
155bf215546Sopenharmony_ci                                  &cache_handle);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   *pPipelineCache = cache_handle;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   return VK_SUCCESS;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_civoid
163bf215546Sopenharmony_civn_DestroyPipelineCache(VkDevice device,
164bf215546Sopenharmony_ci                        VkPipelineCache pipelineCache,
165bf215546Sopenharmony_ci                        const VkAllocationCallbacks *pAllocator)
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci   VN_TRACE_FUNC();
168bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
169bf215546Sopenharmony_ci   struct vn_pipeline_cache *cache =
170bf215546Sopenharmony_ci      vn_pipeline_cache_from_handle(pipelineCache);
171bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
172bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   if (!cache)
175bf215546Sopenharmony_ci      return;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   vn_async_vkDestroyPipelineCache(dev->instance, device, pipelineCache,
178bf215546Sopenharmony_ci                                   NULL);
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   vn_object_base_fini(&cache->base);
181bf215546Sopenharmony_ci   vk_free(alloc, cache);
182bf215546Sopenharmony_ci}
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ciVkResult
185bf215546Sopenharmony_civn_GetPipelineCacheData(VkDevice device,
186bf215546Sopenharmony_ci                        VkPipelineCache pipelineCache,
187bf215546Sopenharmony_ci                        size_t *pDataSize,
188bf215546Sopenharmony_ci                        void *pData)
189bf215546Sopenharmony_ci{
190bf215546Sopenharmony_ci   VN_TRACE_FUNC();
191bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
192bf215546Sopenharmony_ci   struct vn_physical_device *physical_dev = dev->physical_device;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   struct vk_pipeline_cache_header *header = pData;
195bf215546Sopenharmony_ci   VkResult result;
196bf215546Sopenharmony_ci   if (!pData) {
197bf215546Sopenharmony_ci      result = vn_call_vkGetPipelineCacheData(dev->instance, device,
198bf215546Sopenharmony_ci                                              pipelineCache, pDataSize, NULL);
199bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
200bf215546Sopenharmony_ci         return vn_error(dev->instance, result);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci      *pDataSize += sizeof(*header);
203bf215546Sopenharmony_ci      return VK_SUCCESS;
204bf215546Sopenharmony_ci   }
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   if (*pDataSize <= sizeof(*header)) {
207bf215546Sopenharmony_ci      *pDataSize = 0;
208bf215546Sopenharmony_ci      return VK_INCOMPLETE;
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   const VkPhysicalDeviceProperties *props =
212bf215546Sopenharmony_ci      &physical_dev->properties.vulkan_1_0;
213bf215546Sopenharmony_ci   header->header_size = sizeof(*header);
214bf215546Sopenharmony_ci   header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
215bf215546Sopenharmony_ci   header->vendor_id = props->vendorID;
216bf215546Sopenharmony_ci   header->device_id = props->deviceID;
217bf215546Sopenharmony_ci   memcpy(header->uuid, props->pipelineCacheUUID, VK_UUID_SIZE);
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   *pDataSize -= header->header_size;
220bf215546Sopenharmony_ci   result =
221bf215546Sopenharmony_ci      vn_call_vkGetPipelineCacheData(dev->instance, device, pipelineCache,
222bf215546Sopenharmony_ci                                     pDataSize, pData + header->header_size);
223bf215546Sopenharmony_ci   if (result < VK_SUCCESS)
224bf215546Sopenharmony_ci      return vn_error(dev->instance, result);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   *pDataSize += header->header_size;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   return result;
229bf215546Sopenharmony_ci}
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ciVkResult
232bf215546Sopenharmony_civn_MergePipelineCaches(VkDevice device,
233bf215546Sopenharmony_ci                       VkPipelineCache dstCache,
234bf215546Sopenharmony_ci                       uint32_t srcCacheCount,
235bf215546Sopenharmony_ci                       const VkPipelineCache *pSrcCaches)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   VN_TRACE_FUNC();
238bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   vn_async_vkMergePipelineCaches(dev->instance, device, dstCache,
241bf215546Sopenharmony_ci                                  srcCacheCount, pSrcCaches);
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   return VK_SUCCESS;
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci/* pipeline commands */
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_cistruct vn_graphics_pipeline_create_info_fix {
249bf215546Sopenharmony_ci   bool ignore_tessellation_state;
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   /* Ignore the following:
252bf215546Sopenharmony_ci    *    pViewportState
253bf215546Sopenharmony_ci    *    pMultisampleState
254bf215546Sopenharmony_ci    *    pDepthStencilState
255bf215546Sopenharmony_ci    *    pColorBlendState
256bf215546Sopenharmony_ci    */
257bf215546Sopenharmony_ci   bool ignore_raster_dedicated_states;
258bf215546Sopenharmony_ci};
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_cistatic const VkGraphicsPipelineCreateInfo *
261bf215546Sopenharmony_civn_fix_graphics_pipeline_create_info(
262bf215546Sopenharmony_ci   struct vn_device *dev,
263bf215546Sopenharmony_ci   uint32_t create_info_count,
264bf215546Sopenharmony_ci   const VkGraphicsPipelineCreateInfo *create_infos,
265bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc,
266bf215546Sopenharmony_ci   VkGraphicsPipelineCreateInfo **out)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci   VN_TRACE_FUNC();
269bf215546Sopenharmony_ci   VkGraphicsPipelineCreateInfo *infos = NULL;
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   /* Defer allocation until we find a needed fix. */
272bf215546Sopenharmony_ci   struct vn_graphics_pipeline_create_info_fix *fixes = NULL;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   for (uint32_t i = 0; i < create_info_count; i++) {
275bf215546Sopenharmony_ci      const VkGraphicsPipelineCreateInfo *info = &create_infos[i];
276bf215546Sopenharmony_ci      struct vn_graphics_pipeline_create_info_fix fix = { 0 };
277bf215546Sopenharmony_ci      bool any_fix = false;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci      VkShaderStageFlags stages = 0;
280bf215546Sopenharmony_ci      for (uint32_t j = 0; j < info->stageCount; j++) {
281bf215546Sopenharmony_ci         stages |= info->pStages[j].stage;
282bf215546Sopenharmony_ci      }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci      /* Fix pTessellationState?
285bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-pStages-00731
286bf215546Sopenharmony_ci       */
287bf215546Sopenharmony_ci      if (info->pTessellationState &&
288bf215546Sopenharmony_ci          (!(stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ||
289bf215546Sopenharmony_ci           !(stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))) {
290bf215546Sopenharmony_ci         fix.ignore_tessellation_state = true;
291bf215546Sopenharmony_ci         any_fix = true;
292bf215546Sopenharmony_ci      }
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci      bool ignore_raster_dedicated_states =
295bf215546Sopenharmony_ci         !info->pRasterizationState ||
296bf215546Sopenharmony_ci         info->pRasterizationState->rasterizerDiscardEnable == VK_TRUE;
297bf215546Sopenharmony_ci      if (ignore_raster_dedicated_states && info->pDynamicState) {
298bf215546Sopenharmony_ci         for (uint32_t j = 0; j < info->pDynamicState->dynamicStateCount;
299bf215546Sopenharmony_ci              j++) {
300bf215546Sopenharmony_ci            if (info->pDynamicState->pDynamicStates[j] ==
301bf215546Sopenharmony_ci                VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE) {
302bf215546Sopenharmony_ci               ignore_raster_dedicated_states = false;
303bf215546Sopenharmony_ci               break;
304bf215546Sopenharmony_ci            }
305bf215546Sopenharmony_ci         }
306bf215546Sopenharmony_ci      }
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci      /* FIXME: Conditions for ignoring pDepthStencilState and
309bf215546Sopenharmony_ci       * pColorBlendState miss some cases that depend on the render pass. Make
310bf215546Sopenharmony_ci       * them agree with the VUIDs.
311bf215546Sopenharmony_ci       */
312bf215546Sopenharmony_ci      if (ignore_raster_dedicated_states &&
313bf215546Sopenharmony_ci          (info->pViewportState || info->pMultisampleState ||
314bf215546Sopenharmony_ci           info->pDepthStencilState || info->pColorBlendState)) {
315bf215546Sopenharmony_ci         fix.ignore_raster_dedicated_states = true;
316bf215546Sopenharmony_ci         any_fix = true;
317bf215546Sopenharmony_ci      }
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci      if (any_fix) {
320bf215546Sopenharmony_ci         if (!fixes) {
321bf215546Sopenharmony_ci            fixes = vk_zalloc(alloc, create_info_count * sizeof(fixes[0]),
322bf215546Sopenharmony_ci                              VN_DEFAULT_ALIGN,
323bf215546Sopenharmony_ci                              VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
324bf215546Sopenharmony_ci            if (!fixes)
325bf215546Sopenharmony_ci               return NULL;
326bf215546Sopenharmony_ci         }
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci         fixes[i] = fix;
329bf215546Sopenharmony_ci      }
330bf215546Sopenharmony_ci   }
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   if (!fixes)
333bf215546Sopenharmony_ci      return create_infos;
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci   infos = vk_alloc(alloc, sizeof(*infos) * create_info_count,
336bf215546Sopenharmony_ci                    VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
337bf215546Sopenharmony_ci   if (!infos) {
338bf215546Sopenharmony_ci      vk_free(alloc, fixes);
339bf215546Sopenharmony_ci      return NULL;
340bf215546Sopenharmony_ci   }
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   memcpy(infos, create_infos, sizeof(*infos) * create_info_count);
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   for (uint32_t i = 0; i < create_info_count; i++) {
345bf215546Sopenharmony_ci      VkGraphicsPipelineCreateInfo *info = &infos[i];
346bf215546Sopenharmony_ci      struct vn_graphics_pipeline_create_info_fix fix = fixes[i];
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci      if (fix.ignore_tessellation_state)
349bf215546Sopenharmony_ci         info->pTessellationState = NULL;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci      if (fix.ignore_raster_dedicated_states) {
352bf215546Sopenharmony_ci         info->pViewportState = NULL;
353bf215546Sopenharmony_ci         info->pMultisampleState = NULL;
354bf215546Sopenharmony_ci         info->pDepthStencilState = NULL;
355bf215546Sopenharmony_ci         info->pColorBlendState = NULL;
356bf215546Sopenharmony_ci      }
357bf215546Sopenharmony_ci   }
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   vk_free(alloc, fixes);
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci   *out = infos;
362bf215546Sopenharmony_ci   return infos;
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ciVkResult
366bf215546Sopenharmony_civn_CreateGraphicsPipelines(VkDevice device,
367bf215546Sopenharmony_ci                           VkPipelineCache pipelineCache,
368bf215546Sopenharmony_ci                           uint32_t createInfoCount,
369bf215546Sopenharmony_ci                           const VkGraphicsPipelineCreateInfo *pCreateInfos,
370bf215546Sopenharmony_ci                           const VkAllocationCallbacks *pAllocator,
371bf215546Sopenharmony_ci                           VkPipeline *pPipelines)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   VN_TRACE_FUNC();
374bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
375bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
376bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
377bf215546Sopenharmony_ci   VkGraphicsPipelineCreateInfo *local_infos = NULL;
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   pCreateInfos = vn_fix_graphics_pipeline_create_info(
380bf215546Sopenharmony_ci      dev, createInfoCount, pCreateInfos, alloc, &local_infos);
381bf215546Sopenharmony_ci   if (!pCreateInfos)
382bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   for (uint32_t i = 0; i < createInfoCount; i++) {
385bf215546Sopenharmony_ci      struct vn_pipeline *pipeline =
386bf215546Sopenharmony_ci         vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN,
387bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
388bf215546Sopenharmony_ci      if (!pipeline) {
389bf215546Sopenharmony_ci         for (uint32_t j = 0; j < i; j++)
390bf215546Sopenharmony_ci            vk_free(alloc, vn_pipeline_from_handle(pPipelines[j]));
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci         if (local_infos)
393bf215546Sopenharmony_ci            vk_free(alloc, local_infos);
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci         memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount);
396bf215546Sopenharmony_ci         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
397bf215546Sopenharmony_ci      }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci      vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE,
400bf215546Sopenharmony_ci                          &dev->base);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci      VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline);
403bf215546Sopenharmony_ci      pPipelines[i] = pipeline_handle;
404bf215546Sopenharmony_ci   }
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   vn_async_vkCreateGraphicsPipelines(dev->instance, device, pipelineCache,
407bf215546Sopenharmony_ci                                      createInfoCount, pCreateInfos, NULL,
408bf215546Sopenharmony_ci                                      pPipelines);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   if (local_infos)
411bf215546Sopenharmony_ci      vk_free(alloc, local_infos);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   return VK_SUCCESS;
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ciVkResult
417bf215546Sopenharmony_civn_CreateComputePipelines(VkDevice device,
418bf215546Sopenharmony_ci                          VkPipelineCache pipelineCache,
419bf215546Sopenharmony_ci                          uint32_t createInfoCount,
420bf215546Sopenharmony_ci                          const VkComputePipelineCreateInfo *pCreateInfos,
421bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
422bf215546Sopenharmony_ci                          VkPipeline *pPipelines)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   VN_TRACE_FUNC();
425bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
426bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
427bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   for (uint32_t i = 0; i < createInfoCount; i++) {
430bf215546Sopenharmony_ci      struct vn_pipeline *pipeline =
431bf215546Sopenharmony_ci         vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN,
432bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
433bf215546Sopenharmony_ci      if (!pipeline) {
434bf215546Sopenharmony_ci         for (uint32_t j = 0; j < i; j++)
435bf215546Sopenharmony_ci            vk_free(alloc, vn_pipeline_from_handle(pPipelines[j]));
436bf215546Sopenharmony_ci         memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount);
437bf215546Sopenharmony_ci         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
438bf215546Sopenharmony_ci      }
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci      vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE,
441bf215546Sopenharmony_ci                          &dev->base);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline);
444bf215546Sopenharmony_ci      pPipelines[i] = pipeline_handle;
445bf215546Sopenharmony_ci   }
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   vn_async_vkCreateComputePipelines(dev->instance, device, pipelineCache,
448bf215546Sopenharmony_ci                                     createInfoCount, pCreateInfos, NULL,
449bf215546Sopenharmony_ci                                     pPipelines);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   return VK_SUCCESS;
452bf215546Sopenharmony_ci}
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_civoid
455bf215546Sopenharmony_civn_DestroyPipeline(VkDevice device,
456bf215546Sopenharmony_ci                   VkPipeline _pipeline,
457bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator)
458bf215546Sopenharmony_ci{
459bf215546Sopenharmony_ci   VN_TRACE_FUNC();
460bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
461bf215546Sopenharmony_ci   struct vn_pipeline *pipeline = vn_pipeline_from_handle(_pipeline);
462bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
463bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   if (!pipeline)
466bf215546Sopenharmony_ci      return;
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   vn_async_vkDestroyPipeline(dev->instance, device, _pipeline, NULL);
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   vn_object_base_fini(&pipeline->base);
471bf215546Sopenharmony_ci   vk_free(alloc, pipeline);
472bf215546Sopenharmony_ci}
473