diff --git a/docs/features.txt b/docs/features.txt index 3dbbf2c2271..2b66f2768db 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -485,7 +485,7 @@ Vulkan 1.3 -- all DONE: anv, radv, lvp VK_EXT_extended_dynamic_state DONE (anv, lvp, radv, tu, vn) VK_EXT_extended_dynamic_state2 DONE (anv, lvp, radv, tu, vn) VK_EXT_inline_uniform_block DONE (anv, lvp, radv, v3dv, vn) - VK_EXT_pipeline_creation_cache_control DONE (anv, lvp, radv, tu, v3dv) + VK_EXT_pipeline_creation_cache_control DONE (anv, lvp, radv, tu, v3dv, vn) VK_EXT_pipeline_creation_feedback DONE (anv, lvp, radv, tu, v3dv) VK_EXT_private_data DONE (anv, lvp, pvr, radv, tu, v3dv) VK_EXT_image_robustness DONE (anv, lvp, radv, tu, vn) diff --git a/src/virtio/vulkan/vn_physical_device.c b/src/virtio/vulkan/vn_physical_device.c index 9204e611f1e..ac0527ebd6c 100644 --- a/src/virtio/vulkan/vn_physical_device.c +++ b/src/virtio/vulkan/vn_physical_device.c @@ -132,6 +132,9 @@ vn_physical_device_init_features(struct vn_physical_device *physical_dev) VN_ADD_EXT_TO_PNEXT(exts->EXT_inline_uniform_block, feats->inline_uniform_block, INLINE_UNIFORM_BLOCK_FEATURES, features2); + VN_ADD_EXT_TO_PNEXT(exts->EXT_pipeline_creation_cache_control, + feats->pipeline_creation_cache_control, + PIPELINE_CREATION_CACHE_CONTROL_FEATURES, features2); VN_ADD_EXT_TO_PNEXT(exts->KHR_dynamic_rendering, feats->dynamic_rendering, DYNAMIC_RENDERING_FEATURES, features2); VN_ADD_EXT_TO_PNEXT(exts->KHR_maintenance4, feats->maintenance4, @@ -1002,6 +1005,7 @@ vn_physical_device_get_passthrough_extensions( .EXT_extended_dynamic_state2 = true, .EXT_image_robustness = true, .EXT_inline_uniform_block = true, + .EXT_pipeline_creation_cache_control = true, .EXT_shader_demote_to_helper_invocation = true, .EXT_texture_compression_astc_hdr = true, .KHR_copy_commands2 = true, @@ -1634,6 +1638,8 @@ vn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceImageRobustnessFeatures *image_robustness; VkPhysicalDeviceInlineUniformBlockFeatures *inline_uniform_block; VkPhysicalDeviceMaintenance4Features *maintenance4; + VkPhysicalDevicePipelineCreationCacheControlFeatures + *pipeline_creation_cache_control; VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures *shader_demote_to_helper_invocation; VkPhysicalDeviceTextureCompressionASTCHDRFeatures @@ -1829,6 +1835,9 @@ vn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES: *u.inline_uniform_block = feats->inline_uniform_block; break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES: + *u.pipeline_creation_cache_control = feats->pipeline_creation_cache_control; + break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES: *u.shader_demote_to_helper_invocation = feats->shader_demote_to_helper_invocation; diff --git a/src/virtio/vulkan/vn_physical_device.h b/src/virtio/vulkan/vn_physical_device.h index 29610056271..317cb976664 100644 --- a/src/virtio/vulkan/vn_physical_device.h +++ b/src/virtio/vulkan/vn_physical_device.h @@ -30,6 +30,8 @@ struct vn_physical_device_features { VkPhysicalDeviceImageRobustnessFeatures image_robustness; VkPhysicalDeviceInlineUniformBlockFeatures inline_uniform_block; VkPhysicalDeviceMaintenance4Features maintenance4; + VkPhysicalDevicePipelineCreationCacheControlFeatures + pipeline_creation_cache_control; VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures shader_demote_to_helper_invocation; VkPhysicalDeviceTextureCompressionASTCHDRFeatures diff --git a/src/virtio/vulkan/vn_pipeline.c b/src/virtio/vulkan/vn_pipeline.c index c2396d63465..1902073bf2e 100644 --- a/src/virtio/vulkan/vn_pipeline.c +++ b/src/virtio/vulkan/vn_pipeline.c @@ -277,6 +277,28 @@ vn_create_pipeline_handles(struct vn_device *dev, return true; } +/** For vkCreate*Pipelines. */ +static void +vn_destroy_failed_pipelines(struct vn_device *dev, + uint32_t create_info_count, + VkPipeline *pipelines, + const VkAllocationCallbacks *alloc) +{ + for (uint32_t i = 0; i < create_info_count; i++) { + struct vn_pipeline *pipeline = vn_pipeline_from_handle(pipelines[i]); + + if (pipeline->base.id == 0) { + vn_object_base_fini(&pipeline->base); + vk_free(alloc, pipeline); + pipelines[i] = VK_NULL_HANDLE; + } + } +} + +#define VN_PIPELINE_CREATE_SYNC_MASK \ + (VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT | \ + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT) + /** Fixes for a single VkGraphicsPipelineCreateInfo. */ struct vn_graphics_pipeline_create_info_fix { bool ignore_tessellation_state; @@ -636,6 +658,8 @@ vn_CreateGraphicsPipelines(VkDevice device, const VkAllocationCallbacks *alloc = pAllocator ? pAllocator : &dev->base.base.alloc; struct vn_create_graphics_pipelines_fixes *fixes = NULL; + bool want_sync = false; + VkResult result; pCreateInfos = vn_fix_graphics_pipeline_create_info( dev, createInfoCount, pCreateInfos, alloc, &fixes); @@ -647,13 +671,29 @@ vn_CreateGraphicsPipelines(VkDevice device, return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); } - vn_async_vkCreateGraphicsPipelines(dev->instance, device, pipelineCache, - createInfoCount, pCreateInfos, NULL, - pPipelines); + for (uint32_t i = 0; i < createInfoCount; i++) { + if ((pCreateInfos[i].flags & VN_PIPELINE_CREATE_SYNC_MASK)) { + want_sync = true; + break; + } + } + + if (want_sync) { + result = vn_call_vkCreateGraphicsPipelines( + dev->instance, device, pipelineCache, createInfoCount, pCreateInfos, + NULL, pPipelines); + if (result != VK_SUCCESS) + vn_destroy_failed_pipelines(dev, createInfoCount, pPipelines, alloc); + } else { + vn_async_vkCreateGraphicsPipelines(dev->instance, device, pipelineCache, + createInfoCount, pCreateInfos, NULL, + pPipelines); + result = VK_SUCCESS; + } vk_free(alloc, fixes); - return VK_SUCCESS; + return vn_result(dev->instance, result); } VkResult @@ -668,15 +708,33 @@ vn_CreateComputePipelines(VkDevice device, struct vn_device *dev = vn_device_from_handle(device); const VkAllocationCallbacks *alloc = pAllocator ? pAllocator : &dev->base.base.alloc; + bool want_sync = false; + VkResult result; if (!vn_create_pipeline_handles(dev, createInfoCount, pPipelines, alloc)) return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); - vn_async_vkCreateComputePipelines(dev->instance, device, pipelineCache, - createInfoCount, pCreateInfos, NULL, - pPipelines); + for (uint32_t i = 0; i < createInfoCount; i++) { + if ((pCreateInfos[i].flags & VN_PIPELINE_CREATE_SYNC_MASK)) { + want_sync = true; + break; + } + } - return VK_SUCCESS; + if (want_sync) { + result = vn_call_vkCreateComputePipelines( + dev->instance, device, pipelineCache, createInfoCount, pCreateInfos, + NULL, pPipelines); + if (result != VK_SUCCESS) + vn_destroy_failed_pipelines(dev, createInfoCount, pPipelines, alloc); + } else { + vn_call_vkCreateComputePipelines(dev->instance, device, pipelineCache, + createInfoCount, pCreateInfos, NULL, + pPipelines); + result = VK_SUCCESS; + } + + return vn_result(dev->instance, result); } void