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
26 #include "vkRef.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkDebugReportUtil.hpp"
33
34 #include "tcuCommandLine.hpp"
35
36 #include "deMemory.h"
37
38 namespace vkt
39 {
40
41 // Default device utilities
42
43 using std::vector;
44 using std::string;
45 using namespace vk;
46
getValidationLayers(const vector<VkLayerProperties> & supportedLayers)47 vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers)
48 {
49 static const char* s_magicLayer = "VK_LAYER_LUNARG_standard_validation";
50 static const char* s_defaultLayers[] =
51 {
52 "VK_LAYER_GOOGLE_threading",
53 "VK_LAYER_LUNARG_parameter_validation",
54 "VK_LAYER_LUNARG_device_limits",
55 "VK_LAYER_LUNARG_object_tracker",
56 "VK_LAYER_LUNARG_image",
57 "VK_LAYER_LUNARG_core_validation",
58 "VK_LAYER_LUNARG_swapchain",
59 "VK_LAYER_GOOGLE_unique_objects"
60 };
61
62 vector<string> enabledLayers;
63
64 if (isLayerSupported(supportedLayers, RequiredLayer(s_magicLayer)))
65 enabledLayers.push_back(s_magicLayer);
66 else
67 {
68 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
69 {
70 if (isLayerSupported(supportedLayers, RequiredLayer(s_defaultLayers[ndx])))
71 enabledLayers.push_back(s_defaultLayers[ndx]);
72 }
73 }
74
75 return enabledLayers;
76 }
77
getValidationLayers(const PlatformInterface & vkp)78 vector<string> getValidationLayers (const PlatformInterface& vkp)
79 {
80 return getValidationLayers(enumerateInstanceLayerProperties(vkp));
81 }
82
getValidationLayers(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)83 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
84 {
85 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
86 }
87
createInstance(const PlatformInterface & vkp,const tcu::CommandLine & cmdLine)88 Move<VkInstance> createInstance (const PlatformInterface& vkp, const tcu::CommandLine& cmdLine)
89 {
90 const bool isValidationEnabled = cmdLine.isValidationEnabled();
91 vector<string> enabledExtensions;
92 vector<string> enabledLayers;
93
94 if (isValidationEnabled)
95 {
96 if (isDebugReportSupported(vkp))
97 enabledExtensions.push_back("VK_EXT_debug_report");
98 else
99 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
100
101 enabledLayers = getValidationLayers(vkp);
102 if (enabledLayers.empty())
103 TCU_THROW(NotSupportedError, "No validation layers found");
104 }
105
106 return createDefaultInstance(vkp, enabledLayers, enabledExtensions);
107 }
108
findQueueFamilyIndexWithCaps(const InstanceInterface & vkInstance,VkPhysicalDevice physicalDevice,VkQueueFlags requiredCaps)109 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
110 {
111 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
112
113 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
114 {
115 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
116 return (deUint32)queueNdx;
117 }
118
119 TCU_THROW(NotSupportedError, "No matching queue found");
120 }
121
createDefaultDevice(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 queueIndex,const VkPhysicalDeviceFeatures & enabledFeatures,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine)122 Move<VkDevice> createDefaultDevice (const InstanceInterface& vki,
123 VkPhysicalDevice physicalDevice,
124 deUint32 queueIndex,
125 const VkPhysicalDeviceFeatures& enabledFeatures,
126 const vector<string>& enabledExtensions,
127 const tcu::CommandLine& cmdLine)
128 {
129 VkDeviceQueueCreateInfo queueInfo;
130 VkDeviceCreateInfo deviceInfo;
131 vector<string> enabledLayers;
132 vector<const char*> layerPtrs;
133 vector<const char*> extensionPtrs;
134 const float queuePriority = 1.0f;
135
136 deMemset(&queueInfo, 0, sizeof(queueInfo));
137 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
138
139 if (cmdLine.isValidationEnabled())
140 {
141 enabledLayers = getValidationLayers(vki, physicalDevice);
142 if (enabledLayers.empty())
143 TCU_THROW(NotSupportedError, "No validation layers found");
144 }
145
146 layerPtrs.resize(enabledLayers.size());
147
148 for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
149 layerPtrs[ndx] = enabledLayers[ndx].c_str();
150
151 extensionPtrs.resize(enabledExtensions.size());
152
153 for (size_t ndx = 0; ndx < enabledExtensions.size(); ++ndx)
154 extensionPtrs[ndx] = enabledExtensions[ndx].c_str();
155
156 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
157 queueInfo.pNext = DE_NULL;
158 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
159 queueInfo.queueFamilyIndex = queueIndex;
160 queueInfo.queueCount = 1u;
161 queueInfo.pQueuePriorities = &queuePriority;
162
163 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
164 deviceInfo.pNext = DE_NULL;
165 deviceInfo.queueCreateInfoCount = 1u;
166 deviceInfo.pQueueCreateInfos = &queueInfo;
167 deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size();
168 deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]);
169 deviceInfo.enabledLayerCount = (deUint32)layerPtrs.size();
170 deviceInfo.ppEnabledLayerNames = (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]);
171 deviceInfo.pEnabledFeatures = &enabledFeatures;
172
173 return createDevice(vki, physicalDevice, &deviceInfo);
174 };
175
176 class DefaultDevice
177 {
178 public:
179 DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
180 ~DefaultDevice (void);
181
getInstance(void) const182 VkInstance getInstance (void) const { return *m_instance; }
getInstanceInterface(void) const183 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; }
184
getPhysicalDevice(void) const185 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
getDeviceFeatures(void) const186 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures; }
getDevice(void) const187 VkDevice getDevice (void) const { return *m_device; }
getDeviceInterface(void) const188 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; }
getDeviceProperties(void) const189 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; }
getDeviceExtensions(void) const190 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; }
191
getUniversalQueueFamilyIndex(void) const192 deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; }
193 VkQueue getUniversalQueue (void) const;
194
195 private:
196 static VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures);
197 static vector<string> filterDefaultDeviceExtensions (const vector<VkExtensionProperties>& deviceExtensions);
198
199 const Unique<VkInstance> m_instance;
200 const InstanceDriver m_instanceInterface;
201
202 const VkPhysicalDevice m_physicalDevice;
203
204 const deUint32 m_universalQueueFamilyIndex;
205 const VkPhysicalDeviceFeatures m_deviceFeatures;
206 const VkPhysicalDeviceProperties m_deviceProperties;
207 const vector<string> m_deviceExtensions;
208
209 const Unique<VkDevice> m_device;
210 const DeviceDriver m_deviceInterface;
211 };
212
DefaultDevice(const PlatformInterface & vkPlatform,const tcu::CommandLine & cmdLine)213 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
214 : m_instance (createInstance(vkPlatform, cmdLine))
215 , m_instanceInterface (vkPlatform, *m_instance)
216 , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
217 , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
218 , m_deviceFeatures (filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(m_instanceInterface, m_physicalDevice)))
219 , m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice))
220 , m_deviceExtensions (filterDefaultDeviceExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)))
221 , m_device (createDefaultDevice(m_instanceInterface, m_physicalDevice, m_universalQueueFamilyIndex, m_deviceFeatures, m_deviceExtensions, cmdLine))
222 , m_deviceInterface (m_instanceInterface, *m_device)
223 {
224 }
225
~DefaultDevice(void)226 DefaultDevice::~DefaultDevice (void)
227 {
228 }
229
getUniversalQueue(void) const230 VkQueue DefaultDevice::getUniversalQueue (void) const
231 {
232 VkQueue queue = 0;
233 m_deviceInterface.getDeviceQueue(*m_device, m_universalQueueFamilyIndex, 0, &queue);
234 return queue;
235 }
236
filterDefaultDeviceFeatures(const VkPhysicalDeviceFeatures & deviceFeatures)237 VkPhysicalDeviceFeatures DefaultDevice::filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures)
238 {
239 VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures;
240
241 // Disable robustness by default, as it has an impact on performance on some HW.
242 enabledDeviceFeatures.robustBufferAccess = false;
243
244 return enabledDeviceFeatures;
245 }
246
filterDefaultDeviceExtensions(const vector<VkExtensionProperties> & deviceExtensions)247 vector<string> DefaultDevice::filterDefaultDeviceExtensions (const vector<VkExtensionProperties>& deviceExtensions)
248 {
249 vector<string> enabledExtensions;
250
251 // The only extension we enable always (when supported) is
252 // VK_KHR_sampler_mirror_clamp_to_edge that is defined in
253 // the core spec and supported widely.
254 const char* const mirrorClampToEdgeExt = "VK_KHR_sampler_mirror_clamp_to_edge";
255 if (vk::isExtensionSupported(deviceExtensions, vk::RequiredExtension(mirrorClampToEdgeExt)))
256 enabledExtensions.push_back(mirrorClampToEdgeExt);
257
258 return enabledExtensions;
259 }
260
261 // Allocator utilities
262
createAllocator(DefaultDevice * device)263 vk::Allocator* createAllocator (DefaultDevice* device)
264 {
265 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
266
267 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
268 return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
269 }
270
271 // Context
272
Context(tcu::TestContext & testCtx,const vk::PlatformInterface & platformInterface,vk::ProgramCollection<vk::ProgramBinary> & progCollection)273 Context::Context (tcu::TestContext& testCtx,
274 const vk::PlatformInterface& platformInterface,
275 vk::ProgramCollection<vk::ProgramBinary>& progCollection)
276 : m_testCtx (testCtx)
277 , m_platformInterface (platformInterface)
278 , m_progCollection (progCollection)
279 , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
280 , m_allocator (createAllocator(m_device.get()))
281 {
282 }
283
~Context(void)284 Context::~Context (void)
285 {
286 }
287
getInstance(void) const288 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); }
getInstanceInterface(void) const289 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); }
getPhysicalDevice(void) const290 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); }
getDeviceFeatures(void) const291 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); }
getDeviceProperties(void) const292 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); }
getDeviceExtensions(void) const293 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); }
getDevice(void) const294 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); }
getDeviceInterface(void) const295 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); }
getUniversalQueueFamilyIndex(void) const296 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); }
getUniversalQueue(void) const297 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); }
getDefaultAllocator(void) const298 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; }
299
300 // TestCase
301
initPrograms(SourceCollections &) const302 void TestCase::initPrograms (SourceCollections&) const
303 {
304 }
305
306 } // vkt
307