| /* | |
| * Copyright 2025 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_VulkanPreferredFeatures_DEFINED | |
| #define skgpu_VulkanPreferredFeatures_DEFINED | |
| #include "include/private/base/SkAPI.h" | |
| #include "include/private/gpu/vk/SkiaVulkan.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <vector> | |
| namespace skgpu { | |
| class SK_API VulkanPreferredFeatures { | |
| public: | |
| ~VulkanPreferredFeatures(); | |
| /* | |
| * VulkanPreferredFeatures is used by Skia to add extensions and features on top of what the app | |
| * wants to enable. The flow of Vulkan initialization for an app that wants to use Skia would | |
| * be: | |
| * | |
| * ``` | |
| * // Query the loader for instance information, decide on API version to use | |
| * | |
| * // Prepare for Skia-enabled extensions and features | |
| * skgpu::VulkanPreferredFeatures skiaFeatures; | |
| * skiaFeatures.init(apiVersion); | |
| * | |
| * // Decide on instance extensions to use in the app. | |
| * | |
| * // Allow Skia to add to the instance extension list. | |
| * skiaFeatures.addToInstanceExtensions(...); | |
| * | |
| * // Create the instance, choose physical device, query available extensions, decide on | |
| * // device features to query | |
| * | |
| * // Allow Skia to add to the feature query list. | |
| * skiaFeatures.addFeaturesToQuery(...); | |
| * | |
| * // Query features, decide on extensions and features to enable. | |
| * | |
| * // Allow Skia to add to the device extension and feature list. | |
| * skiaFeatures.addFeaturesToEnable(...); | |
| * | |
| * // Create the Vulkan device. | |
| * ``` | |
| * | |
| * Parameters: | |
| * | |
| * * appAPIVersion: The API version the app has specified in VkApplicationInfo::apiVersion (and | |
| * will later provide in VulkanBackendContext::fMaxAPIVersion). The minimum supported version | |
| * is VK_API_VERSION_1_1, maximum is VK_API_VERSION_1_4. | |
| */ | |
| void init(uint32_t appAPIVersion); | |
| /* | |
| * Before creating a Vulkan instance, call addToInstanceExtensions to give Skia a chance to add | |
| * instance extensions it may take advantage of. Extensions are only added to appExtensions if | |
| * caller hasn't already included them to be enabled. | |
| * | |
| * Parameters: | |
| * | |
| * * instanceExtensions, instanceExtensionCount: The list of available instance extensions as | |
| * queried from the loader. | |
| * * appExtensions: The list of extensions to be enabled on the instance; more extensions may be | |
| * added to this list by this call. | |
| */ | |
| void addToInstanceExtensions(const VkExtensionProperties* instanceExtensions, | |
| size_t instanceExtensionCount, | |
| std::vector<const char*>& appExtensions); | |
| /* | |
| * Before querying Vulkan device features, call addFeaturesToQuery to give Skia a chance to add | |
| * device extension features it may take advantage of to the query. Features are only added to | |
| * appFeatures if caller hasn't already included them in the query. | |
| * | |
| * Beware that the structs that get chained to appFeatures are member variables of this class, | |
| * so this object must not leave scope until feature query and device creation is complete. | |
| * | |
| * Parameters: | |
| * | |
| * * deviceExtensions, deviceExtensionCount: The list of available device extensions as queried | |
| * from the physical device. | |
| * * appFeatures: The features to be queried from the physical device; more features may be | |
| * added to the pNext chain by this call. | |
| */ | |
| void addFeaturesToQuery(const VkExtensionProperties* deviceExtensions, | |
| size_t deviceExtensionCount, | |
| VkPhysicalDeviceFeatures2& appFeatures); | |
| /* | |
| * Before creating the Vulkan device, call addFeaturesToEnable to give Skia a chance to add | |
| * device extensions and features it may take advantage of. Extensions and features are only | |
| * added to appExtensions and appFeatures respectively if caller hasn't already included them to | |
| * be enabled. This function may replace chained features with VkPhysicalDeviceVulkanNNFeatures | |
| * structs instead in order to add features. Features that are already enabled by the | |
| * application are retained in that case in the new struct. | |
| * | |
| * Parameters: | |
| * | |
| * * appExtensions: The list of extensions to be enabled on the device; more extensions may be | |
| * added to this list by this call. | |
| * * appFeatures: The features to be enabled on the device; more features may be | |
| * added to the pNext chain by this call. | |
| */ | |
| void addFeaturesToEnable(std::vector<const char*>& appExtensions, | |
| VkPhysicalDeviceFeatures2& appFeatures); | |
| private: | |
| uint32_t fAPIVersion = 0; | |
| // Track what the application did, so warnings can be generated if the class is not | |
| // fully/correctly used. | |
| bool fHasAddedToInstanceExtensions = false; | |
| bool fHasAddedFeaturesToQuery = false; | |
| bool fHasAddedFeaturesToEnable = false; | |
| // The list of device features Skia is interested in. If any are included in | |
| // VkPhysicalDeviceFeatures2::pNext by the app, it is not included again by Skia. However, to | |
| // take best advantage of the Vulkan API, the app should not intentionally include these feature | |
| // structs only to forcefully disable the feature - this blocks Skia from leveraging it. | |
| // | |
| // When ambiguous, the extension name is included to determine which extension a feature struct | |
| // has come from. This is usually needed when addFeaturesToQuery has included a feature struct | |
| // that is present in multiple extensions (e.g. due to extension promotion). It is later used by | |
| // addFeaturesToEnable to know which extension to enable. | |
| // Available since Vulkan 1.2 | |
| VkPhysicalDeviceVulkan11Features fVulkan11 = {}; | |
| // Available since Vulkan 1.2 | |
| VkPhysicalDeviceVulkan12Features fVulkan12 = {}; | |
| // Available since Vulkan 1.3 | |
| VkPhysicalDeviceVulkan13Features fVulkan13 = {}; | |
| // Available since Vulkan 1.4 | |
| VkPhysicalDeviceVulkan14Features fVulkan14 = {}; | |
| // Feature of VK_EXT_rasterization_order_attachment_access or | |
| // VK_ARM_rasterization_order_attachment_access. | |
| VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT | |
| fRasterizationOrderAttachmentAccess = {}; | |
| const char* fRasterizationOrderAttachmentAccessExtension = nullptr; | |
| // Feature of VK_EXT_blend_operation_advanced | |
| VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT fBlendOperationAdvanced = {}; | |
| // Feature of VK_EXT_extended_dynamic_state | |
| VkPhysicalDeviceExtendedDynamicStateFeaturesEXT fExtendedDynamicState = {}; | |
| // Feature of VK_EXT_extended_dynamic_state2 | |
| VkPhysicalDeviceExtendedDynamicState2FeaturesEXT fExtendedDynamicState2 = {}; | |
| // Feature of VK_EXT_vertex_input_dynamic_state | |
| VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT fVertexInputDynamicState = {}; | |
| // Feature of VK_EXT_graphics_pipeline_library | |
| VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT fGraphicsPipelineLibrary = {}; | |
| // Feature of VK_KHR_sampler_ycbcr_conversion or Vulkan 1.1 | |
| VkPhysicalDeviceSamplerYcbcrConversionFeatures fSamplerYcbcrConversion = {}; | |
| // Feature of VK_EXT_rgba10x6_formats | |
| VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT fRGBA10x6Formats = {}; | |
| // Feature of VK_KHR_synchronization2 or Vulkan 1.3 | |
| VkPhysicalDeviceDynamicRenderingFeatures fSynchronization2 = {}; | |
| // Feature of VK_KHR_dynamic_rendering or Vulkan 1.3 | |
| VkPhysicalDeviceDynamicRenderingFeatures fDynamicRendering = {}; | |
| // Feature of VK_KHR_dynamic_rendering_local_read or Vulkan 1.4 | |
| VkPhysicalDeviceDynamicRenderingLocalReadFeatures fDynamicRenderingLocalRead = {}; | |
| // Feature of VK_EXT_multisampled_render_to_single_sampled | |
| VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT | |
| fMultisampledRenderToSingleSampled = {}; | |
| // Feature of VK_EXT_host_image_copy or Vulkan 1.4 | |
| VkPhysicalDeviceHostImageCopyFeatures fHostImageCopy = {}; | |
| // Feature of VK_EXT_pipeline_creation_cache_control or Vulkan 1.3 | |
| VkPhysicalDevicePipelineCreationCacheControlFeatures fPipelineCreationCacheControl = {}; | |
| // Feature of VK_EXT_frame_boundary | |
| VkPhysicalDeviceFrameBoundaryFeaturesEXT fFrameBoundary = {}; | |
| // Extensions that don't have a feature: | |
| // VK_KHR_driver_properties or Vulkan 1.2 | |
| const char* fDriverPropertiesExtension = nullptr; | |
| // VK_KHR_create_renderpass2 or Vulkan 1.2 | |
| const char* fCreateRenderpass2Extension = nullptr; | |
| // VK_EXT_load_store_op_none, VK_KHR_load_store_op_none or Vulkan 1.4 | |
| const char* fLoadStoreOpNoneExtension = nullptr; | |
| // VK_EXT_conservative_rasterization | |
| const char* fConservativeRasterizationExtension = nullptr; | |
| // Extensions that the other extensions above depend on: | |
| // Dependency of VK_EXT_graphics_pipeline_library: VK_KHR_pipeline_library | |
| const char* fPipelineLibraryExtension = nullptr; | |
| // Dependencies of VK_EXT_host_image_copy: VK_KHR_copy_commands2, VK_KHR_format_feature_flags2 | |
| const char* fCopyCommands2Extension = nullptr; | |
| const char* fFormatFeatureFlags2Extension = nullptr; | |
| // Dependency of VK_EXT_multisampled_render_to_single_sampled: VK_KHR_depth_stencil_resolve | |
| const char* fDepthStencilResolveExtension = nullptr; | |
| }; | |
| } // namespace skgpu | |
| #endif // skgpu_VulkanPreferredFeatures_DEFINED |