1 /*-------------------------------------------------------------------------
2 * Vulkan CTS
3 * ----------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include "deSTLUtil.hpp"
21 #include "deString.h"
22 #include "vkQueryUtil.hpp"
23 #include "vkDeviceFeatures.inl"
24 #include "vkDeviceFeatures.hpp"
25
26 namespace vk
27 {
28
DeviceFeatures(const InstanceInterface & vki,const deUint32 apiVersion,const VkPhysicalDevice physicalDevice,const std::vector<std::string> & instanceExtensions,const std::vector<std::string> & deviceExtensions)29 DeviceFeatures::DeviceFeatures (const InstanceInterface& vki,
30 const deUint32 apiVersion,
31 const VkPhysicalDevice physicalDevice,
32 const std::vector<std::string>& instanceExtensions,
33 const std::vector<std::string>& deviceExtensions)
34 {
35 VkPhysicalDeviceRobustness2FeaturesEXT* robustness2Features = nullptr;
36 VkPhysicalDeviceImageRobustnessFeaturesEXT* imageRobustnessFeatures = nullptr;
37 VkPhysicalDeviceFragmentShadingRateFeaturesKHR* fragmentShadingRateFeatures = nullptr;
38 VkPhysicalDeviceShadingRateImageFeaturesNV* shadingRateImageFeatures = nullptr;
39 VkPhysicalDeviceFragmentDensityMapFeaturesEXT* fragmentDensityMapFeatures = nullptr;
40
41 m_coreFeatures2 = initVulkanStructure();
42 m_vulkan11Features = initVulkanStructure();
43 m_vulkan12Features = initVulkanStructure();
44
45 if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
46 {
47 const std::vector<VkExtensionProperties> deviceExtensionProperties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
48 void** nextPtr = &m_coreFeatures2.pNext;
49 std::vector<FeatureStructWrapperBase*> featuresToFillFromBlob;
50 bool vk12Supported = (apiVersion >= VK_MAKE_VERSION(1, 2, 0));
51
52 // in vk12 we have blob structures combining features of couple previously
53 // available feature structures, that now in vk12 must be removed from chain
54 if (vk12Supported)
55 {
56 addToChainVulkanStructure(&nextPtr, m_vulkan11Features);
57 addToChainVulkanStructure(&nextPtr, m_vulkan12Features);
58 }
59
60 // iterate over data for all feature that are defined in specification
61 for (const auto& featureStructCreationData : featureStructCreationArray)
62 {
63 const char* featureName = featureStructCreationData.name;
64
65 // check if this feature is available on current device
66 if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), featureName) &&
67 verifyFeatureAddCriteria(featureStructCreationData, deviceExtensionProperties))
68 {
69 FeatureStructWrapperBase* p = (*featureStructCreationData.creatorFunction)();
70 if (p == DE_NULL)
71 continue;
72
73 // if feature struct is part of VkPhysicalDeviceVulkan1{1,2}Features
74 // we dont add it to the chain but store and fill later from blob data
75 bool featureFilledFromBlob = false;
76 if (vk12Supported)
77 featureFilledFromBlob = isPartOfBlobFeatures(p->getFeatureDesc().sType);
78
79 if (featureFilledFromBlob)
80 featuresToFillFromBlob.push_back(p);
81 else
82 {
83 VkStructureType structType = p->getFeatureDesc().sType;
84 void* rawStructPtr = p->getFeatureTypeRaw();
85
86 if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT)
87 robustness2Features = reinterpret_cast<VkPhysicalDeviceRobustness2FeaturesEXT*>(rawStructPtr);
88 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT)
89 imageRobustnessFeatures = reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT*>(rawStructPtr);
90 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR)
91 fragmentShadingRateFeatures = reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR*>(rawStructPtr);
92 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV)
93 shadingRateImageFeatures = reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV*>(rawStructPtr);
94 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT)
95 fragmentDensityMapFeatures = reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>(rawStructPtr);
96
97 // add to chain
98 *nextPtr = rawStructPtr;
99 nextPtr = p->getFeatureTypeNext();
100 }
101 m_features.push_back(p);
102 }
103 }
104
105 vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2);
106
107 // fill data from VkPhysicalDeviceVulkan1{1,2}Features
108 if (vk12Supported)
109 {
110 AllFeaturesBlobs allBlobs =
111 {
112 m_vulkan11Features,
113 m_vulkan12Features,
114 // add blobs from future vulkan versions here
115 };
116
117 for (auto feature : featuresToFillFromBlob)
118 feature->initializeFeatureFromBlob(allBlobs);
119 }
120 }
121 else
122 m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice);
123
124 // Disable robustness by default, as it has an impact on performance on some HW.
125 if (robustness2Features)
126 {
127 robustness2Features->robustBufferAccess2 = false;
128 robustness2Features->robustImageAccess2 = false;
129 robustness2Features->nullDescriptor = false;
130 }
131 if (imageRobustnessFeatures)
132 {
133 imageRobustnessFeatures->robustImageAccess = false;
134 }
135 m_coreFeatures2.features.robustBufferAccess = false;
136
137 // Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features
138 // that must: not be enabled if KHR fragment shading rate features are enabled.
139 if (fragmentShadingRateFeatures &&
140 (fragmentShadingRateFeatures->pipelineFragmentShadingRate ||
141 fragmentShadingRateFeatures->primitiveFragmentShadingRate ||
142 fragmentShadingRateFeatures->attachmentFragmentShadingRate))
143 {
144 if (shadingRateImageFeatures)
145 shadingRateImageFeatures->shadingRateImage = false;
146 if (fragmentDensityMapFeatures)
147 fragmentDensityMapFeatures->fragmentDensityMap = false;
148 }
149 }
150
verifyFeatureAddCriteria(const FeatureStructCreationData & item,const std::vector<VkExtensionProperties> & properties)151 bool DeviceFeatures::verifyFeatureAddCriteria (const FeatureStructCreationData& item, const std::vector<VkExtensionProperties>& properties)
152 {
153 if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME))
154 {
155 for (const auto& property : properties)
156 {
157 if (deStringEqual(property.extensionName, item.name))
158 return (property.specVersion == item.specVersion);
159 }
160 }
161
162 return true;
163 }
164
contains(const std::string & feature,bool throwIfNotExists) const165 bool DeviceFeatures::contains (const std::string& feature, bool throwIfNotExists) const
166 {
167 for (const auto f : m_features)
168 {
169 if (deStringEqual(f->getFeatureDesc().name, feature.c_str()))
170 return true;
171 }
172
173 if (throwIfNotExists)
174 TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported");
175
176 return false;
177 }
178
isDeviceFeatureInitialized(VkStructureType sType) const179 bool DeviceFeatures::isDeviceFeatureInitialized (VkStructureType sType) const
180 {
181 for (const auto f : m_features)
182 {
183 if (f->getFeatureDesc().sType == sType)
184 return true;
185 }
186 return false;
187 }
188
~DeviceFeatures(void)189 DeviceFeatures::~DeviceFeatures (void)
190 {
191 for (auto p : m_features)
192 delete p;
193
194 m_features.clear();
195 }
196
197 } // vk
198
199