1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 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 Utilities for Vulkan SPIR-V assembly tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmUtils.hpp"
25
26 #include "deMemory.h"
27 #include "deSTLUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkRefUtil.hpp"
30
31 namespace vkt
32 {
33 namespace SpirVAssembly
34 {
35
36 using namespace vk;
37
38 namespace
39 {
40
filterDefaultDeviceFeatures(const VkPhysicalDeviceFeatures & deviceFeatures)41 VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures)
42 {
43 VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures;
44
45 // Disable robustness by default, as it has an impact on performance on some HW.
46 enabledDeviceFeatures.robustBufferAccess = false;
47
48 return enabledDeviceFeatures;
49 }
50
querySupported16BitStorageFeatures(const InstanceInterface & vki,VkPhysicalDevice device,const std::vector<std::string> & instanceExtensions)51 VkPhysicalDevice16BitStorageFeaturesKHR querySupported16BitStorageFeatures (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
52 {
53 VkPhysicalDevice16BitStorageFeaturesKHR extensionFeatures =
54 {
55 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR, // sType
56 DE_NULL, // pNext
57 false, // storageUniformBufferBlock16
58 false, // storageUniform16
59 false, // storagePushConstant16
60 false, // storageInputOutput16
61 };
62 VkPhysicalDeviceFeatures2KHR features;
63
64 deMemset(&features, 0, sizeof(features));
65 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
66 features.pNext = &extensionFeatures;
67
68 // Call the getter only if supported. Otherwise above "zero" defaults are used
69 if (de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2"))
70 {
71 vki.getPhysicalDeviceFeatures2KHR(device, &features);
72 }
73
74 return extensionFeatures;
75 }
76
querySupportedVariablePointersFeatures(const InstanceInterface & vki,VkPhysicalDevice device,const std::vector<std::string> & instanceExtensions)77 VkPhysicalDeviceVariablePointerFeaturesKHR querySupportedVariablePointersFeatures (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
78 {
79 VkPhysicalDeviceVariablePointerFeaturesKHR extensionFeatures =
80 {
81 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR, // sType
82 DE_NULL, // pNext
83 false, // variablePointersStorageBuffer
84 false, // variablePointers
85 };
86
87 VkPhysicalDeviceFeatures2KHR features;
88 deMemset(&features, 0, sizeof(features));
89 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
90 features.pNext = &extensionFeatures;
91
92 // Call the getter only if supported. Otherwise above "zero" defaults are used
93 if (de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2"))
94 {
95 vki.getPhysicalDeviceFeatures2KHR(device, &features);
96 }
97
98 return extensionFeatures;
99 }
100
101 } // anonymous
102
is16BitStorageFeaturesSupported(const InstanceInterface & vki,VkPhysicalDevice device,const std::vector<std::string> & instanceExtensions,Extension16BitStorageFeatures toCheck)103 bool is16BitStorageFeaturesSupported (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, Extension16BitStorageFeatures toCheck)
104 {
105 VkPhysicalDevice16BitStorageFeaturesKHR extensionFeatures = querySupported16BitStorageFeatures(vki, device, instanceExtensions);
106
107 if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK) != 0 && extensionFeatures.storageBuffer16BitAccess == VK_FALSE)
108 return false;
109
110 if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM) != 0 && extensionFeatures.uniformAndStorageBuffer16BitAccess == VK_FALSE)
111 return false;
112
113 if ((toCheck & EXT16BITSTORAGEFEATURES_PUSH_CONSTANT) != 0 && extensionFeatures.storagePushConstant16 == VK_FALSE)
114 return false;
115
116 if ((toCheck & EXT16BITSTORAGEFEATURES_INPUT_OUTPUT) != 0 && extensionFeatures.storageInputOutput16 == VK_FALSE)
117 return false;
118
119 return true;
120 }
121
isVariablePointersFeaturesSupported(const InstanceInterface & vki,VkPhysicalDevice device,const std::vector<std::string> & instanceExtensions,ExtensionVariablePointersFeatures toCheck)122 bool isVariablePointersFeaturesSupported (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, ExtensionVariablePointersFeatures toCheck)
123 {
124 VkPhysicalDeviceVariablePointerFeaturesKHR extensionFeatures = querySupportedVariablePointersFeatures(vki, device, instanceExtensions);
125
126 if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER) != 0 && extensionFeatures.variablePointersStorageBuffer == VK_FALSE)
127 return false;
128
129 if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS) != 0 && extensionFeatures.variablePointers == VK_FALSE)
130 return false;
131
132 return true;
133 }
134
createDeviceWithExtensions(Context & context,const deUint32 queueFamilyIndex,const std::vector<std::string> & supportedExtensions,const std::vector<std::string> & requiredExtensions)135 Move<VkDevice> createDeviceWithExtensions (Context& context,
136 const deUint32 queueFamilyIndex,
137 const std::vector<std::string>& supportedExtensions,
138 const std::vector<std::string>& requiredExtensions)
139 {
140 const InstanceInterface& vki = context.getInstanceInterface();
141 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
142 std::vector<const char*> extensions (requiredExtensions.size());
143 void* pExtension = DE_NULL;
144 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(vki, physicalDevice);
145 VkPhysicalDevice16BitStorageFeaturesKHR ext16BitStorageFeatures;
146 VkPhysicalDeviceVariablePointerFeaturesKHR extVariablePointerFeatures;
147
148 for (deUint32 extNdx = 0; extNdx < requiredExtensions.size(); ++extNdx)
149 {
150 const std::string& ext = requiredExtensions[extNdx];
151
152 // Check that all required extensions are supported first.
153 if (!de::contains(supportedExtensions.begin(), supportedExtensions.end(), ext))
154 {
155 TCU_THROW(NotSupportedError, (std::string("Device extension not supported: ") + ext).c_str());
156 }
157
158 // Currently don't support enabling multiple extensions at the same time.
159 if (ext == "VK_KHR_16bit_storage")
160 {
161 // For the 16bit storage extension, we have four features to test. Requesting all features supported.
162 // Note that we don't throw NotImplemented errors here if a specific feature is not supported;
163 // that should be done when actually trying to use that specific feature.
164 ext16BitStorageFeatures = querySupported16BitStorageFeatures(vki, physicalDevice, context.getInstanceExtensions());
165 pExtension = &ext16BitStorageFeatures;
166 }
167 else if (ext == "VK_KHR_variable_pointers")
168 {
169 // For the VariablePointers extension, we have two features to test. Requesting all features supported.
170 extVariablePointerFeatures = querySupportedVariablePointersFeatures(vki, physicalDevice, context.getInstanceExtensions());
171 pExtension = &extVariablePointerFeatures;
172 }
173
174 extensions[extNdx] = ext.c_str();
175 }
176
177 const float queuePriorities[] = { 1.0f };
178 const VkDeviceQueueCreateInfo queueInfos[] =
179 {
180 {
181 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
182 DE_NULL,
183 (VkDeviceQueueCreateFlags)0,
184 queueFamilyIndex,
185 DE_LENGTH_OF_ARRAY(queuePriorities),
186 &queuePriorities[0]
187 }
188 };
189 const VkPhysicalDeviceFeatures features = filterDefaultDeviceFeatures(deviceFeatures);
190 const VkDeviceCreateInfo deviceParams =
191 {
192 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
193 pExtension,
194 (VkDeviceCreateFlags)0,
195 DE_LENGTH_OF_ARRAY(queueInfos),
196 &queueInfos[0],
197 0u,
198 DE_NULL,
199 (deUint32)extensions.size(),
200 extensions.empty() ? DE_NULL : &extensions[0],
201 &features
202 };
203
204 return vk::createDevice(vki, physicalDevice, &deviceParams);
205 }
206
createAllocator(const InstanceInterface & instanceInterface,const VkPhysicalDevice physicalDevice,const DeviceInterface & deviceInterface,const VkDevice device)207 Allocator* createAllocator (const InstanceInterface& instanceInterface, const VkPhysicalDevice physicalDevice, const DeviceInterface& deviceInterface, const VkDevice device)
208 {
209 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instanceInterface, physicalDevice);
210
211 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
212 return new SimpleAllocator(deviceInterface, device, memoryProperties);
213 }
214
215 } // SpirVAssembly
216 } // vkt
217