Files
UnrealEngine/Engine/Source/Runtime/VulkanRHI/Private/VulkanExtensions.h
2025-05-18 13:04:45 +08:00

172 lines
6.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VulkanExtensions.h: Vulkan extension definitions.
=============================================================================*/
#pragma once
#include "VulkanConfiguration.h"
struct FOptionalVulkanInstanceExtensions;
#define VULKAN_EXTENSION_NOT_PROMOTED UINT32_MAX
#define VULKAN_EXTENSION_ENABLED 1
#define VULKAN_EXTENSION_DISABLED 0
class FVulkanDevice;
enum class EVulkanVariableRateShadingPreference : uint8
{
PreferFSR = 0, // This can be used to prefer FSR over FDM when both are available.
UseFSROnlyIfAvailable, // This will only print a message if FSR is not available.
RequireFSR, // This will print an error if FSR is not available.
PreferFDM, // This can be used to prefer FDM over FSR when both are available.
UseFDMOnlyIfAvailable, // This will only print a message if FDM is not available.
RequireFDM, // This will print an error if FDM is not available.
};
class FVulkanExtensionBase
{
public:
enum EExtensionActivation : uint8
{
// If the extension is enabled in code and supported by the driver, it will automatically get used.
AutoActivate,
// The extension will not be used unless SetActivated() is called in the extension.
// Can be used to add engine support for an extension, but not use it by default unless externally requested.
// Useful for extensions only activated by plugins, or only present when a certain layer is loaded.
ManuallyActivate
};
FVulkanExtensionBase(const ANSICHAR* InExtensionName, int32 InEnabledInCode, uint32 InPromotedVersion, EExtensionActivation InActivation)
: ExtensionName(InExtensionName)
, PromotedVersion(InPromotedVersion)
, bEnabledInCode(InEnabledInCode == VULKAN_EXTENSION_ENABLED)
, bSupported(false)
, bActivated(InActivation == EExtensionActivation::AutoActivate)
, bCore(false)
{}
virtual ~FVulkanExtensionBase() {}
inline void SetSupported() { bSupported = true; }
inline void SetActivated() { bActivated = true; }
inline bool SetCore(uint32 ApiVersion) { return (bCore = (ApiVersion >= PromotedVersion)); }
inline const ANSICHAR* GetExtensionName() const { return ExtensionName; }
inline bool IsEnabled() const { return bEnabledInCode; }
inline bool IsSupported() const { return bSupported; }
inline bool IsCore() { return bCore; }
inline bool InUse() const
{
return bEnabledInCode && bSupported && bActivated;
}
template <typename ExtensionType>
static int32 FindExtension(const TArray<TUniquePtr<ExtensionType>>& UEExtensions, const ANSICHAR* ExtensionName)
{
for (int32 Index = 0; Index < UEExtensions.Num(); ++Index)
{
if (!FCStringAnsi::Strcmp(UEExtensions[Index]->GetExtensionName(), ExtensionName))
{
return Index;
}
}
return INDEX_NONE;
}
protected:
const ANSICHAR* ExtensionName;
const uint32 PromotedVersion;
// Extension is enabled in code if the VULKAN_SUPPORTS_* define is TRUE in VulkanConfiguration.h or Vulkan*Platform.h.
bool bEnabledInCode;
// Signals if the extension is support by the driver of the device being used (evaluated at runtime).
bool bSupported;
// Signals if the runtime currently wants this extension to be loaded.
bool bActivated;
// Signals if the extension has been promoted to core Vulkan for the current instance version
bool bCore;
};
class FVulkanDeviceExtension : public FVulkanExtensionBase
{
public:
FVulkanDeviceExtension(FVulkanDevice* InDevice, const ANSICHAR* InExtensionName, int32 InEnabledInCode, uint32 InPromotedVersion = VULKAN_EXTENSION_NOT_PROMOTED, TUniqueFunction<void(FOptionalVulkanDeviceExtensions& ExtensionFlags)>&& InFlagSetter = nullptr, EExtensionActivation InActivation = FVulkanExtensionBase::AutoActivate)
: FVulkanExtensionBase(InExtensionName, InEnabledInCode, InPromotedVersion, InActivation)
, Device(InDevice)
, FlagSetter(MoveTemp(InFlagSetter))
, bRequirementsPassed(true)
{}
static FVulkanDeviceExtensionArray GetUESupportedDeviceExtensions(FVulkanDevice* InDevice, uint32 ApiVersion);
static TArray<VkExtensionProperties> GetDriverSupportedDeviceExtensions(VkPhysicalDevice Gpu, const ANSICHAR* LayerName = nullptr);
virtual void PrePhysicalDeviceProperties(VkPhysicalDeviceProperties2KHR& PhysicalDeviceProperties2) {}
virtual void PostPhysicalDeviceProperties() {}
virtual void PrePhysicalDeviceFeatures(VkPhysicalDeviceFeatures2KHR& PhysicalDeviceFeatures2) {}
virtual void PostPhysicalDeviceFeatures(FOptionalVulkanDeviceExtensions& ExtensionFlags)
{
if (FlagSetter)
{
FlagSetter(ExtensionFlags);
}
}
virtual void PreCreateDevice(VkDeviceCreateInfo& DeviceInfo) {}
// Holds extensions requested externally (eg plugins)
static TArray<const ANSICHAR*> ExternalExtensions;
protected:
struct FOptionalVulkanDeviceExtensionProperties& GetDeviceExtensionProperties();
FVulkanDevice* Device;
TUniqueFunction<void(FOptionalVulkanDeviceExtensions& ExtensionFlags)> FlagSetter;
// Signals that this extension has passed any specific feature and/or property requirements
bool bRequirementsPassed;
};
class FVulkanInstanceExtension : public FVulkanExtensionBase
{
public:
FVulkanInstanceExtension(const ANSICHAR* InExtensionName, int32 InEnabledInCode, uint32 InPromotedVersion = VULKAN_EXTENSION_NOT_PROMOTED, TUniqueFunction<void(FOptionalVulkanInstanceExtensions& ExtensionFlags)>&& InFlagSetter = nullptr, EExtensionActivation InActivation = FVulkanExtensionBase::AutoActivate)
: FVulkanExtensionBase(InExtensionName, InEnabledInCode, InPromotedVersion, InActivation)
, FlagSetter(MoveTemp(InFlagSetter))
{}
static FVulkanInstanceExtensionArray GetUESupportedInstanceExtensions(uint32 ApiVersion);
static TArray<VkExtensionProperties> GetDriverSupportedInstanceExtensions(const ANSICHAR* LayerName = nullptr);
virtual void PreCreateInstance(VkInstanceCreateInfo& CreateInfo, FOptionalVulkanInstanceExtensions& ExtensionFlags)
{
if (FlagSetter)
{
FlagSetter(ExtensionFlags);
}
}
static TArray<const ANSICHAR*> ExternalExtensions;
protected:
TUniqueFunction<void(FOptionalVulkanInstanceExtensions& ExtensionFlags)> FlagSetter;
};
// Helpers to create simple extensions that set a flag
#define DEVICE_EXT_FLAG_SETTER(FLAG_NAME) [](FOptionalVulkanDeviceExtensions& ExtensionFlags) { ExtensionFlags.FLAG_NAME = 1; }
#define INSTANCE_EXT_FLAG_SETTER(FLAG_NAME) [](FOptionalVulkanInstanceExtensions& ExtensionFlags) { ExtensionFlags.FLAG_NAME = 1; }