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