1/* 2 * Copyright 2019 Google LLC 3 * SPDX-License-Identifier: MIT 4 * 5 * based in part on anv and radv which are: 6 * Copyright © 2015 Intel Corporation 7 * Copyright © 2016 Red Hat. 8 * Copyright © 2016 Bas Nieuwenhuizen 9 */ 10 11#include "vn_pipeline.h" 12 13#include "venus-protocol/vn_protocol_driver_pipeline.h" 14#include "venus-protocol/vn_protocol_driver_pipeline_cache.h" 15#include "venus-protocol/vn_protocol_driver_pipeline_layout.h" 16#include "venus-protocol/vn_protocol_driver_shader_module.h" 17 18#include "vn_device.h" 19#include "vn_physical_device.h" 20 21/* shader module commands */ 22 23VkResult 24vn_CreateShaderModule(VkDevice device, 25 const VkShaderModuleCreateInfo *pCreateInfo, 26 const VkAllocationCallbacks *pAllocator, 27 VkShaderModule *pShaderModule) 28{ 29 struct vn_device *dev = vn_device_from_handle(device); 30 const VkAllocationCallbacks *alloc = 31 pAllocator ? pAllocator : &dev->base.base.alloc; 32 33 struct vn_shader_module *mod = 34 vk_zalloc(alloc, sizeof(*mod), VN_DEFAULT_ALIGN, 35 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 36 if (!mod) 37 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 38 39 vn_object_base_init(&mod->base, VK_OBJECT_TYPE_SHADER_MODULE, &dev->base); 40 41 VkShaderModule mod_handle = vn_shader_module_to_handle(mod); 42 vn_async_vkCreateShaderModule(dev->instance, device, pCreateInfo, NULL, 43 &mod_handle); 44 45 *pShaderModule = mod_handle; 46 47 return VK_SUCCESS; 48} 49 50void 51vn_DestroyShaderModule(VkDevice device, 52 VkShaderModule shaderModule, 53 const VkAllocationCallbacks *pAllocator) 54{ 55 struct vn_device *dev = vn_device_from_handle(device); 56 struct vn_shader_module *mod = vn_shader_module_from_handle(shaderModule); 57 const VkAllocationCallbacks *alloc = 58 pAllocator ? pAllocator : &dev->base.base.alloc; 59 60 if (!mod) 61 return; 62 63 vn_async_vkDestroyShaderModule(dev->instance, device, shaderModule, NULL); 64 65 vn_object_base_fini(&mod->base); 66 vk_free(alloc, mod); 67} 68 69/* pipeline layout commands */ 70 71VkResult 72vn_CreatePipelineLayout(VkDevice device, 73 const VkPipelineLayoutCreateInfo *pCreateInfo, 74 const VkAllocationCallbacks *pAllocator, 75 VkPipelineLayout *pPipelineLayout) 76{ 77 struct vn_device *dev = vn_device_from_handle(device); 78 const VkAllocationCallbacks *alloc = 79 pAllocator ? pAllocator : &dev->base.base.alloc; 80 81 struct vn_pipeline_layout *layout = 82 vk_zalloc(alloc, sizeof(*layout), VN_DEFAULT_ALIGN, 83 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 84 if (!layout) 85 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 86 87 vn_object_base_init(&layout->base, VK_OBJECT_TYPE_PIPELINE_LAYOUT, 88 &dev->base); 89 90 VkPipelineLayout layout_handle = vn_pipeline_layout_to_handle(layout); 91 vn_async_vkCreatePipelineLayout(dev->instance, device, pCreateInfo, NULL, 92 &layout_handle); 93 94 *pPipelineLayout = layout_handle; 95 96 return VK_SUCCESS; 97} 98 99void 100vn_DestroyPipelineLayout(VkDevice device, 101 VkPipelineLayout pipelineLayout, 102 const VkAllocationCallbacks *pAllocator) 103{ 104 struct vn_device *dev = vn_device_from_handle(device); 105 struct vn_pipeline_layout *layout = 106 vn_pipeline_layout_from_handle(pipelineLayout); 107 const VkAllocationCallbacks *alloc = 108 pAllocator ? pAllocator : &dev->base.base.alloc; 109 110 if (!layout) 111 return; 112 113 vn_async_vkDestroyPipelineLayout(dev->instance, device, pipelineLayout, 114 NULL); 115 116 vn_object_base_fini(&layout->base); 117 vk_free(alloc, layout); 118} 119 120/* pipeline cache commands */ 121 122VkResult 123vn_CreatePipelineCache(VkDevice device, 124 const VkPipelineCacheCreateInfo *pCreateInfo, 125 const VkAllocationCallbacks *pAllocator, 126 VkPipelineCache *pPipelineCache) 127{ 128 struct vn_device *dev = vn_device_from_handle(device); 129 const VkAllocationCallbacks *alloc = 130 pAllocator ? pAllocator : &dev->base.base.alloc; 131 132 struct vn_pipeline_cache *cache = 133 vk_zalloc(alloc, sizeof(*cache), VN_DEFAULT_ALIGN, 134 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 135 if (!cache) 136 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 137 138 vn_object_base_init(&cache->base, VK_OBJECT_TYPE_PIPELINE_CACHE, 139 &dev->base); 140 141 VkPipelineCacheCreateInfo local_create_info; 142 if (pCreateInfo->initialDataSize) { 143 const struct vk_pipeline_cache_header *header = 144 pCreateInfo->pInitialData; 145 146 local_create_info = *pCreateInfo; 147 local_create_info.initialDataSize -= header->header_size; 148 local_create_info.pInitialData += header->header_size; 149 pCreateInfo = &local_create_info; 150 } 151 152 VkPipelineCache cache_handle = vn_pipeline_cache_to_handle(cache); 153 vn_async_vkCreatePipelineCache(dev->instance, device, pCreateInfo, NULL, 154 &cache_handle); 155 156 *pPipelineCache = cache_handle; 157 158 return VK_SUCCESS; 159} 160 161void 162vn_DestroyPipelineCache(VkDevice device, 163 VkPipelineCache pipelineCache, 164 const VkAllocationCallbacks *pAllocator) 165{ 166 struct vn_device *dev = vn_device_from_handle(device); 167 struct vn_pipeline_cache *cache = 168 vn_pipeline_cache_from_handle(pipelineCache); 169 const VkAllocationCallbacks *alloc = 170 pAllocator ? pAllocator : &dev->base.base.alloc; 171 172 if (!cache) 173 return; 174 175 vn_async_vkDestroyPipelineCache(dev->instance, device, pipelineCache, 176 NULL); 177 178 vn_object_base_fini(&cache->base); 179 vk_free(alloc, cache); 180} 181 182VkResult 183vn_GetPipelineCacheData(VkDevice device, 184 VkPipelineCache pipelineCache, 185 size_t *pDataSize, 186 void *pData) 187{ 188 struct vn_device *dev = vn_device_from_handle(device); 189 struct vn_physical_device *physical_dev = dev->physical_device; 190 191 struct vk_pipeline_cache_header *header = pData; 192 VkResult result; 193 if (!pData) { 194 result = vn_call_vkGetPipelineCacheData(dev->instance, device, 195 pipelineCache, pDataSize, NULL); 196 if (result != VK_SUCCESS) 197 return vn_error(dev->instance, result); 198 199 *pDataSize += sizeof(*header); 200 return VK_SUCCESS; 201 } 202 203 if (*pDataSize <= sizeof(*header)) { 204 *pDataSize = 0; 205 return VK_INCOMPLETE; 206 } 207 208 const VkPhysicalDeviceProperties *props = 209 &physical_dev->properties.properties; 210 header->header_size = sizeof(*header); 211 header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE; 212 header->vendor_id = props->vendorID; 213 header->device_id = props->deviceID; 214 memcpy(header->uuid, props->pipelineCacheUUID, VK_UUID_SIZE); 215 216 *pDataSize -= header->header_size; 217 result = 218 vn_call_vkGetPipelineCacheData(dev->instance, device, pipelineCache, 219 pDataSize, pData + header->header_size); 220 if (result < VK_SUCCESS) 221 return vn_error(dev->instance, result); 222 223 *pDataSize += header->header_size; 224 225 return result; 226} 227 228VkResult 229vn_MergePipelineCaches(VkDevice device, 230 VkPipelineCache dstCache, 231 uint32_t srcCacheCount, 232 const VkPipelineCache *pSrcCaches) 233{ 234 struct vn_device *dev = vn_device_from_handle(device); 235 236 vn_async_vkMergePipelineCaches(dev->instance, device, dstCache, 237 srcCacheCount, pSrcCaches); 238 239 return VK_SUCCESS; 240} 241 242/* pipeline commands */ 243 244static const VkGraphicsPipelineCreateInfo * 245vn_fix_graphics_pipeline_create_info( 246 struct vn_device *dev, 247 uint32_t create_info_count, 248 const VkGraphicsPipelineCreateInfo *create_infos, 249 const VkAllocationCallbacks *alloc, 250 VkGraphicsPipelineCreateInfo **out) 251{ 252 VkGraphicsPipelineCreateInfo *infos = NULL; 253 bool has_ignored_state = false; 254 255 for (uint32_t i = 0; i < create_info_count; i++) { 256 if (create_infos[i].pRasterizationState->rasterizerDiscardEnable == 257 VK_FALSE) 258 continue; 259 260 if (create_infos[i].pViewportState || 261 create_infos[i].pMultisampleState || 262 create_infos[i].pDepthStencilState || 263 create_infos[i].pColorBlendState) { 264 has_ignored_state = true; 265 break; 266 } 267 } 268 269 if (!has_ignored_state) 270 return create_infos; 271 272 infos = vk_alloc(alloc, sizeof(*infos) * create_info_count, 273 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 274 if (!infos) 275 return NULL; 276 277 memcpy(infos, create_infos, sizeof(*infos) * create_info_count); 278 279 for (uint32_t i = 0; i < create_info_count; i++) { 280 if (infos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE) 281 continue; 282 283 infos[i].pViewportState = NULL; 284 infos[i].pMultisampleState = NULL; 285 infos[i].pDepthStencilState = NULL; 286 infos[i].pColorBlendState = NULL; 287 } 288 289 *out = infos; 290 return infos; 291} 292 293VkResult 294vn_CreateGraphicsPipelines(VkDevice device, 295 VkPipelineCache pipelineCache, 296 uint32_t createInfoCount, 297 const VkGraphicsPipelineCreateInfo *pCreateInfos, 298 const VkAllocationCallbacks *pAllocator, 299 VkPipeline *pPipelines) 300{ 301 struct vn_device *dev = vn_device_from_handle(device); 302 const VkAllocationCallbacks *alloc = 303 pAllocator ? pAllocator : &dev->base.base.alloc; 304 VkGraphicsPipelineCreateInfo *local_infos = NULL; 305 306 pCreateInfos = vn_fix_graphics_pipeline_create_info( 307 dev, createInfoCount, pCreateInfos, alloc, &local_infos); 308 if (!pCreateInfos) 309 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 310 311 for (uint32_t i = 0; i < createInfoCount; i++) { 312 struct vn_pipeline *pipeline = 313 vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN, 314 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 315 if (!pipeline) { 316 for (uint32_t j = 0; j < i; j++) 317 vk_free(alloc, vn_pipeline_from_handle(pPipelines[j])); 318 319 if (local_infos) 320 vk_free(alloc, local_infos); 321 322 memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount); 323 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 324 } 325 326 vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE, 327 &dev->base); 328 329 VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline); 330 pPipelines[i] = pipeline_handle; 331 } 332 333 vn_async_vkCreateGraphicsPipelines(dev->instance, device, pipelineCache, 334 createInfoCount, pCreateInfos, NULL, 335 pPipelines); 336 337 if (local_infos) 338 vk_free(alloc, local_infos); 339 340 return VK_SUCCESS; 341} 342 343VkResult 344vn_CreateComputePipelines(VkDevice device, 345 VkPipelineCache pipelineCache, 346 uint32_t createInfoCount, 347 const VkComputePipelineCreateInfo *pCreateInfos, 348 const VkAllocationCallbacks *pAllocator, 349 VkPipeline *pPipelines) 350{ 351 struct vn_device *dev = vn_device_from_handle(device); 352 const VkAllocationCallbacks *alloc = 353 pAllocator ? pAllocator : &dev->base.base.alloc; 354 355 for (uint32_t i = 0; i < createInfoCount; i++) { 356 struct vn_pipeline *pipeline = 357 vk_zalloc(alloc, sizeof(*pipeline), VN_DEFAULT_ALIGN, 358 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 359 if (!pipeline) { 360 for (uint32_t j = 0; j < i; j++) 361 vk_free(alloc, vn_pipeline_from_handle(pPipelines[j])); 362 memset(pPipelines, 0, sizeof(*pPipelines) * createInfoCount); 363 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 364 } 365 366 vn_object_base_init(&pipeline->base, VK_OBJECT_TYPE_PIPELINE, 367 &dev->base); 368 369 VkPipeline pipeline_handle = vn_pipeline_to_handle(pipeline); 370 pPipelines[i] = pipeline_handle; 371 } 372 373 vn_async_vkCreateComputePipelines(dev->instance, device, pipelineCache, 374 createInfoCount, pCreateInfos, NULL, 375 pPipelines); 376 377 return VK_SUCCESS; 378} 379 380void 381vn_DestroyPipeline(VkDevice device, 382 VkPipeline _pipeline, 383 const VkAllocationCallbacks *pAllocator) 384{ 385 struct vn_device *dev = vn_device_from_handle(device); 386 struct vn_pipeline *pipeline = vn_pipeline_from_handle(_pipeline); 387 const VkAllocationCallbacks *alloc = 388 pAllocator ? pAllocator : &dev->base.base.alloc; 389 390 if (!pipeline) 391 return; 392 393 vn_async_vkDestroyPipeline(dev->instance, device, _pipeline, NULL); 394 395 vn_object_base_fini(&pipeline->base); 396 vk_free(alloc, pipeline); 397} 398