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