blob: cbe88ac20f5ba00053dc1e031b59febc45e8ee94 [file] [log] [blame]
/*
* 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 = {};
// 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