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 #include "vkPlatform.hpp"
31
32 #include <limits>
33
34 namespace vkt
35 {
36 namespace SpirVAssembly
37 {
38
39 using namespace vk;
40
toString() const41 std::string VariableLocation::toString() const
42 {
43 return "set_" + de::toString(set) + "_binding_" + de::toString(binding);
44 }
45
toDescription() const46 std::string VariableLocation::toDescription() const
47 {
48 return "Set " + de::toString(set) + " and Binding " + de::toString(binding);
49 }
50
51 #define IS_CORE_FEATURE_AVAILABLE(CHECKED, AVAILABLE, FEATURE) \
52 if ((CHECKED.FEATURE != DE_FALSE) && (AVAILABLE.FEATURE == DE_FALSE)) { *missingFeature = #FEATURE; return false; }
53
isCoreFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceFeatures & toCheck,const char ** missingFeature)54 bool isCoreFeaturesSupported (const Context& context,
55 const vk::VkPhysicalDeviceFeatures& toCheck,
56 const char** missingFeature)
57 {
58 const VkPhysicalDeviceFeatures& availableFeatures = context.getDeviceFeatures();
59
60 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, robustBufferAccess)
61 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, fullDrawIndexUint32)
62 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, imageCubeArray)
63 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, independentBlend)
64 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, geometryShader)
65 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, tessellationShader)
66 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sampleRateShading)
67 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, dualSrcBlend)
68 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, logicOp)
69 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, multiDrawIndirect)
70 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, drawIndirectFirstInstance)
71 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, depthClamp)
72 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, depthBiasClamp)
73 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, fillModeNonSolid)
74 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, depthBounds)
75 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, wideLines)
76 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, largePoints)
77 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, alphaToOne)
78 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, multiViewport)
79 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, samplerAnisotropy)
80 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, textureCompressionETC2)
81 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, textureCompressionASTC_LDR)
82 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, textureCompressionBC)
83 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, occlusionQueryPrecise)
84 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, pipelineStatisticsQuery)
85 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, vertexPipelineStoresAndAtomics)
86 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, fragmentStoresAndAtomics)
87 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderTessellationAndGeometryPointSize)
88 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderImageGatherExtended)
89 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageImageExtendedFormats)
90 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageImageMultisample)
91 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageImageReadWithoutFormat)
92 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageImageWriteWithoutFormat)
93 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderUniformBufferArrayDynamicIndexing)
94 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderSampledImageArrayDynamicIndexing)
95 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageBufferArrayDynamicIndexing)
96 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderStorageImageArrayDynamicIndexing)
97 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderClipDistance)
98 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderCullDistance)
99 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderFloat64)
100 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderInt64)
101 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderInt16)
102 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderResourceResidency)
103 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, shaderResourceMinLod)
104 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseBinding)
105 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidencyBuffer)
106 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidencyImage2D)
107 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidencyImage3D)
108 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidency2Samples)
109 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidency4Samples)
110 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidency8Samples)
111 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidency16Samples)
112 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, sparseResidencyAliased)
113 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, variableMultisampleRate)
114 IS_CORE_FEATURE_AVAILABLE(toCheck, availableFeatures, inheritedQueries)
115
116 return true;
117 }
118
119 #define IS_AVAIL(EXT_NAME, FEATURE) \
120 if (toCheck.FEATURE && !extensionFeatures.FEATURE) { *missingFeature = EXT_NAME #FEATURE; return false; }
121
isFloat16Int8FeaturesSupported(const Context & context,const vk::VkPhysicalDeviceShaderFloat16Int8Features & toCheck,const char ** missingFeature)122 bool isFloat16Int8FeaturesSupported(const Context& context, const vk::VkPhysicalDeviceShaderFloat16Int8Features& toCheck, const char **missingFeature)
123 {
124 const VkPhysicalDeviceShaderFloat16Int8Features& extensionFeatures = context.getShaderFloat16Int8Features();
125
126 IS_AVAIL("ShaderFloat16Int8.", shaderFloat16);
127 IS_AVAIL("ShaderFloat16Int8.", shaderInt8);
128
129 return true;
130 }
131
is8BitStorageFeaturesSupported(const Context & context,const vk::VkPhysicalDevice8BitStorageFeatures & toCheck,const char ** missingFeature)132 bool is8BitStorageFeaturesSupported(const Context& context, const vk::VkPhysicalDevice8BitStorageFeatures& toCheck, const char **missingFeature)
133 {
134 const VkPhysicalDevice8BitStorageFeaturesKHR& extensionFeatures = context.get8BitStorageFeatures();
135
136 IS_AVAIL("8BitStorage.", storageBuffer8BitAccess);
137 IS_AVAIL("8BitStorage.", uniformAndStorageBuffer8BitAccess);
138 IS_AVAIL("8BitStorage.", storagePushConstant8);
139
140 return true;
141 }
142
is16BitStorageFeaturesSupported(const Context & context,const vk::VkPhysicalDevice16BitStorageFeatures & toCheck,const char ** missingFeature)143 bool is16BitStorageFeaturesSupported(const Context& context, const vk::VkPhysicalDevice16BitStorageFeatures& toCheck, const char **missingFeature)
144 {
145 const VkPhysicalDevice16BitStorageFeatures& extensionFeatures = context.get16BitStorageFeatures();
146
147 IS_AVAIL("16BitStorage.", storageBuffer16BitAccess);
148 IS_AVAIL("16BitStorage.", uniformAndStorageBuffer16BitAccess);
149 IS_AVAIL("16BitStorage.", storagePushConstant16);
150 IS_AVAIL("16BitStorage.", storageInputOutput16);
151
152 return true;
153 }
154
isVariablePointersFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceVariablePointersFeatures & toCheck,const char ** missingFeature)155 bool isVariablePointersFeaturesSupported(const Context& context, const vk::VkPhysicalDeviceVariablePointersFeatures& toCheck, const char **missingFeature)
156 {
157 const VkPhysicalDeviceVariablePointersFeatures& extensionFeatures = context.getVariablePointersFeatures();
158
159 IS_AVAIL("VariablePointers.", variablePointersStorageBuffer);
160 IS_AVAIL("VariablePointers.", variablePointers);
161
162 return true;
163 }
164
isVulkanMemoryModelFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceVulkanMemoryModelFeatures & toCheck,const char ** missingFeature)165 bool isVulkanMemoryModelFeaturesSupported(const Context& context, const vk::VkPhysicalDeviceVulkanMemoryModelFeatures& toCheck, const char **missingFeature)
166 {
167 const VkPhysicalDeviceVulkanMemoryModelFeaturesKHR& extensionFeatures = context.getVulkanMemoryModelFeatures();
168
169 IS_AVAIL("VulkanMemoryModel.", vulkanMemoryModel);
170 IS_AVAIL("VulkanMemoryModel.", vulkanMemoryModelDeviceScope);
171 IS_AVAIL("VulkanMemoryModel.", vulkanMemoryModelAvailabilityVisibilityChains);
172
173 return true;
174 }
175
isIntegerDotProductFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR & toCheck,const char ** missingFeature)176 bool isIntegerDotProductFeaturesSupported(const Context& context, const vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR& toCheck, const char **missingFeature)
177 {
178 const VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR& extensionFeatures = context.getShaderIntegerDotProductFeatures();
179
180 IS_AVAIL("ShaderIntegerDotProduct.", shaderIntegerDotProduct);
181
182 return true;
183 }
184
185 #undef IS_AVAIL
186
isFloatControlsFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceFloatControlsProperties & toCheck,const char ** missingFeature)187 bool isFloatControlsFeaturesSupported (const Context& context, const vk::VkPhysicalDeviceFloatControlsProperties& toCheck, const char **missingFeature)
188 {
189 // if all flags are set to false then no float control features are actualy requested by the test
190 if ((toCheck.shaderSignedZeroInfNanPreserveFloat16 ||
191 toCheck.shaderSignedZeroInfNanPreserveFloat32 ||
192 toCheck.shaderSignedZeroInfNanPreserveFloat64 ||
193 toCheck.shaderDenormPreserveFloat16 ||
194 toCheck.shaderDenormPreserveFloat32 ||
195 toCheck.shaderDenormPreserveFloat64 ||
196 toCheck.shaderDenormFlushToZeroFloat16 ||
197 toCheck.shaderDenormFlushToZeroFloat32 ||
198 toCheck.shaderDenormFlushToZeroFloat64 ||
199 toCheck.shaderRoundingModeRTEFloat16 ||
200 toCheck.shaderRoundingModeRTEFloat32 ||
201 toCheck.shaderRoundingModeRTEFloat64 ||
202 toCheck.shaderRoundingModeRTZFloat16 ||
203 toCheck.shaderRoundingModeRTZFloat32 ||
204 toCheck.shaderRoundingModeRTZFloat64) == false)
205 return true;
206
207 *missingFeature = "Float controls properties";
208
209 // return false when float control features are requested and proper extension is not supported
210 if (!context.isDeviceFunctionalitySupported("VK_KHR_shader_float_controls"))
211 return false;
212
213 // perform query to get supported float control properties
214 vk::VkPhysicalDeviceFloatControlsProperties refControls;
215 {
216 refControls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR;
217 refControls.pNext = DE_NULL;
218
219 VkPhysicalDeviceProperties2 deviceProperties;
220 deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
221 deviceProperties.pNext = &refControls;
222
223 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
224 const vk::InstanceInterface& instanceInterface = context.getInstanceInterface();
225
226 instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
227 }
228
229 using FCIndependence = VkShaderFloatControlsIndependence;
230 FCIndependence fcInd32 = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR;
231 FCIndependence fcIndAll = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR;
232 FCIndependence fcIndNone = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR;
233
234 bool requiredDenormBehaviorNotSupported =
235 ((toCheck.denormBehaviorIndependence == fcIndAll) && (refControls.denormBehaviorIndependence != fcIndAll)) ||
236 ((toCheck.denormBehaviorIndependence == fcInd32) && (refControls.denormBehaviorIndependence == fcIndNone));
237
238 bool requiredRoundingModeNotSupported =
239 ((toCheck.roundingModeIndependence == fcIndAll) && (refControls.roundingModeIndependence != fcIndAll)) ||
240 ((toCheck.roundingModeIndependence == fcInd32) && (refControls.roundingModeIndependence == fcIndNone));
241
242 // check if flags needed by the test are not supported by the device
243 bool requiredFeaturesNotSupported =
244 requiredDenormBehaviorNotSupported ||
245 requiredRoundingModeNotSupported ||
246 (toCheck.shaderDenormFlushToZeroFloat16 && !refControls.shaderDenormFlushToZeroFloat16) ||
247 (toCheck.shaderDenormPreserveFloat16 && !refControls.shaderDenormPreserveFloat16) ||
248 (toCheck.shaderRoundingModeRTEFloat16 && !refControls.shaderRoundingModeRTEFloat16) ||
249 (toCheck.shaderRoundingModeRTZFloat16 && !refControls.shaderRoundingModeRTZFloat16) ||
250 (toCheck.shaderSignedZeroInfNanPreserveFloat16 && !refControls.shaderSignedZeroInfNanPreserveFloat16) ||
251 (toCheck.shaderDenormFlushToZeroFloat32 && !refControls.shaderDenormFlushToZeroFloat32) ||
252 (toCheck.shaderDenormPreserveFloat32 && !refControls.shaderDenormPreserveFloat32) ||
253 (toCheck.shaderRoundingModeRTEFloat32 && !refControls.shaderRoundingModeRTEFloat32) ||
254 (toCheck.shaderRoundingModeRTZFloat32 && !refControls.shaderRoundingModeRTZFloat32) ||
255 (toCheck.shaderSignedZeroInfNanPreserveFloat32 && !refControls.shaderSignedZeroInfNanPreserveFloat32) ||
256 (toCheck.shaderDenormFlushToZeroFloat64 && !refControls.shaderDenormFlushToZeroFloat64) ||
257 (toCheck.shaderDenormPreserveFloat64 && !refControls.shaderDenormPreserveFloat64) ||
258 (toCheck.shaderRoundingModeRTEFloat64 && !refControls.shaderRoundingModeRTEFloat64) ||
259 (toCheck.shaderRoundingModeRTZFloat64 && !refControls.shaderRoundingModeRTZFloat64) ||
260 (toCheck.shaderSignedZeroInfNanPreserveFloat64 && !refControls.shaderSignedZeroInfNanPreserveFloat64);
261
262 // we checked if required features are not supported - we need to
263 // negate the result to know if all required features are available
264 return !requiredFeaturesNotSupported;
265 }
266
isVulkanFeaturesSupported(const Context & context,const VulkanFeatures & requested,const char ** missingFeature)267 bool isVulkanFeaturesSupported(const Context& context, const VulkanFeatures& requested, const char **missingFeature)
268 {
269 if (!isCoreFeaturesSupported(context, requested.coreFeatures, missingFeature))
270 return false;
271
272 if (!is8BitStorageFeaturesSupported(context, requested.ext8BitStorage, missingFeature))
273 return false;
274
275 if (!is16BitStorageFeaturesSupported(context, requested.ext16BitStorage, missingFeature))
276 return false;
277
278 if (!isVariablePointersFeaturesSupported(context, requested.extVariablePointers, missingFeature))
279 return false;
280
281 if (!isFloat16Int8FeaturesSupported(context, requested.extFloat16Int8, missingFeature))
282 return false;
283
284 if (!isVulkanMemoryModelFeaturesSupported(context, requested.extVulkanMemoryModel, missingFeature))
285 return false;
286
287 if (!isFloatControlsFeaturesSupported(context, requested.floatControlsProperties, missingFeature))
288 return false;
289
290 if (!isIntegerDotProductFeaturesSupported(context, requested.extIntegerDotProduct, missingFeature))
291 return false;
292
293 return true;
294 }
295
getMinRequiredVulkanVersion(const SpirvVersion version)296 deUint32 getMinRequiredVulkanVersion (const SpirvVersion version)
297 {
298 switch(version)
299 {
300 case SPIRV_VERSION_1_0:
301 return VK_API_VERSION_1_0;
302 case SPIRV_VERSION_1_1:
303 case SPIRV_VERSION_1_2:
304 case SPIRV_VERSION_1_3:
305 case SPIRV_VERSION_1_4:
306 return VK_API_VERSION_1_1;
307 case SPIRV_VERSION_1_5:
308 return VK_API_VERSION_1_2;
309 case SPIRV_VERSION_1_6:
310 return VK_API_VERSION_1_3;
311 default:
312 DE_ASSERT(0);
313 }
314 return 0u;
315 }
316
getVulkanName(const deUint32 version)317 std::string getVulkanName (const deUint32 version)
318 {
319 if (version == VK_API_VERSION_1_1) return "1.1";
320 if (version == VK_API_VERSION_1_2) return "1.2";
321 if (version == VK_API_VERSION_1_3) return "1.3";
322
323 return "1.0";
324 }
325
326 // Generate and return 64-bit integers.
327 //
328 // Expected count to be at least 16.
getInt64s(de::Random & rnd,const deUint32 count)329 std::vector<deInt64> getInt64s (de::Random& rnd, const deUint32 count)
330 {
331 std::vector<deInt64> data;
332
333 data.reserve(count);
334
335 // Make sure we have boundary numbers.
336 data.push_back(deInt64(0x0000000000000000)); // 0
337 data.push_back(deInt64(0x0000000000000001)); // 1
338 data.push_back(deInt64(0x000000000000002a)); // 42
339 data.push_back(deInt64(0x000000007fffffff)); // 2147483647
340 data.push_back(deInt64(0x0000000080000000)); // 2147483648
341 data.push_back(deInt64(0x00000000ffffffff)); // 4294967295
342 data.push_back(deInt64(0x0000000100000000)); // 4294967296
343 data.push_back(deInt64(0x7fffffffffffffff)); // 9223372036854775807
344 data.push_back(deInt64(0x8000000000000000)); // -9223372036854775808
345 data.push_back(deInt64(0x8000000000000001)); // -9223372036854775807
346 data.push_back(deInt64(0xffffffff00000000)); // -4294967296
347 data.push_back(deInt64(0xffffffff00000001)); // -4294967295
348 data.push_back(deInt64(0xffffffff80000000)); // -2147483648
349 data.push_back(deInt64(0xffffffff80000001)); // -2147483647
350 data.push_back(deInt64(0xffffffffffffffd6)); // -42
351 data.push_back(deInt64(0xffffffffffffffff)); // -1
352
353 DE_ASSERT(count >= data.size());
354
355 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
356 data.push_back(static_cast<deInt64>(rnd.getUint64()));
357
358 return data;
359 }
360
361 // Generate and return 32-bit integers.
362 //
363 // Expected count to be at least 16.
getInt32s(de::Random & rnd,const deUint32 count)364 std::vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count)
365 {
366 std::vector<deInt32> data;
367
368 data.reserve(count);
369
370 // Make sure we have boundary numbers.
371 data.push_back(deInt32(0x00000000)); // 0
372 data.push_back(deInt32(0x00000001)); // 1
373 data.push_back(deInt32(0x0000002a)); // 42
374 data.push_back(deInt32(0x00007fff)); // 32767
375 data.push_back(deInt32(0x00008000)); // 32768
376 data.push_back(deInt32(0x0000ffff)); // 65535
377 data.push_back(deInt32(0x00010000)); // 65536
378 data.push_back(deInt32(0x7fffffff)); // 2147483647
379 data.push_back(deInt32(0x80000000)); // -2147483648
380 data.push_back(deInt32(0x80000001)); // -2147483647
381 data.push_back(deInt32(0xffff0000)); // -65536
382 data.push_back(deInt32(0xffff0001)); // -65535
383 data.push_back(deInt32(0xffff8000)); // -32768
384 data.push_back(deInt32(0xffff8001)); // -32767
385 data.push_back(deInt32(0xffffffd6)); // -42
386 data.push_back(deInt32(0xffffffff)); // -1
387
388 DE_ASSERT(count >= data.size());
389
390 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
391 data.push_back(static_cast<deInt32>(rnd.getUint32()));
392
393 return data;
394 }
395
396 // Generate and return 16-bit integers.
397 //
398 // Expected count to be at least 8.
getInt16s(de::Random & rnd,const deUint32 count)399 std::vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count)
400 {
401 std::vector<deInt16> data;
402
403 data.reserve(count);
404
405 // Make sure we have boundary numbers.
406 data.push_back(deInt16(0x0000)); // 0
407 data.push_back(deInt16(0x0001)); // 1
408 data.push_back(deInt16(0x002a)); // 42
409 data.push_back(deInt16(0x7fff)); // 32767
410 data.push_back(deInt16(0x8000)); // -32868
411 data.push_back(deInt16(0x8001)); // -32767
412 data.push_back(deInt16(0xffd6)); // -42
413 data.push_back(deInt16(0xffff)); // -1
414
415 DE_ASSERT(count >= data.size());
416
417 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
418 data.push_back(static_cast<deInt16>(rnd.getUint16()));
419
420 return data;
421 }
422
423 // Generate and return 8-bit integers.
424 //
425 // Expected count to be at least 8.
getInt8s(de::Random & rnd,const deUint32 count)426 std::vector<deInt8> getInt8s (de::Random& rnd, const deUint32 count)
427 {
428 std::vector<deInt8> data;
429
430 data.reserve(count);
431
432 // Make sure we have boundary numbers.
433 data.push_back(deInt8(0x00)); // 0
434 data.push_back(deInt8(0x01)); // 1
435 data.push_back(deInt8(0x2a)); // 42
436 data.push_back(deInt8(0x7f)); // 127
437 data.push_back(deInt8(0x80)); // -128
438 data.push_back(deInt8(0x81)); // -127
439 data.push_back(deInt8(0xd6)); // -42
440 data.push_back(deInt8(0xff)); // -1
441
442 DE_ASSERT(count >= data.size());
443
444 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
445 data.push_back(static_cast<deInt8>(rnd.getUint8()));
446
447 return data;
448 }
449
450 // IEEE-754 floating point numbers:
451 // +--------+------+----------+-------------+
452 // | binary | sign | exponent | significand |
453 // +--------+------+----------+-------------+
454 // | 64-bit | 1 | 11 | 52 |
455 // +--------+------+----------+-------------+
456 // | 32-bit | 1 | 8 | 23 |
457 // +--------+------+----------+-------------+
458 // | 16-bit | 1 | 5 | 10 |
459 // +--------+------+----------+-------------+
460 //
461 // 64-bit floats:
462 //
463 // (0x3FD2000000000000: 0.28125: with exact match in 16-bit normalized)
464 // (0x3F10060000000000: exact half way within two 16-bit normalized; round to zero: 0x0401)
465 // (0xBF10060000000000: exact half way within two 16-bit normalized; round to zero: 0x8402)
466 // (0x3F100C0000000000: not exact half way within two 16-bit normalized; round to zero: 0x0403)
467 // (0xBF100C0000000000: not exact half way within two 16-bit normalized; round to zero: 0x8404)
468
469 // Generate and return 64-bit floats
470 //
471 // The first 24 number pairs are manually picked, while the rest are randomly generated.
472 // Expected count to be at least 24 (numPicks).
getFloat64s(de::Random & rnd,deUint32 count)473 std::vector<double> getFloat64s (de::Random& rnd, deUint32 count)
474 {
475 std::vector<double> float64;
476
477 float64.reserve(count);
478
479 if (count >= 24)
480 {
481 // Zero
482 float64.push_back(0.f);
483 float64.push_back(-0.f);
484 // Infinity
485 float64.push_back(std::numeric_limits<double>::infinity());
486 float64.push_back(-std::numeric_limits<double>::infinity());
487 // SNaN
488 float64.push_back(std::numeric_limits<double>::signaling_NaN());
489 float64.push_back(-std::numeric_limits<double>::signaling_NaN());
490 // QNaN
491 float64.push_back(std::numeric_limits<double>::quiet_NaN());
492 float64.push_back(-std::numeric_limits<double>::quiet_NaN());
493
494 // Denormalized 64-bit float matching 0 in 16-bit
495 float64.push_back(ldexp((double)1.f, -1023));
496 float64.push_back(-ldexp((double)1.f, -1023));
497
498 // Normalized 64-bit float matching 0 in 16-bit
499 float64.push_back(ldexp((double)1.f, -100));
500 float64.push_back(-ldexp((double)1.f, -100));
501 // Normalized 64-bit float with exact denormalized match in 16-bit
502 float64.push_back(bitwiseCast<double>(deUint64(0x3B0357C299A88EA8)));
503 float64.push_back(bitwiseCast<double>(deUint64(0xBB0357C299A88EA8)));
504
505 // Normalized 64-bit float with exact normalized match in 16-bit
506 float64.push_back(ldexp((double)1.f, -14)); // 2e-14: minimum 16-bit positive normalized
507 float64.push_back(-ldexp((double)1.f, -14)); // 2e-14: maximum 16-bit negative normalized
508 // Normalized 64-bit float falling above half way within two 16-bit normalized
509 float64.push_back(bitwiseCast<double>(deUint64(0x3FD2000000000000)));
510 float64.push_back(bitwiseCast<double>(deUint64(0xBFD2000000000000)));
511 // Normalized 64-bit float falling exact half way within two 16-bit normalized
512 float64.push_back(bitwiseCast<double>(deUint64(0x3F100C0000000000)));
513 float64.push_back(bitwiseCast<double>(deUint64(0xBF100C0000000000)));
514 // Some number
515 float64.push_back((double)0.28125f);
516 float64.push_back((double)-0.28125f);
517 // Normalized 64-bit float matching infinity in 16-bit
518 float64.push_back(ldexp((double)1.f, 100));
519 float64.push_back(-ldexp((double)1.f, 100));
520 }
521
522 const deUint32 numPicks = static_cast<deUint32>(float64.size());
523
524 DE_ASSERT(count >= numPicks);
525 count -= numPicks;
526
527 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
528 {
529 double randValue = rnd.getDouble();
530 float64.push_back(randValue);
531 }
532
533 return float64;
534 }
535
536 // IEEE-754 floating point numbers:
537 // +--------+------+----------+-------------+
538 // | binary | sign | exponent | significand |
539 // +--------+------+----------+-------------+
540 // | 16-bit | 1 | 5 | 10 |
541 // +--------+------+----------+-------------+
542 // | 32-bit | 1 | 8 | 23 |
543 // +--------+------+----------+-------------+
544 //
545 // 16-bit floats:
546 //
547 // 0 000 00 00 0000 0001 (0x0001: 2e-24: minimum positive denormalized)
548 // 0 000 00 11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
549 // 0 000 01 00 0000 0000 (0x0400: 2e-14: minimum positive normalized)
550 //
551 // 32-bit floats:
552 //
553 // 0 011 1110 1 001 0000 0000 0000 0000 0000 (0x3e900000: 0.28125: with exact match in 16-bit normalized)
554 // 0 011 1000 1 000 0000 0011 0000 0000 0000 (0x38803000: exact half way within two 16-bit normalized; round to zero: 0x0401)
555 // 1 011 1000 1 000 0000 0011 0000 0000 0000 (0xb8803000: exact half way within two 16-bit normalized; round to zero: 0x8402)
556 // 0 011 1000 1 000 0000 1111 1111 0000 0000 (0x3880ff00: not exact half way within two 16-bit normalized; round to zero: 0x0403)
557 // 1 011 1000 1 000 0000 1111 1111 0000 0000 (0xb880ff00: not exact half way within two 16-bit normalized; round to zero: 0x8404)
558
559 // Generate and return 32-bit floats
560 //
561 // The first 24 number pairs are manually picked, while the rest are randomly generated.
562 // Expected count to be at least 24 (numPicks).
getFloat32s(de::Random & rnd,deUint32 count)563 std::vector<float> getFloat32s (de::Random& rnd, deUint32 count)
564 {
565 std::vector<float> float32;
566
567 float32.reserve(count);
568
569 // Zero
570 float32.push_back(0.f);
571 float32.push_back(-0.f);
572 // Infinity
573 float32.push_back(std::numeric_limits<float>::infinity());
574 float32.push_back(-std::numeric_limits<float>::infinity());
575 // SNaN
576 float32.push_back(std::numeric_limits<float>::signaling_NaN());
577 float32.push_back(-std::numeric_limits<float>::signaling_NaN());
578 // QNaN
579 float32.push_back(std::numeric_limits<float>::quiet_NaN());
580 float32.push_back(-std::numeric_limits<float>::quiet_NaN());
581
582 // Denormalized 32-bit float matching 0 in 16-bit
583 float32.push_back(deFloatLdExp(1.f, -127));
584 float32.push_back(-deFloatLdExp(1.f, -127));
585
586 // Normalized 32-bit float matching 0 in 16-bit
587 float32.push_back(deFloatLdExp(1.f, -100));
588 float32.push_back(-deFloatLdExp(1.f, -100));
589 // Normalized 32-bit float with exact denormalized match in 16-bit
590 float32.push_back(deFloatLdExp(1.f, -24)); // 2e-24: minimum 16-bit positive denormalized
591 float32.push_back(-deFloatLdExp(1.f, -24)); // 2e-24: maximum 16-bit negative denormalized
592 // Normalized 32-bit float with exact normalized match in 16-bit
593 float32.push_back(deFloatLdExp(1.f, -14)); // 2e-14: minimum 16-bit positive normalized
594 float32.push_back(-deFloatLdExp(1.f, -14)); // 2e-14: maximum 16-bit negative normalized
595 // Normalized 32-bit float falling above half way within two 16-bit normalized
596 float32.push_back(bitwiseCast<float>(deUint32(0x3880ff00)));
597 float32.push_back(bitwiseCast<float>(deUint32(0xb880ff00)));
598 // Normalized 32-bit float falling exact half way within two 16-bit normalized
599 float32.push_back(bitwiseCast<float>(deUint32(0x38803000)));
600 float32.push_back(bitwiseCast<float>(deUint32(0xb8803000)));
601 // Some number
602 float32.push_back(0.28125f);
603 float32.push_back(-0.28125f);
604 // Normalized 32-bit float matching infinity in 16-bit
605 float32.push_back(deFloatLdExp(1.f, 100));
606 float32.push_back(-deFloatLdExp(1.f, 100));
607
608 const deUint32 numPicks = static_cast<deUint32>(float32.size());
609
610 DE_ASSERT(count >= numPicks);
611 count -= numPicks;
612
613 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
614 float32.push_back(rnd.getFloat());
615
616 return float32;
617 }
618
619 // IEEE-754 floating point numbers:
620 // +--------+------+----------+-------------+
621 // | binary | sign | exponent | significand |
622 // +--------+------+----------+-------------+
623 // | 16-bit | 1 | 5 | 10 |
624 // +--------+------+----------+-------------+
625 // | 32-bit | 1 | 8 | 23 |
626 // +--------+------+----------+-------------+
627 //
628 // 16-bit floats:
629 //
630 // 0 000 00 00 0000 0001 (0x0001: 2e-24: minimum positive denormalized)
631 // 0 000 00 11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
632 // 0 000 01 00 0000 0000 (0x0400: 2e-14: minimum positive normalized)
633 //
634 // 0 000 00 00 0000 0000 (0x0000: +0)
635 // 0 111 11 00 0000 0000 (0x7c00: +Inf)
636 // 0 000 00 11 1111 0000 (0x03f0: +Denorm)
637 // 0 000 01 00 0000 0001 (0x0401: +Norm)
638 // 0 111 11 00 0000 1111 (0x7c0f: +SNaN)
639 // 0 111 11 00 1111 0000 (0x7c0f: +QNaN)
640
641 // Generate and return 16-bit floats and their corresponding 32-bit values.
642 //
643 // The first 14 number pairs are manually picked, while the rest are randomly generated.
644 // Expected count to be at least 14 (numPicks).
getFloat16s(de::Random & rnd,deUint32 count)645 std::vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count)
646 {
647 std::vector<deFloat16> float16;
648
649 float16.reserve(count);
650
651 // Zero
652 float16.push_back(deUint16(0x0000));
653 float16.push_back(deUint16(0x8000));
654 // Infinity
655 float16.push_back(deUint16(0x7c00));
656 float16.push_back(deUint16(0xfc00));
657 // SNaN
658 float16.push_back(deUint16(0x7c0f));
659 float16.push_back(deUint16(0xfc0f));
660 // QNaN
661 float16.push_back(deUint16(0x7cf0));
662 float16.push_back(deUint16(0xfcf0));
663
664 // Denormalized
665 float16.push_back(deUint16(0x03f0));
666 float16.push_back(deUint16(0x83f0));
667 // Normalized
668 float16.push_back(deUint16(0x0401));
669 float16.push_back(deUint16(0x8401));
670 // Some normal number
671 float16.push_back(deUint16(0x14cb));
672 float16.push_back(deUint16(0x94cb));
673
674 const deUint32 numPicks = static_cast<deUint32>(float16.size());
675
676 DE_ASSERT(count >= numPicks);
677 count -= numPicks;
678
679 for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
680 float16.push_back(rnd.getUint16());
681
682 return float16;
683 }
684
getOpCapabilityShader()685 std::string getOpCapabilityShader()
686 {
687 return "OpCapability Shader\n";
688 }
689
getUnusedEntryPoint()690 std::string getUnusedEntryPoint()
691 {
692 return "OpEntryPoint Vertex %unused_func \"unused_func\"\n";
693 }
694
getUnusedDecorations(const VariableLocation & location)695 std::string getUnusedDecorations(const VariableLocation& location)
696 {
697 return "OpMemberDecorate %UnusedBufferType 0 Offset 0\n"
698 "OpMemberDecorate %UnusedBufferType 1 Offset 4\n"
699 "OpDecorate %UnusedBufferType BufferBlock\n"
700 "OpDecorate %unused_buffer DescriptorSet " + de::toString(location.set) + "\n"
701 "OpDecorate %unused_buffer Binding " + de::toString(location.binding) + "\n";
702 }
703
getUnusedTypesAndConstants()704 std::string getUnusedTypesAndConstants()
705 {
706 return "%c_f32_101 = OpConstant %f32 101\n"
707 "%c_i32_201 = OpConstant %i32 201\n"
708 "%UnusedBufferType = OpTypeStruct %f32 %i32\n"
709 "%unused_ptr_Uniform_UnusedBufferType = OpTypePointer Uniform %UnusedBufferType\n"
710 "%unused_ptr_Uniform_float = OpTypePointer Uniform %f32\n"
711 "%unused_ptr_Uniform_int = OpTypePointer Uniform %i32\n";
712 }
713
getUnusedBuffer()714 std::string getUnusedBuffer()
715 {
716 return "%unused_buffer = OpVariable %unused_ptr_Uniform_UnusedBufferType Uniform\n";
717 }
718
getUnusedFunctionBody()719 std::string getUnusedFunctionBody()
720 {
721 return "%unused_func = OpFunction %void None %voidf\n"
722 "%unused_func_label = OpLabel\n"
723 "%unused_out_float_ptr = OpAccessChain %unused_ptr_Uniform_float %unused_buffer %c_i32_0\n"
724 "OpStore %unused_out_float_ptr %c_f32_101\n"
725 "%unused_out_int_ptr = OpAccessChain %unused_ptr_Uniform_int %unused_buffer %c_i32_1\n"
726 "OpStore %unused_out_int_ptr %c_i32_201\n"
727 "OpReturn\n"
728 "OpFunctionEnd\n";
729 }
730
731 } // SpirVAssembly
732 } // vkt
733