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 "vkDeviceProperties.inl"
24 #include "vkDeviceProperties.hpp"
25
26 namespace vk
27 {
28
DeviceProperties(const InstanceInterface & vki,const uint32_t apiVersion,const VkPhysicalDevice physicalDevice,const std::vector<std::string> & instanceExtensions,const std::vector<std::string> & deviceExtensions)29 DeviceProperties::DeviceProperties(const InstanceInterface &vki, const uint32_t apiVersion,
30 const VkPhysicalDevice physicalDevice,
31 const std::vector<std::string> &instanceExtensions,
32 const std::vector<std::string> &deviceExtensions)
33 {
34 m_coreProperties2 = initVulkanStructure();
35 m_vulkan11Properties = initVulkanStructure();
36 m_vulkan12Properties = initVulkanStructure();
37 #ifndef CTS_USES_VULKANSC
38 m_vulkan13Properties = initVulkanStructure();
39 #endif // CTS_USES_VULKANSC
40 #ifdef CTS_USES_VULKANSC
41 m_vulkanSC10Properties = initVulkanStructure();
42 #endif // CTS_USES_VULKANSC
43
44 if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
45 {
46 const std::vector<VkExtensionProperties> deviceExtensionProperties =
47 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
48 void **nextPtr = &m_coreProperties2.pNext;
49 std::vector<PropertyStructWrapperBase *> propertiesToFillFromBlob;
50 std::vector<PropertyStructWrapperBase *> propertiesAddedWithVK;
51 bool vk11Supported = (apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0));
52 bool vk12Supported = (apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0));
53 #ifndef CTS_USES_VULKANSC
54 bool vk13Supported = (apiVersion >= VK_MAKE_API_VERSION(0, 1, 3, 0));
55 #endif // CTS_USES_VULKANSC
56 #ifdef CTS_USES_VULKANSC
57 bool vksc10Supported = (apiVersion >= VK_MAKE_API_VERSION(1, 1, 0, 0));
58 #endif // CTS_USES_VULKANSC
59
60 // there are 3 properies structures that were added with vk11 (without being first part of extension)
61 if (vk11Supported)
62 {
63 propertiesAddedWithVK = {createPropertyStructWrapper<VkPhysicalDeviceSubgroupProperties>(),
64 createPropertyStructWrapper<VkPhysicalDeviceIDProperties>(),
65 createPropertyStructWrapper<VkPhysicalDeviceProtectedMemoryProperties>()};
66
67 for (auto pAddedWithVK : propertiesAddedWithVK)
68 {
69 m_properties.push_back(pAddedWithVK);
70
71 if (!vk12Supported)
72 addToChainStructWrapper(&nextPtr, pAddedWithVK);
73 }
74 }
75
76 // since vk12 we have blob structures combining properties of couple previously
77 // available property structures, that now in vk12 and above must be removed from chain
78 if (vk12Supported)
79 {
80 addToChainVulkanStructure(&nextPtr, m_vulkan11Properties);
81 addToChainVulkanStructure(&nextPtr, m_vulkan12Properties);
82
83 #ifndef CTS_USES_VULKANSC
84 if (vk13Supported)
85 addToChainVulkanStructure(&nextPtr, m_vulkan13Properties);
86 #endif // CTS_USES_VULKANSC
87 }
88
89 std::vector<std::string> allDeviceExtensions = deviceExtensions;
90 #ifdef CTS_USES_VULKANSC
91 // VulkanSC: add missing core extensions to the list
92 std::vector<const char *> coreExtensions;
93 getCoreDeviceExtensions(apiVersion, coreExtensions);
94 for (const auto &coreExt : coreExtensions)
95 if (!de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(), std::string(coreExt)))
96 allDeviceExtensions.push_back(coreExt);
97 if (vksc10Supported)
98 addToChainVulkanStructure(&nextPtr, m_vulkanSC10Properties);
99 #endif // CTS_USES_VULKANSC
100
101 // iterate over data for all property that are defined in specification
102 for (const auto &propertyStructCreationData : propertyStructCreationArray)
103 {
104 const char *propertyName = propertyStructCreationData.name;
105
106 // check if this property is available on current device.
107 if (de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(), propertyName) ||
108 std::string(propertyName) == "core_property")
109 {
110 PropertyStructWrapperBase *p = (*propertyStructCreationData.creatorFunction)();
111 if (p == DE_NULL)
112 continue;
113
114 #ifdef CTS_USES_VULKANSC
115 // m_vulkanSC10Properties was already added above
116 if (p->getPropertyDesc().sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_PROPERTIES)
117 continue;
118 #endif // CTS_USES_VULKANSC
119
120 // if property struct is part of VkPhysicalDeviceVulkan1{1,2}Properties
121 // we dont add it to the chain but store and fill later from blob data
122 bool propertyFilledFromBlob = false;
123 if (vk12Supported)
124 {
125 uint32_t blobApiVersion = getBlobPropertiesVersion(p->getPropertyDesc().sType);
126 if (blobApiVersion)
127 propertyFilledFromBlob = (apiVersion >= blobApiVersion);
128 }
129
130 if (propertyFilledFromBlob)
131 propertiesToFillFromBlob.push_back(p);
132 else
133 {
134 // add to chain
135 addToChainStructWrapper(&nextPtr, p);
136 }
137 m_properties.push_back(p);
138 }
139 }
140
141 vki.getPhysicalDeviceProperties2(physicalDevice, &m_coreProperties2);
142
143 // fill data from VkPhysicalDeviceVulkan1{1,2,3}Properties
144 if (vk12Supported)
145 {
146 AllPropertiesBlobs allBlobs = {
147 m_vulkan11Properties, m_vulkan12Properties,
148 #ifndef CTS_USES_VULKANSC
149 m_vulkan13Properties,
150 #endif // CTS_USES_VULKANSC
151 // add blobs from future vulkan versions here
152 };
153
154 // three properties that were added with vk11 in vk12 were merged to VkPhysicalDeviceVulkan11Properties
155 propertiesToFillFromBlob.insert(propertiesToFillFromBlob.end(), propertiesAddedWithVK.begin(),
156 propertiesAddedWithVK.end());
157
158 for (auto property : propertiesToFillFromBlob)
159 property->initializePropertyFromBlob(allBlobs);
160 }
161 }
162 else
163 m_coreProperties2.properties = getPhysicalDeviceProperties(vki, physicalDevice);
164 }
165
addToChainStructWrapper(void *** chainPNextPtr,PropertyStructWrapperBase * structWrapper)166 void DeviceProperties::addToChainStructWrapper(void ***chainPNextPtr, PropertyStructWrapperBase *structWrapper)
167 {
168 DE_ASSERT(chainPNextPtr != DE_NULL);
169
170 (**chainPNextPtr) = structWrapper->getPropertyTypeRaw();
171 (*chainPNextPtr) = structWrapper->getPropertyTypeNext();
172 }
173
contains(const std::string & property,bool throwIfNotExists) const174 bool DeviceProperties::contains(const std::string &property, bool throwIfNotExists) const
175 {
176 for (const auto f : m_properties)
177 {
178 if (deStringEqual(f->getPropertyDesc().name, property.c_str()))
179 return true;
180 }
181
182 if (throwIfNotExists)
183 TCU_THROW(NotSupportedError, "Property " + property + " is not supported");
184
185 return false;
186 }
187
isDevicePropertyInitialized(VkStructureType sType) const188 bool DeviceProperties::isDevicePropertyInitialized(VkStructureType sType) const
189 {
190 for (const auto f : m_properties)
191 {
192 if (f->getPropertyDesc().sType == sType)
193 return true;
194 }
195 return false;
196 }
197
~DeviceProperties(void)198 DeviceProperties::~DeviceProperties(void)
199 {
200 for (auto p : m_properties)
201 delete p;
202
203 m_properties.clear();
204 }
205
206 } // namespace vk
207