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