Add tests for the VK_KHR_8bit_storage extension
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmUtils.cpp
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
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
51 VkPhysicalDevice8BitStorageFeaturesKHR  querySupported8BitStorageFeatures (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
52 {
53         VkPhysicalDevice8BitStorageFeaturesKHR  extensionFeatures       =
54         {
55                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,    // VkStructureType      sType;
56                 DE_NULL,                                                                                                                // void*                        pNext;
57                 false,                                                                                                                  // VkBool32                     storageBuffer8BitAccess;
58                 false,                                                                                                                  // VkBool32                     uniformAndStorageBuffer8BitAccess;
59                 false,                                                                                                                  // VkBool32                     storagePushConstant8;
60         };
61         VkPhysicalDeviceFeatures2                       features;
62
63         deMemset(&features, 0, sizeof(features));
64         features.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
65         features.pNext  = &extensionFeatures;
66
67         // Call the getter only if supported. Otherwise above "zero" defaults are used
68         if(isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
69         {
70                 vki.getPhysicalDeviceFeatures2(device, &features);
71         }
72
73         return extensionFeatures;
74 }
75
76 VkPhysicalDevice16BitStorageFeatures    querySupported16BitStorageFeatures (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
77 {
78         VkPhysicalDevice16BitStorageFeatures    extensionFeatures       =
79         {
80                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,   // sType
81                 DE_NULL,                                                                                                                // pNext
82                 false,                                                                                                                  // storageUniformBufferBlock16
83                 false,                                                                                                                  // storageUniform16
84                 false,                                                                                                                  // storagePushConstant16
85                 false,                                                                                                                  // storageInputOutput16
86         };
87         VkPhysicalDeviceFeatures2                       features;
88
89         deMemset(&features, 0, sizeof(features));
90         features.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
91         features.pNext  = &extensionFeatures;
92
93         // Call the getter only if supported. Otherwise above "zero" defaults are used
94         if(isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
95         {
96                 vki.getPhysicalDeviceFeatures2(device, &features);
97         }
98
99         return extensionFeatures;
100 }
101
102 VkPhysicalDeviceVariablePointerFeatures querySupportedVariablePointersFeatures (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
103 {
104         VkPhysicalDeviceVariablePointerFeatures extensionFeatures       =
105         {
106                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR,        // sType
107                 DE_NULL,                                                                                                                        // pNext
108                 false,                                                                                                                          // variablePointersStorageBuffer
109                 false,                                                                                                                          // variablePointers
110         };
111
112         VkPhysicalDeviceFeatures2       features;
113         deMemset(&features, 0, sizeof(features));
114         features.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
115         features.pNext  = &extensionFeatures;
116
117         // Call the getter only if supported. Otherwise above "zero" defaults are used
118         if(isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
119         {
120                 vki.getPhysicalDeviceFeatures2(device, &features);
121         }
122
123         return extensionFeatures;
124 }
125
126 } // anonymous
127
128 bool is8BitStorageFeaturesSupported (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, Extension8BitStorageFeatures toCheck)
129 {
130         VkPhysicalDevice8BitStorageFeaturesKHR extensionFeatures        = querySupported8BitStorageFeatures(apiVersion, vki, device, instanceExtensions);
131
132         if ((toCheck & EXT8BITSTORAGEFEATURES_STORAGE_BUFFER) != 0 && extensionFeatures.storageBuffer8BitAccess == VK_FALSE)
133                 TCU_FAIL("storageBuffer8BitAccess has to be supported");
134
135         if ((toCheck & EXT8BITSTORAGEFEATURES_UNIFORM_STORAGE_BUFFER) != 0 && extensionFeatures.uniformAndStorageBuffer8BitAccess == VK_FALSE)
136                 return false;
137
138         if ((toCheck & EXT8BITSTORAGEFEATURES_PUSH_CONSTANT) != 0 && extensionFeatures.storagePushConstant8 == VK_FALSE)
139                 return false;
140
141         return true;
142 }
143
144 bool is16BitStorageFeaturesSupported (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, Extension16BitStorageFeatures toCheck)
145 {
146         VkPhysicalDevice16BitStorageFeatures extensionFeatures  = querySupported16BitStorageFeatures(apiVersion, vki, device, instanceExtensions);
147
148         if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK) != 0 && extensionFeatures.storageBuffer16BitAccess == VK_FALSE)
149                 return false;
150
151         if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM) != 0 && extensionFeatures.uniformAndStorageBuffer16BitAccess == VK_FALSE)
152                 return false;
153
154         if ((toCheck & EXT16BITSTORAGEFEATURES_PUSH_CONSTANT) != 0 && extensionFeatures.storagePushConstant16 == VK_FALSE)
155                 return false;
156
157         if ((toCheck & EXT16BITSTORAGEFEATURES_INPUT_OUTPUT) != 0 && extensionFeatures.storageInputOutput16 == VK_FALSE)
158                 return false;
159
160         return true;
161 }
162
163 bool isVariablePointersFeaturesSupported (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, ExtensionVariablePointersFeatures toCheck)
164 {
165         VkPhysicalDeviceVariablePointerFeatures extensionFeatures = querySupportedVariablePointersFeatures(apiVersion, vki, device, instanceExtensions);
166
167         if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER) != 0 && extensionFeatures.variablePointersStorageBuffer == VK_FALSE)
168                 return false;
169
170         if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS) != 0 && extensionFeatures.variablePointers == VK_FALSE)
171                 return false;
172
173         return true;
174 }
175
176 Move<VkDevice> createDeviceWithExtensions (Context&                                                     context,
177                                                                                    const deUint32                                       queueFamilyIndex,
178                                                                                    const std::vector<std::string>&      supportedExtensions,
179                                                                                    const std::vector<std::string>&      requiredExtensions)
180 {
181         const InstanceInterface&                                        vki                                                     = context.getInstanceInterface();
182         const VkPhysicalDevice                                          physicalDevice                          = context.getPhysicalDevice();
183         std::vector<const char*>                                        extensions;
184         void*                                                                           pExtension                                      = DE_NULL;
185         const VkPhysicalDeviceFeatures                          deviceFeatures                          = getPhysicalDeviceFeatures(vki, physicalDevice);
186         VkPhysicalDevice16BitStorageFeatures            ext16BitStorageFeatures;
187         VkPhysicalDeviceVariablePointerFeatures         extVariablePointerFeatures;
188
189         for (deUint32 extNdx = 0; extNdx < requiredExtensions.size(); ++extNdx)
190         {
191                 const std::string&      ext = requiredExtensions[extNdx];
192
193                 // Check that all required extensions are supported first.
194                 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), supportedExtensions, ext))
195                 {
196                         TCU_THROW(NotSupportedError, (std::string("Device extension not supported: ") + ext).c_str());
197                 }
198
199                 // Currently don't support enabling multiple extensions at the same time.
200                 if (ext == "VK_KHR_16bit_storage")
201                 {
202                         // For the 16bit storage extension, we have four features to test. Requesting all features supported.
203                         // Note that we don't throw NotImplemented errors here if a specific feature is not supported;
204                         // that should be done when actually trying to use that specific feature.
205                         ext16BitStorageFeatures = querySupported16BitStorageFeatures(context.getUsedApiVersion(), vki, physicalDevice, context.getInstanceExtensions());
206                         pExtension = &ext16BitStorageFeatures;
207                 }
208                 else if (ext == "VK_KHR_variable_pointers")
209                 {
210                         // For the VariablePointers extension, we have two features to test. Requesting all features supported.
211                         extVariablePointerFeatures      = querySupportedVariablePointersFeatures(context.getUsedApiVersion(), vki, physicalDevice, context.getInstanceExtensions());
212                         pExtension = &extVariablePointerFeatures;
213                 }
214
215                 if (!isCoreDeviceExtension(context.getUsedApiVersion(), ext))
216                         extensions.push_back(ext.c_str());
217         }
218
219         const float                                             queuePriorities[]       = { 1.0f };
220         const VkDeviceQueueCreateInfo   queueInfos[]            =
221         {
222                 {
223                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
224                         DE_NULL,
225                         (VkDeviceQueueCreateFlags)0,
226                         queueFamilyIndex,
227                         DE_LENGTH_OF_ARRAY(queuePriorities),
228                         &queuePriorities[0]
229                 }
230         };
231         const VkPhysicalDeviceFeatures  features                        = filterDefaultDeviceFeatures(deviceFeatures);
232         const VkDeviceCreateInfo                deviceParams            =
233         {
234                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
235                 pExtension,
236                 (VkDeviceCreateFlags)0,
237                 DE_LENGTH_OF_ARRAY(queueInfos),
238                 &queueInfos[0],
239                 0u,
240                 DE_NULL,
241                 (deUint32)extensions.size(),
242                 extensions.empty() ? DE_NULL : &extensions[0],
243                 &features
244         };
245
246         return vk::createDevice(vki, physicalDevice, &deviceParams);
247 }
248
249 Allocator* createAllocator (const InstanceInterface& instanceInterface, const VkPhysicalDevice physicalDevice, const DeviceInterface& deviceInterface, const VkDevice device)
250 {
251         const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instanceInterface, physicalDevice);
252
253         // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
254         return new SimpleAllocator(deviceInterface, device, memoryProperties);
255 }
256
257 deUint32 getMinRequiredVulkanVersion (const SpirvVersion version)
258 {
259         switch(version)
260         {
261         case SPIRV_VERSION_1_0:
262                 return VK_API_VERSION_1_0;
263         case SPIRV_VERSION_1_1:
264         case SPIRV_VERSION_1_2:
265         case SPIRV_VERSION_1_3:
266                 return VK_API_VERSION_1_1;
267         default:
268                 DE_ASSERT(0);
269         }
270         return 0u;
271 }
272
273 std::string     getVulkanName (const deUint32 version)
274 {
275         return std::string(version == VK_API_VERSION_1_1 ? "1.1" : "1.0");
276 }
277
278 } // SpirVAssembly
279 } // vkt