blob: fc432a2042e884a6f11e16292ba23c067dec04f6 [file] [log] [blame]
/*
* Copyright (c) 2024 Valve Corporation
* Copyright (c) 2024 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "../framework/feature_requirements.h"
#include "generated/pnext_chain_extraction.h"
#include <vulkan/utility/vk_struct_helper.hpp>
namespace vkt {
FeatureRequirements::~FeatureRequirements() {
vvl::PnextChainFree(feature_chain_);
feature_chain_ = nullptr;
}
void FeatureRequirements::AddRequiredFeature(APIVersion api_version, vkt::Feature feature) {
FeatureAndName f = SetFeature(api_version, feature, VK_TRUE);
*f.feature = VK_TRUE;
required_features_.emplace_back(f);
}
void FeatureRequirements::AddOptionalFeature(APIVersion api_version, vkt::Feature feature) {
// By setting the feature here it will be queried and passed pack to device creation
// with the resulting values, so this in effect allows enabling the feature when available
FeatureAndName f = SetFeature(api_version, feature, VK_TRUE);
*f.feature = VK_TRUE;
}
vkt::FeatureAndName FeatureRequirements::SetFeature(APIVersion api_version, vkt::Feature feature, VkBool32 value) {
switch (feature) {
case vkt::Feature::robustBufferAccess: {
phys_dev_features_.features.robustBufferAccess = value;
FeatureAndName f{&phys_dev_features_.features.robustBufferAccess, "VkPhysicalDeviceFeatures::robustBufferAccess"};
return f;
}
case vkt::Feature::fullDrawIndexUint32: {
phys_dev_features_.features.fullDrawIndexUint32 = value;
FeatureAndName f{&phys_dev_features_.features.fullDrawIndexUint32, "VkPhysicalDeviceFeatures::fullDrawIndexUint32"};
return f;
}
case vkt::Feature::imageCubeArray: {
phys_dev_features_.features.imageCubeArray = value;
FeatureAndName f{&phys_dev_features_.features.imageCubeArray, "VkPhysicalDeviceFeatures::imageCubeArray"};
return f;
}
case vkt::Feature::independentBlend: {
phys_dev_features_.features.independentBlend = value;
FeatureAndName f{&phys_dev_features_.features.independentBlend, "VkPhysicalDeviceFeatures::independentBlend"};
return f;
}
case vkt::Feature::geometryShader: {
phys_dev_features_.features.geometryShader = value;
FeatureAndName f{&phys_dev_features_.features.geometryShader, "VkPhysicalDeviceFeatures::geometryShader"};
return f;
}
case vkt::Feature::tessellationShader: {
phys_dev_features_.features.tessellationShader = value;
FeatureAndName f{&phys_dev_features_.features.tessellationShader, "VkPhysicalDeviceFeatures::tessellationShader"};
return f;
}
case vkt::Feature::sampleRateShading: {
phys_dev_features_.features.sampleRateShading = value;
FeatureAndName f{&phys_dev_features_.features.sampleRateShading, "VkPhysicalDeviceFeatures::sampleRateShading"};
return f;
}
case vkt::Feature::dualSrcBlend: {
phys_dev_features_.features.dualSrcBlend = value;
FeatureAndName f{&phys_dev_features_.features.dualSrcBlend, "VkPhysicalDeviceFeatures::dualSrcBlend"};
return f;
}
case vkt::Feature::logicOp: {
phys_dev_features_.features.logicOp = value;
FeatureAndName f{&phys_dev_features_.features.logicOp, "VkPhysicalDeviceFeatures::logicOp"};
return f;
}
case vkt::Feature::multiDrawIndirect: {
phys_dev_features_.features.multiDrawIndirect = value;
FeatureAndName f{&phys_dev_features_.features.multiDrawIndirect, "VkPhysicalDeviceFeatures::multiDrawIndirect"};
return f;
}
case vkt::Feature::drawIndirectFirstInstance: {
phys_dev_features_.features.drawIndirectFirstInstance = value;
FeatureAndName f{&phys_dev_features_.features.drawIndirectFirstInstance,
"VkPhysicalDeviceFeatures::drawIndirectFirstInstance"};
return f;
}
case vkt::Feature::depthClamp: {
phys_dev_features_.features.depthClamp = value;
FeatureAndName f{&phys_dev_features_.features.depthClamp, "VkPhysicalDeviceFeatures::depthClamp"};
return f;
}
case vkt::Feature::depthBiasClamp: {
phys_dev_features_.features.depthBiasClamp = value;
FeatureAndName f{&phys_dev_features_.features.depthBiasClamp, "VkPhysicalDeviceFeatures::depthBiasClamp"};
return f;
}
case vkt::Feature::fillModeNonSolid: {
phys_dev_features_.features.fillModeNonSolid = value;
FeatureAndName f{&phys_dev_features_.features.fillModeNonSolid, "VkPhysicalDeviceFeatures::fillModeNonSolid"};
return f;
}
case vkt::Feature::depthBounds: {
phys_dev_features_.features.depthBounds = value;
FeatureAndName f{&phys_dev_features_.features.depthBounds, "VkPhysicalDeviceFeatures::depthBounds"};
return f;
}
case vkt::Feature::wideLines: {
phys_dev_features_.features.wideLines = value;
FeatureAndName f{&phys_dev_features_.features.wideLines, "VkPhysicalDeviceFeatures::wideLines"};
return f;
}
case vkt::Feature::largePoints: {
phys_dev_features_.features.largePoints = value;
FeatureAndName f{&phys_dev_features_.features.largePoints, "VkPhysicalDeviceFeatures::largePoints"};
return f;
}
case vkt::Feature::alphaToOne: {
phys_dev_features_.features.alphaToOne = value;
FeatureAndName f{&phys_dev_features_.features.alphaToOne, "VkPhysicalDeviceFeatures::alphaToOne"};
return f;
}
case vkt::Feature::multiViewport: {
phys_dev_features_.features.multiViewport = value;
FeatureAndName f{&phys_dev_features_.features.multiViewport, "VkPhysicalDeviceFeatures::multiViewport"};
return f;
}
case vkt::Feature::samplerAnisotropy: {
phys_dev_features_.features.samplerAnisotropy = value;
FeatureAndName f{&phys_dev_features_.features.samplerAnisotropy, "VkPhysicalDeviceFeatures::samplerAnisotropy"};
return f;
}
case vkt::Feature::textureCompressionETC2: {
phys_dev_features_.features.textureCompressionETC2 = value;
FeatureAndName f{&phys_dev_features_.features.textureCompressionETC2,
"VkPhysicalDeviceFeatures::textureCompressionETC2"};
return f;
}
case vkt::Feature::textureCompressionASTC_LDR: {
phys_dev_features_.features.textureCompressionASTC_LDR = value;
FeatureAndName f{&phys_dev_features_.features.textureCompressionASTC_LDR,
"VkPhysicalDeviceFeatures::textureCompressionASTC_LDR"};
return f;
}
case vkt::Feature::textureCompressionBC: {
phys_dev_features_.features.textureCompressionBC = value;
FeatureAndName f{&phys_dev_features_.features.textureCompressionBC, "VkPhysicalDeviceFeatures::textureCompressionBC"};
return f;
}
case vkt::Feature::occlusionQueryPrecise: {
phys_dev_features_.features.occlusionQueryPrecise = value;
FeatureAndName f{&phys_dev_features_.features.occlusionQueryPrecise, "VkPhysicalDeviceFeatures::occlusionQueryPrecise"};
return f;
}
case vkt::Feature::pipelineStatisticsQuery: {
phys_dev_features_.features.pipelineStatisticsQuery = value;
FeatureAndName f{&phys_dev_features_.features.pipelineStatisticsQuery,
"VkPhysicalDeviceFeatures::pipelineStatisticsQuery"};
return f;
}
case vkt::Feature::vertexPipelineStoresAndAtomics: {
phys_dev_features_.features.vertexPipelineStoresAndAtomics = value;
FeatureAndName f{&phys_dev_features_.features.vertexPipelineStoresAndAtomics,
"VkPhysicalDeviceFeatures::vertexPipelineStoresAndAtomics"};
return f;
}
case vkt::Feature::fragmentStoresAndAtomics: {
phys_dev_features_.features.fragmentStoresAndAtomics = value;
FeatureAndName f{&phys_dev_features_.features.fragmentStoresAndAtomics,
"VkPhysicalDeviceFeatures::fragmentStoresAndAtomics"};
return f;
}
case vkt::Feature::shaderTessellationAndGeometryPointSize: {
phys_dev_features_.features.shaderTessellationAndGeometryPointSize = value;
FeatureAndName f{&phys_dev_features_.features.shaderTessellationAndGeometryPointSize,
"VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize"};
return f;
}
case vkt::Feature::shaderImageGatherExtended: {
phys_dev_features_.features.shaderImageGatherExtended = value;
FeatureAndName f{&phys_dev_features_.features.shaderImageGatherExtended,
"VkPhysicalDeviceFeatures::shaderImageGatherExtended"};
return f;
}
case vkt::Feature::shaderStorageImageExtendedFormats: {
phys_dev_features_.features.shaderStorageImageExtendedFormats = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageImageExtendedFormats,
"VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats"};
return f;
}
case vkt::Feature::shaderStorageImageMultisample: {
phys_dev_features_.features.shaderStorageImageMultisample = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageImageMultisample,
"VkPhysicalDeviceFeatures::shaderStorageImageMultisample"};
return f;
}
case vkt::Feature::shaderStorageImageReadWithoutFormat: {
phys_dev_features_.features.shaderStorageImageReadWithoutFormat = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageImageReadWithoutFormat,
"VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat"};
return f;
}
case vkt::Feature::shaderStorageImageWriteWithoutFormat: {
phys_dev_features_.features.shaderStorageImageWriteWithoutFormat = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageImageWriteWithoutFormat,
"VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat"};
return f;
}
case vkt::Feature::shaderUniformBufferArrayDynamicIndexing: {
phys_dev_features_.features.shaderUniformBufferArrayDynamicIndexing = value;
FeatureAndName f{&phys_dev_features_.features.shaderUniformBufferArrayDynamicIndexing,
"VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing"};
return f;
}
case vkt::Feature::shaderSampledImageArrayDynamicIndexing: {
phys_dev_features_.features.shaderSampledImageArrayDynamicIndexing = value;
FeatureAndName f{&phys_dev_features_.features.shaderSampledImageArrayDynamicIndexing,
"VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing"};
return f;
}
case vkt::Feature::shaderStorageBufferArrayDynamicIndexing: {
phys_dev_features_.features.shaderStorageBufferArrayDynamicIndexing = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageBufferArrayDynamicIndexing,
"VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing"};
return f;
}
case vkt::Feature::shaderStorageImageArrayDynamicIndexing: {
phys_dev_features_.features.shaderStorageImageArrayDynamicIndexing = value;
FeatureAndName f{&phys_dev_features_.features.shaderStorageImageArrayDynamicIndexing,
"VkPhysicalDeviceFeatures::shaderStorageImageArrayDynamicIndexing"};
return f;
}
case vkt::Feature::shaderClipDistance: {
phys_dev_features_.features.shaderClipDistance = value;
FeatureAndName f{&phys_dev_features_.features.shaderClipDistance, "VkPhysicalDeviceFeatures::shaderClipDistance"};
return f;
}
case vkt::Feature::shaderCullDistance: {
phys_dev_features_.features.shaderCullDistance = value;
FeatureAndName f{&phys_dev_features_.features.shaderCullDistance, "VkPhysicalDeviceFeatures::shaderCullDistance"};
return f;
}
case vkt::Feature::shaderFloat64: {
phys_dev_features_.features.shaderFloat64 = value;
FeatureAndName f{&phys_dev_features_.features.shaderFloat64, "VkPhysicalDeviceFeatures::shaderFloat64"};
return f;
}
case vkt::Feature::shaderInt64: {
phys_dev_features_.features.shaderInt64 = value;
FeatureAndName f{&phys_dev_features_.features.shaderInt64, "VkPhysicalDeviceFeatures::shaderInt64"};
return f;
}
case vkt::Feature::shaderInt16: {
phys_dev_features_.features.shaderInt16 = value;
FeatureAndName f{&phys_dev_features_.features.shaderInt16, "VkPhysicalDeviceFeatures::shaderInt16"};
return f;
}
case vkt::Feature::shaderResourceResidency: {
phys_dev_features_.features.shaderResourceResidency = value;
FeatureAndName f{&phys_dev_features_.features.shaderResourceResidency,
"VkPhysicalDeviceFeatures::shaderResourceResidency"};
return f;
}
case vkt::Feature::shaderResourceMinLod: {
phys_dev_features_.features.shaderResourceMinLod = value;
FeatureAndName f{&phys_dev_features_.features.shaderResourceMinLod, "VkPhysicalDeviceFeatures::shaderResourceMinLod"};
return f;
}
case vkt::Feature::sparseBinding: {
phys_dev_features_.features.sparseBinding = value;
FeatureAndName f{&phys_dev_features_.features.sparseBinding, "VkPhysicalDeviceFeatures::sparseBinding"};
return f;
}
case vkt::Feature::sparseResidencyBuffer: {
phys_dev_features_.features.sparseResidencyBuffer = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidencyBuffer, "VkPhysicalDeviceFeatures::sparseResidencyBuffer"};
return f;
}
case vkt::Feature::sparseResidencyImage2D: {
phys_dev_features_.features.sparseResidencyImage2D = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidencyImage2D,
"VkPhysicalDeviceFeatures::sparseResidencyImage2D"};
return f;
}
case vkt::Feature::sparseResidencyImage3D: {
phys_dev_features_.features.sparseResidencyImage3D = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidencyImage3D,
"VkPhysicalDeviceFeatures::sparseResidencyImage3D"};
return f;
}
case vkt::Feature::sparseResidency2Samples: {
phys_dev_features_.features.sparseResidency2Samples = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidency2Samples,
"VkPhysicalDeviceFeatures::sparseResidency2Samples"};
return f;
}
case vkt::Feature::sparseResidency4Samples: {
phys_dev_features_.features.sparseResidency4Samples = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidency4Samples,
"VkPhysicalDeviceFeatures::sparseResidency4Samples"};
return f;
}
case vkt::Feature::sparseResidency8Samples: {
phys_dev_features_.features.sparseResidency8Samples = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidency8Samples,
"VkPhysicalDeviceFeatures::sparseResidency8Samples"};
return f;
}
case vkt::Feature::sparseResidency16Samples: {
phys_dev_features_.features.sparseResidency16Samples = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidency16Samples,
"VkPhysicalDeviceFeatures::sparseResidency16Samples"};
return f;
}
case vkt::Feature::sparseResidencyAliased: {
phys_dev_features_.features.sparseResidencyAliased = value;
FeatureAndName f{&phys_dev_features_.features.sparseResidencyAliased,
"VkPhysicalDeviceFeatures::sparseResidencyAliased"};
return f;
}
case vkt::Feature::variableMultisampleRate: {
phys_dev_features_.features.variableMultisampleRate = value;
FeatureAndName f{&phys_dev_features_.features.variableMultisampleRate,
"VkPhysicalDeviceFeatures::variableMultisampleRate"};
return f;
}
case vkt::Feature::inheritedQueries: {
phys_dev_features_.features.inheritedQueries = value;
FeatureAndName f{&phys_dev_features_.features.inheritedQueries, "VkPhysicalDeviceFeatures::inheritedQueries"};
return f;
}
default:
FeatureAndName f = vkt::AddFeature(api_version, feature, &feature_chain_);
return f;
}
}
VkPhysicalDeviceFeatures2* FeatureRequirements::GetFeatures2() {
phys_dev_features_.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
phys_dev_features_.pNext = feature_chain_;
return &phys_dev_features_;
}
const char* FeatureRequirements::AnyRequiredFeatureDisabled() const {
for (const auto [feature, name] : required_features_) {
if (*feature == VK_FALSE) {
return name;
}
}
return nullptr;
}
void FeatureRequirements::EnforceRequiredFeatures() {
for (const auto [feature, name] : required_features_) {
*feature = VK_TRUE;
}
}
} // namespace vkt