1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 Google 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 * \file
21 * \brief Vulkan test case base classes
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktTestCase.hpp"
25 #include "vktCustomInstancesDevices.hpp"
26
27 #include "vkRef.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkDebugReportUtil.hpp"
34 #include "vkDeviceFeatures.hpp"
35 #include "vkDeviceProperties.hpp"
36
37 #include "tcuCommandLine.hpp"
38 #include "tcuTestLog.hpp"
39
40 #include "deSTLUtil.hpp"
41 #include "deMemory.h"
42
43 #include <set>
44
45 struct vk_executor;
46
47 namespace vkt
48 {
49
50 // Default device utilities
51
52 using std::vector;
53 using std::string;
54 using std::set;
55 using namespace vk;
56
57 namespace
58 {
59
filterExtensions(const vector<VkExtensionProperties> & extensions)60 vector<string> filterExtensions (const vector<VkExtensionProperties>& extensions)
61 {
62 vector<string> enabledExtensions;
63 bool khrBufferDeviceAddress = false;
64
65 const char* extensionGroups[] =
66 {
67 "VK_KHR_",
68 "VK_EXT_",
69 "VK_KHX_",
70 "VK_NV_cooperative_matrix",
71 "VK_EXT_extended_dynamic_state2",
72 "VK_NV_ray_tracing",
73 "VK_NV_inherited_viewport_scissor",
74 "VK_AMD_mixed_attachment_samples",
75 "VK_AMD_shader_fragment_mask",
76 "VK_AMD_buffer_marker",
77 "VK_AMD_shader_explicit_vertex_parameter",
78 "VK_AMD_shader_image_load_store_lod",
79 "VK_AMD_shader_trinary_minmax",
80 "VK_AMD_texture_gather_bias_lod",
81 "VK_ANDROID_external_memory_android_hardware_buffer",
82 };
83
84 for (size_t extNdx = 0; extNdx < extensions.size(); extNdx++)
85 {
86 if (deStringEqual(extensions[extNdx].extensionName, "VK_KHR_buffer_device_address"))
87 {
88 khrBufferDeviceAddress = true;
89 break;
90 }
91 }
92
93 for (size_t extNdx = 0; extNdx < extensions.size(); extNdx++)
94 {
95 const auto& extName = extensions[extNdx].extensionName;
96
97 // Skip enabling VK_KHR_pipeline_library unless needed.
98 if (deStringEqual(extName, "VK_KHR_pipeline_library"))
99 continue;
100
101 // VK_EXT_buffer_device_address is deprecated and must not be enabled if VK_KHR_buffer_device_address is enabled
102 if (khrBufferDeviceAddress && deStringEqual(extName, "VK_EXT_buffer_device_address"))
103 continue;
104
105 for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++)
106 {
107 if (deStringBeginsWith(extName, extensionGroups[extGroupNdx]))
108 enabledExtensions.push_back(extName);
109 }
110 }
111
112 return enabledExtensions;
113 }
114
addExtensions(const vector<string> & a,const vector<const char * > & b)115 vector<string> addExtensions (const vector<string>& a, const vector<const char*>& b)
116 {
117 vector<string> res (a);
118
119 for (vector<const char*>::const_iterator bIter = b.begin(); bIter != b.end(); ++bIter)
120 {
121 if (!de::contains(res.begin(), res.end(), string(*bIter)))
122 res.push_back(string(*bIter));
123 }
124
125 return res;
126 }
127
removeExtensions(const vector<string> & a,const vector<const char * > & b)128 vector<string> removeExtensions (const vector<string>& a, const vector<const char*>& b)
129 {
130 vector<string> res;
131 set<string> removeExts (b.begin(), b.end());
132
133 for (vector<string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
134 {
135 if (!de::contains(removeExts, *aIter))
136 res.push_back(*aIter);
137 }
138
139 return res;
140 }
141
addCoreInstanceExtensions(const vector<string> & extensions,deUint32 instanceVersion)142 vector<string> addCoreInstanceExtensions (const vector<string>& extensions, deUint32 instanceVersion)
143 {
144 vector<const char*> coreExtensions;
145 getCoreInstanceExtensions(instanceVersion, coreExtensions);
146 return addExtensions(extensions, coreExtensions);
147 }
148
addCoreDeviceExtensions(const vector<string> & extensions,deUint32 instanceVersion)149 vector<string> addCoreDeviceExtensions(const vector<string>& extensions, deUint32 instanceVersion)
150 {
151 vector<const char*> coreExtensions;
152 getCoreDeviceExtensions(instanceVersion, coreExtensions);
153 return addExtensions(extensions, coreExtensions);
154 }
155
getTargetInstanceVersion(const PlatformInterface & vkp)156 deUint32 getTargetInstanceVersion (const PlatformInterface& vkp)
157 {
158 deUint32 version = pack(ApiVersion(1, 0, 0));
159
160 if (vkp.enumerateInstanceVersion(&version) != VK_SUCCESS)
161 TCU_THROW(InternalError, "Enumerate instance version error");
162 return version;
163 }
164
determineDeviceVersions(const PlatformInterface & vkp,deUint32 apiVersion,const tcu::CommandLine & cmdLine)165 std::pair<deUint32, deUint32> determineDeviceVersions(const PlatformInterface& vkp, deUint32 apiVersion, const tcu::CommandLine& cmdLine)
166 {
167 Move<VkInstance> preinstance = createDefaultInstance(vkp, apiVersion);
168 InstanceDriver preinterface (vkp, preinstance.get());
169
170 const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(preinterface, preinstance.get());
171 deUint32 lowestDeviceVersion = 0xFFFFFFFFu;
172 for (deUint32 deviceNdx = 0u; deviceNdx < devices.size(); ++deviceNdx)
173 {
174 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, devices[deviceNdx]);
175 if (props.apiVersion < lowestDeviceVersion)
176 lowestDeviceVersion = props.apiVersion;
177 }
178
179 const vk::VkPhysicalDevice choosenDevice = chooseDevice(preinterface, *preinstance, cmdLine);
180 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, choosenDevice);
181 const deUint32 choosenDeviceVersion = props.apiVersion;
182
183 return std::make_pair(choosenDeviceVersion, lowestDeviceVersion);
184 }
185
186
createInstance(const PlatformInterface & vkp,deUint32 apiVersion,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine)187 Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine)
188 {
189 const bool isValidationEnabled = cmdLine.isValidationEnabled();
190 vector<const char*> enabledLayers;
191
192 // \note Extensions in core are not explicitly enabled even though
193 // they are in the extension list advertised to tests.
194 vector<const char*> coreExtensions;
195 getCoreInstanceExtensions(apiVersion, coreExtensions);
196 vector<string> nonCoreExtensions (removeExtensions(enabledExtensions, coreExtensions));
197
198 if (isValidationEnabled)
199 {
200 if (!isDebugReportSupported(vkp))
201 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
202
203 enabledLayers = vkt::getValidationLayers(vkp);
204 if (enabledLayers.empty())
205 TCU_THROW(NotSupportedError, "No validation layers found");
206 }
207
208 return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions);
209 }
210
findQueueFamilyIndexWithCaps(const InstanceInterface & vkInstance,VkPhysicalDevice physicalDevice,VkQueueFlags requiredCaps)211 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
212 {
213 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
214
215 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
216 {
217 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
218 return (deUint32)queueNdx;
219 }
220
221 TCU_THROW(NotSupportedError, "No matching queue found");
222 }
223
createDefaultDevice(const PlatformInterface & vkp,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const deUint32 apiVersion,deUint32 queueIndex,deUint32 sparseQueueIndex,const VkPhysicalDeviceFeatures2 & enabledFeatures,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine)224 Move<VkDevice> createDefaultDevice (const PlatformInterface& vkp,
225 VkInstance instance,
226 const InstanceInterface& vki,
227 VkPhysicalDevice physicalDevice,
228 const deUint32 apiVersion,
229 deUint32 queueIndex,
230 deUint32 sparseQueueIndex,
231 const VkPhysicalDeviceFeatures2& enabledFeatures,
232 const vector<string>& enabledExtensions,
233 const tcu::CommandLine& cmdLine)
234 {
235 VkDeviceQueueCreateInfo queueInfo[2];
236 VkDeviceCreateInfo deviceInfo;
237 vector<const char*> enabledLayers;
238 vector<const char*> extensionPtrs;
239 const float queuePriority = 1.0f;
240 const deUint32 numQueues = (enabledFeatures.features.sparseBinding && (queueIndex != sparseQueueIndex)) ? 2 : 1;
241
242 deMemset(&queueInfo, 0, sizeof(queueInfo));
243 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
244
245 if (cmdLine.isValidationEnabled())
246 {
247 enabledLayers = vkt::getValidationLayers(vki, physicalDevice);
248 if (enabledLayers.empty())
249 TCU_THROW(NotSupportedError, "No validation layers found");
250 }
251
252 // \note Extensions in core are not explicitly enabled even though
253 // they are in the extension list advertised to tests.
254 vector<const char*> coreExtensions;
255 getCoreDeviceExtensions(apiVersion, coreExtensions);
256 vector<string> nonCoreExtensions(removeExtensions(enabledExtensions, coreExtensions));
257
258 extensionPtrs.resize(nonCoreExtensions.size());
259
260 for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx)
261 extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str();
262
263 queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
264 queueInfo[0].pNext = DE_NULL;
265 queueInfo[0].flags = (VkDeviceQueueCreateFlags)0u;
266 queueInfo[0].queueFamilyIndex = queueIndex;
267 queueInfo[0].queueCount = 1u;
268 queueInfo[0].pQueuePriorities = &queuePriority;
269
270 if (numQueues > 1)
271 {
272 queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
273 queueInfo[1].pNext = DE_NULL;
274 queueInfo[1].flags = (VkDeviceQueueCreateFlags)0u;
275 queueInfo[1].queueFamilyIndex = sparseQueueIndex;
276 queueInfo[1].queueCount = 1u;
277 queueInfo[1].pQueuePriorities = &queuePriority;
278 }
279
280 // VK_KHR_get_physical_device_properties2 is used if enabledFeatures.pNext != 0
281 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
282 deviceInfo.pNext = enabledFeatures.pNext ? &enabledFeatures : DE_NULL;
283 deviceInfo.queueCreateInfoCount = numQueues;
284 deviceInfo.pQueueCreateInfos = queueInfo;
285 deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size();
286 deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]);
287 deviceInfo.enabledLayerCount = (deUint32)enabledLayers.size();
288 deviceInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
289 deviceInfo.pEnabledFeatures = enabledFeatures.pNext ? DE_NULL : &enabledFeatures.features;
290
291 return createDevice(vkp, instance, vki, physicalDevice, &deviceInfo);
292 };
293
294 } // anonymous
295
296 class DefaultDevice
297 {
298 public:
299 DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
300 ~DefaultDevice (void);
301
getInstance(void) const302 VkInstance getInstance (void) const { return *m_instance; }
getInstanceInterface(void) const303 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; }
getMaximumFrameworkVulkanVersion(void) const304 deUint32 getMaximumFrameworkVulkanVersion (void) const { return m_maximumFrameworkVulkanVersion; }
getAvailableInstanceVersion(void) const305 deUint32 getAvailableInstanceVersion (void) const { return m_availableInstanceVersion; }
getUsedInstanceVersion(void) const306 deUint32 getUsedInstanceVersion (void) const { return m_usedInstanceVersion; }
getInstanceExtensions(void) const307 const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; }
308
getPhysicalDevice(void) const309 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
getDeviceVersion(void) const310 deUint32 getDeviceVersion (void) const { return m_deviceVersion; }
311
isDeviceFeatureInitialized(VkStructureType sType) const312 bool isDeviceFeatureInitialized (VkStructureType sType) const { return m_deviceFeatures.isDeviceFeatureInitialized(sType); }
getDeviceFeatures(void) const313 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures.getCoreFeatures2().features; }
getDeviceFeatures2(void) const314 const VkPhysicalDeviceFeatures2& getDeviceFeatures2 (void) const { return m_deviceFeatures.getCoreFeatures2(); }
getVulkan11Features(void) const315 const VkPhysicalDeviceVulkan11Features& getVulkan11Features (void) const { return m_deviceFeatures.getVulkan11Features(); }
getVulkan12Features(void) const316 const VkPhysicalDeviceVulkan12Features& getVulkan12Features (void) const { return m_deviceFeatures.getVulkan12Features(); }
317
318 #include "vkDeviceFeaturesForDefaultDeviceDefs.inl"
319
isDevicePropertyInitialized(VkStructureType sType) const320 bool isDevicePropertyInitialized (VkStructureType sType) const { return m_deviceProperties.isDevicePropertyInitialized(sType); }
getDeviceProperties(void) const321 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties.getCoreProperties2().properties; }
getDeviceProperties2(void) const322 const VkPhysicalDeviceProperties2& getDeviceProperties2 (void) const { return m_deviceProperties.getCoreProperties2(); }
getVulkan11Properties(void) const323 const VkPhysicalDeviceVulkan11Properties& getVulkan11Properties (void) const { return m_deviceProperties.getVulkan11Properties(); }
getVulkan12Properties(void) const324 const VkPhysicalDeviceVulkan12Properties& getVulkan12Properties (void) const { return m_deviceProperties.getVulkan12Properties(); }
325
326 #include "vkDevicePropertiesForDefaultDeviceDefs.inl"
327
getDevice(void) const328 VkDevice getDevice (void) const { return *m_device; }
getDeviceInterface(void) const329 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; }
getDeviceExtensions(void) const330 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; }
getUsedApiVersion(void) const331 deUint32 getUsedApiVersion (void) const { return m_usedApiVersion; }
getUniversalQueueFamilyIndex(void) const332 deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; }
333 VkQueue getUniversalQueue (void) const;
getSparseQueueFamilyIndex(void) const334 deUint32 getSparseQueueFamilyIndex (void) const { return m_sparseQueueFamilyIndex; }
335 VkQueue getSparseQueue (void) const;
336
hasDebugReportRecorder(void) const337 bool hasDebugReportRecorder (void) const { return m_debugReportRecorder.get() != nullptr; }
getDebugReportRecorder(void) const338 vk::DebugReportRecorder& getDebugReportRecorder (void) const { return *m_debugReportRecorder.get(); }
339
340 private:
341 using DebugReportRecorderPtr = de::UniquePtr<vk::DebugReportRecorder>;
342
343 const deUint32 m_maximumFrameworkVulkanVersion;
344 const deUint32 m_availableInstanceVersion;
345 const deUint32 m_usedInstanceVersion;
346
347 const std::pair<deUint32, deUint32> m_deviceVersions;
348 const deUint32 m_usedApiVersion;
349
350 const vector<string> m_instanceExtensions;
351 const Unique<VkInstance> m_instance;
352 const InstanceDriver m_instanceInterface;
353 const DebugReportRecorderPtr m_debugReportRecorder;
354
355 const VkPhysicalDevice m_physicalDevice;
356 const deUint32 m_deviceVersion;
357
358 const vector<string> m_deviceExtensions;
359 const DeviceFeatures m_deviceFeatures;
360
361 const deUint32 m_universalQueueFamilyIndex;
362 const deUint32 m_sparseQueueFamilyIndex;
363 const DeviceProperties m_deviceProperties;
364
365 const Unique<VkDevice> m_device;
366 const DeviceDriver m_deviceInterface;
367 };
368
369 namespace
370 {
371
sanitizeApiVersion(deUint32 v)372 deUint32 sanitizeApiVersion(deUint32 v)
373 {
374 return VK_MAKE_VERSION(VK_API_VERSION_MAJOR(v), VK_API_VERSION_MINOR(v), 0 );
375 }
376
createDebugReportRecorder(const vk::PlatformInterface & vkp,const vk::InstanceInterface & vki,vk::VkInstance instance,bool printValidationErrors)377 de::MovePtr<vk::DebugReportRecorder> createDebugReportRecorder (const vk::PlatformInterface& vkp, const vk::InstanceInterface& vki, vk::VkInstance instance, bool printValidationErrors)
378 {
379 if (isDebugReportSupported(vkp))
380 return de::MovePtr<vk::DebugReportRecorder>(new vk::DebugReportRecorder(vki, instance, printValidationErrors));
381 else
382 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
383 }
384
385 } // anonymous
386
DefaultDevice(const PlatformInterface & vkPlatform,const tcu::CommandLine & cmdLine)387 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
388 : m_maximumFrameworkVulkanVersion (VK_API_MAX_FRAMEWORK_VERSION)
389 , m_availableInstanceVersion (getTargetInstanceVersion(vkPlatform))
390 , m_usedInstanceVersion (sanitizeApiVersion(deMinu32(m_availableInstanceVersion, m_maximumFrameworkVulkanVersion)))
391 , m_deviceVersions (determineDeviceVersions(vkPlatform, m_usedInstanceVersion, cmdLine))
392 , m_usedApiVersion (sanitizeApiVersion(deMinu32(m_usedInstanceVersion, m_deviceVersions.first)))
393
394 , m_instanceExtensions (addCoreInstanceExtensions(filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)), m_usedApiVersion))
395 , m_instance (createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine))
396
397 , m_instanceInterface (vkPlatform, *m_instance)
398 , m_debugReportRecorder (cmdLine.isValidationEnabled()
399 ? createDebugReportRecorder(vkPlatform,
400 m_instanceInterface,
401 *m_instance,
402 cmdLine.printValidationErrors())
403 : de::MovePtr<vk::DebugReportRecorder>(DE_NULL))
404 , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
405 , m_deviceVersion (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice).apiVersion)
406
407 , m_deviceExtensions (addCoreDeviceExtensions(filterExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)), m_usedApiVersion))
408 , m_deviceFeatures (m_instanceInterface, m_usedApiVersion, m_physicalDevice, m_instanceExtensions, m_deviceExtensions)
409 , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
410 , m_sparseQueueFamilyIndex (m_deviceFeatures.getCoreFeatures2().features.sparseBinding ? findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_SPARSE_BINDING_BIT) : 0)
411 , m_deviceProperties (m_instanceInterface, m_usedApiVersion, m_physicalDevice, m_instanceExtensions, m_deviceExtensions)
412 , m_device (createDefaultDevice(vkPlatform, *m_instance, m_instanceInterface, m_physicalDevice, m_usedApiVersion, m_universalQueueFamilyIndex, m_sparseQueueFamilyIndex, m_deviceFeatures.getCoreFeatures2(), m_deviceExtensions, cmdLine))
413 , m_deviceInterface (vkPlatform, *m_instance, *m_device)
414 {
415 DE_ASSERT(m_deviceVersions.first == m_deviceVersion);
416 }
417
~DefaultDevice(void)418 DefaultDevice::~DefaultDevice (void)
419 {
420 }
421
getUniversalQueue(void) const422 VkQueue DefaultDevice::getUniversalQueue (void) const
423 {
424 return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0);
425 }
426
getSparseQueue(void) const427 VkQueue DefaultDevice::getSparseQueue (void) const
428 {
429 if (!m_deviceFeatures.getCoreFeatures2().features.sparseBinding)
430 TCU_THROW(NotSupportedError, "Sparse binding not supported.");
431
432 return getDeviceQueue(m_deviceInterface, *m_device, m_sparseQueueFamilyIndex, 0);
433 }
434
435 namespace
436 {
437 // Allocator utilities
438
createAllocator(DefaultDevice * device)439 vk::Allocator* createAllocator (DefaultDevice* device)
440 {
441 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
442
443 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
444 return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
445 }
446
447 } // anonymous
448
449 // Context
450
Context(tcu::TestContext & testCtx,const vk::PlatformInterface & platformInterface,vk::BinaryCollection & progCollection)451 Context::Context (tcu::TestContext& testCtx,
452 const vk::PlatformInterface& platformInterface,
453 vk::BinaryCollection& progCollection)
454 : m_testCtx (testCtx)
455 , m_platformInterface (platformInterface)
456 , m_progCollection (progCollection)
457 , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
458 , m_allocator (createAllocator(m_device.get()))
459 , m_resultSetOnValidation (false)
460 {
461 }
462
~Context(void)463 Context::~Context (void)
464 {
465 }
466
getMaximumFrameworkVulkanVersion(void) const467 deUint32 Context::getMaximumFrameworkVulkanVersion (void) const { return m_device->getMaximumFrameworkVulkanVersion(); }
getAvailableInstanceVersion(void) const468 deUint32 Context::getAvailableInstanceVersion (void) const { return m_device->getAvailableInstanceVersion(); }
getInstanceExtensions(void) const469 const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); }
getInstance(void) const470 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); }
getInstanceInterface(void) const471 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); }
getPhysicalDevice(void) const472 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); }
getDeviceVersion(void) const473 deUint32 Context::getDeviceVersion (void) const { return m_device->getDeviceVersion(); }
getDeviceFeatures(void) const474 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); }
getDeviceFeatures2(void) const475 const vk::VkPhysicalDeviceFeatures2& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); }
476
isDeviceFunctionalitySupported(const std::string & extension) const477 bool Context::isDeviceFunctionalitySupported (const std::string& extension) const
478 {
479 // check if extension was promoted to core
480 deUint32 apiVersion = getUsedApiVersion();
481 if (isCoreDeviceExtension(apiVersion, extension))
482 {
483 if (apiVersion < VK_MAKE_VERSION(1, 2, 0))
484 {
485 // Check feature bits in extension-specific structures.
486 if (extension == "VK_KHR_multiview")
487 return !!m_device->getMultiviewFeatures().multiview;
488 if (extension == "VK_KHR_variable_pointers")
489 return !!m_device->getVariablePointersFeatures().variablePointersStorageBuffer;
490 if (extension == "VK_KHR_sampler_ycbcr_conversion")
491 return !!m_device->getSamplerYcbcrConversionFeatures().samplerYcbcrConversion;
492 if (extension == "VK_KHR_shader_draw_parameters")
493 return !!m_device->getShaderDrawParametersFeatures().shaderDrawParameters;
494 }
495 else
496 {
497 // Check feature bits using the new Vulkan 1.2 structures.
498 const auto& vk11Features = m_device->getVulkan11Features();
499 if (extension == "VK_KHR_multiview")
500 return !!vk11Features.multiview;
501 if (extension == "VK_KHR_variable_pointers")
502 return !!vk11Features.variablePointersStorageBuffer;
503 if (extension == "VK_KHR_sampler_ycbcr_conversion")
504 return !!vk11Features.samplerYcbcrConversion;
505 if (extension == "VK_KHR_shader_draw_parameters")
506 return !!vk11Features.shaderDrawParameters;
507
508 const auto& vk12Features = m_device->getVulkan12Features();
509 if (extension == "VK_KHR_timeline_semaphore")
510 return !!vk12Features.timelineSemaphore;
511 if (extension == "VK_KHR_buffer_device_address")
512 return !!vk12Features.bufferDeviceAddress;
513 if (extension == "VK_EXT_descriptor_indexing")
514 return !!vk12Features.descriptorIndexing;
515 if (extension == "VK_KHR_draw_indirect_count")
516 return !!vk12Features.drawIndirectCount;
517 if (extension == "VK_KHR_sampler_mirror_clamp_to_edge")
518 return !!vk12Features.samplerMirrorClampToEdge;
519 if (extension == "VK_EXT_sampler_filter_minmax")
520 return !!vk12Features.samplerFilterMinmax;
521 if (extension == "VK_EXT_shader_viewport_index_layer")
522 return !!vk12Features.shaderOutputViewportIndex && !!vk12Features.shaderOutputLayer;
523 }
524
525 // No feature flags to check.
526 return true;
527 }
528
529 // check if extension is on the lits of extensions for current device
530 const auto& extensions = getDeviceExtensions();
531 if (de::contains(extensions.begin(), extensions.end(), extension))
532 {
533 if (extension == "VK_KHR_timeline_semaphore")
534 return !!getTimelineSemaphoreFeatures().timelineSemaphore;
535 if (extension == "VK_KHR_synchronization2")
536 return !!getSynchronization2Features().synchronization2;
537 if (extension == "VK_EXT_extended_dynamic_state")
538 return !!getExtendedDynamicStateFeaturesEXT().extendedDynamicState;
539 if (extension == "VK_EXT_shader_demote_to_helper_invocation")
540 return !!getShaderDemoteToHelperInvocationFeaturesEXT().shaderDemoteToHelperInvocation;
541 if (extension == "VK_KHR_workgroup_memory_explicit_layout")
542 return !!getWorkgroupMemoryExplicitLayoutFeatures().workgroupMemoryExplicitLayout;
543
544 return true;
545 }
546
547 return false;
548 }
549
isInstanceFunctionalitySupported(const std::string & extension) const550 bool Context::isInstanceFunctionalitySupported(const std::string& extension) const
551 {
552 // NOTE: current implementation uses isInstanceExtensionSupported but
553 // this will change when some instance extensions will be promoted to the
554 // core; don't use isInstanceExtensionSupported directly, use this method instead
555 return isInstanceExtensionSupported(getUsedApiVersion(), getInstanceExtensions(), extension);
556 }
557
558 #include "vkDeviceFeaturesForContextDefs.inl"
559
getDeviceProperties(void) const560 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); }
getDeviceProperties2(void) const561 const vk::VkPhysicalDeviceProperties2& Context::getDeviceProperties2 (void) const { return m_device->getDeviceProperties2(); }
562
563 #include "vkDevicePropertiesForContextDefs.inl"
564
getDeviceExtensions(void) const565 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); }
getDevice(void) const566 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); }
getDeviceInterface(void) const567 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); }
getUniversalQueueFamilyIndex(void) const568 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); }
getUniversalQueue(void) const569 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); }
getSparseQueueFamilyIndex(void) const570 deUint32 Context::getSparseQueueFamilyIndex (void) const { return m_device->getSparseQueueFamilyIndex(); }
getSparseQueue(void) const571 vk::VkQueue Context::getSparseQueue (void) const { return m_device->getSparseQueue(); }
getDefaultAllocator(void) const572 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; }
getUsedApiVersion(void) const573 deUint32 Context::getUsedApiVersion (void) const { return m_device->getUsedApiVersion(); }
contextSupports(const deUint32 majorNum,const deUint32 minorNum,const deUint32 patchNum) const574 bool Context::contextSupports (const deUint32 majorNum, const deUint32 minorNum, const deUint32 patchNum) const
575 { return m_device->getUsedApiVersion() >= VK_MAKE_VERSION(majorNum, minorNum, patchNum); }
contextSupports(const ApiVersion version) const576 bool Context::contextSupports (const ApiVersion version) const
577 { return m_device->getUsedApiVersion() >= pack(version); }
contextSupports(const deUint32 requiredApiVersionBits) const578 bool Context::contextSupports (const deUint32 requiredApiVersionBits) const
579 { return m_device->getUsedApiVersion() >= requiredApiVersionBits; }
isDeviceFeatureInitialized(vk::VkStructureType sType) const580 bool Context::isDeviceFeatureInitialized (vk::VkStructureType sType) const
581 { return m_device->isDeviceFeatureInitialized(sType); }
isDevicePropertyInitialized(vk::VkStructureType sType) const582 bool Context::isDevicePropertyInitialized (vk::VkStructureType sType) const
583 { return m_device->isDevicePropertyInitialized(sType); }
584
requireDeviceFunctionality(const std::string & required) const585 bool Context::requireDeviceFunctionality (const std::string& required) const
586 {
587 if (!isDeviceFunctionalitySupported(required))
588 TCU_THROW(NotSupportedError, required + " is not supported");
589
590 return true;
591 }
592
requireInstanceFunctionality(const std::string & required) const593 bool Context::requireInstanceFunctionality (const std::string& required) const
594 {
595 if (!isInstanceFunctionalitySupported(required))
596 TCU_THROW(NotSupportedError, required + " is not supported");
597
598 return true;
599 }
600
601 struct DeviceCoreFeaturesTable
602 {
603 const char* featureName;
604 const deUint32 featureArrayIndex;
605 const deUint32 featureArrayOffset;
606 };
607
608 #define DEVICE_CORE_FEATURE_OFFSET(FEATURE_FIELD_NAME) DE_OFFSET_OF(VkPhysicalDeviceFeatures, FEATURE_FIELD_NAME)
609 #define DEVICE_CORE_FEATURE_ENTRY(BITNAME, FIELDNAME) { #FIELDNAME, BITNAME, DEVICE_CORE_FEATURE_OFFSET(FIELDNAME) }
610
611 const DeviceCoreFeaturesTable deviceCoreFeaturesTable[] =
612 {
613 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_ROBUST_BUFFER_ACCESS , robustBufferAccess ),
614 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FULL_DRAW_INDEX_UINT32 , fullDrawIndexUint32 ),
615 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY , imageCubeArray ),
616 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_INDEPENDENT_BLEND , independentBlend ),
617 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_GEOMETRY_SHADER , geometryShader ),
618 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TESSELLATION_SHADER , tessellationShader ),
619 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING , sampleRateShading ),
620 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DUAL_SRC_BLEND , dualSrcBlend ),
621 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_LOGIC_OP , logicOp ),
622 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_MULTI_DRAW_INDIRECT , multiDrawIndirect ),
623 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DRAW_INDIRECT_FIRST_INSTANCE , drawIndirectFirstInstance ),
624 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_CLAMP , depthClamp ),
625 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_BIAS_CLAMP , depthBiasClamp ),
626 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FILL_MODE_NON_SOLID , fillModeNonSolid ),
627 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_BOUNDS , depthBounds ),
628 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_WIDE_LINES , wideLines ),
629 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_LARGE_POINTS , largePoints ),
630 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_ALPHA_TO_ONE , alphaToOne ),
631 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_MULTI_VIEWPORT , multiViewport ),
632 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SAMPLER_ANISOTROPY , samplerAnisotropy ),
633 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_ETC2 , textureCompressionETC2 ),
634 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_ASTC_LDR , textureCompressionASTC_LDR ),
635 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_BC , textureCompressionBC ),
636 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_OCCLUSION_QUERY_PRECISE , occlusionQueryPrecise ),
637 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_PIPELINE_STATISTICS_QUERY , pipelineStatisticsQuery ),
638 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS , vertexPipelineStoresAndAtomics ),
639 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS , fragmentStoresAndAtomics ),
640 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE , shaderTessellationAndGeometryPointSize ),
641 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED , shaderImageGatherExtended ),
642 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS , shaderStorageImageExtendedFormats ),
643 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_MULTISAMPLE , shaderStorageImageMultisample ),
644 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT , shaderStorageImageReadWithoutFormat ),
645 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT , shaderStorageImageWriteWithoutFormat ),
646 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING , shaderUniformBufferArrayDynamicIndexing ),
647 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING , shaderSampledImageArrayDynamicIndexing ),
648 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING , shaderStorageBufferArrayDynamicIndexing ),
649 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING , shaderStorageImageArrayDynamicIndexing ),
650 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE , shaderClipDistance ),
651 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_CULL_DISTANCE , shaderCullDistance ),
652 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_FLOAT64 , shaderFloat64 ),
653 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_INT64 , shaderInt64 ),
654 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_INT16 , shaderInt16 ),
655 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_RESOURCE_RESIDENCY , shaderResourceResidency ),
656 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_RESOURCE_MIN_LOD , shaderResourceMinLod ),
657 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_BINDING , sparseBinding ),
658 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_BUFFER , sparseResidencyBuffer ),
659 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_IMAGE2D , sparseResidencyImage2D ),
660 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_IMAGE3D , sparseResidencyImage3D ),
661 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY2_SAMPLES , sparseResidency2Samples ),
662 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY4_SAMPLES , sparseResidency4Samples ),
663 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY8_SAMPLES , sparseResidency8Samples ),
664 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY16_SAMPLES , sparseResidency16Samples ),
665 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_ALIASED , sparseResidencyAliased ),
666 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_VARIABLE_MULTISAMPLE_RATE , variableMultisampleRate ),
667 DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_INHERITED_QUERIES , inheritedQueries ),
668 };
669
requireDeviceCoreFeature(const DeviceCoreFeature requiredFeature)670 bool Context::requireDeviceCoreFeature (const DeviceCoreFeature requiredFeature)
671 {
672 const vk::VkPhysicalDeviceFeatures& featuresAvailable = getDeviceFeatures();
673 const vk::VkBool32* featuresAvailableArray = (vk::VkBool32*)(&featuresAvailable);
674 const deUint32 requiredFeatureIndex = static_cast<deUint32>(requiredFeature);
675
676 DE_ASSERT(requiredFeatureIndex * sizeof(vk::VkBool32) < sizeof(featuresAvailable));
677 DE_ASSERT(deviceCoreFeaturesTable[requiredFeatureIndex].featureArrayIndex * sizeof(vk::VkBool32) == deviceCoreFeaturesTable[requiredFeatureIndex].featureArrayOffset);
678
679 if (featuresAvailableArray[requiredFeatureIndex] == DE_FALSE)
680 TCU_THROW(NotSupportedError, "Requested core feature is not supported: " + std::string(deviceCoreFeaturesTable[requiredFeatureIndex].featureName));
681
682 return true;
683 }
684
getInstanceProcAddr()685 void* Context::getInstanceProcAddr ()
686 {
687 return (void*)m_platformInterface.getGetInstanceProcAddr();
688 }
689
isBufferDeviceAddressSupported(void) const690 bool Context::isBufferDeviceAddressSupported(void) const
691 {
692 return isDeviceFunctionalitySupported("VK_KHR_buffer_device_address") ||
693 isDeviceFunctionalitySupported("VK_EXT_buffer_device_address");
694 }
695
hasDebugReportRecorder() const696 bool Context::hasDebugReportRecorder () const
697 {
698 return m_device->hasDebugReportRecorder();
699 }
700
getDebugReportRecorder() const701 vk::DebugReportRecorder& Context::getDebugReportRecorder () const
702 {
703 return m_device->getDebugReportRecorder();
704 }
705
706 // TestCase
707
initPrograms(SourceCollections &) const708 void TestCase::initPrograms (SourceCollections&) const
709 {
710 }
711
checkSupport(Context &) const712 void TestCase::checkSupport (Context&) const
713 {
714 }
715
delayedInit(void)716 void TestCase::delayedInit (void)
717 {
718 }
719
collectAndReportDebugMessages(vk::DebugReportRecorder & debugReportRecorder,Context & context)720 void collectAndReportDebugMessages(vk::DebugReportRecorder &debugReportRecorder, Context& context)
721 {
722 using DebugMessages = vk::DebugReportRecorder::MessageList;
723
724 const DebugMessages& messages = debugReportRecorder.getMessages();
725 tcu::TestLog& log = context.getTestContext().getLog();
726
727 if (messages.size() > 0)
728 {
729 const tcu::ScopedLogSection section (log, "DebugMessages", "Debug Messages");
730 int numErrors = 0;
731
732 for (const auto& msg : messages)
733 {
734 if (msg.shouldBeLogged())
735 log << tcu::TestLog::Message << msg << tcu::TestLog::EndMessage;
736
737 if (msg.isError())
738 numErrors += 1;
739 }
740
741 debugReportRecorder.clearMessages();
742
743 if (numErrors > 0)
744 {
745 string errorMsg = de::toString(numErrors) + " API usage errors found";
746 context.resultSetOnValidation(true);
747 context.getTestContext().setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, errorMsg.c_str());
748 }
749 }
750 }
751
752 } // vkt
753