xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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