• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 VkPhysicalDevice8BitStorageFeatures& 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 VkPhysicalDeviceVulkanMemoryModelFeatures& 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 
176 #ifndef CTS_USES_VULKANSC
isIntegerDotProductFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR & toCheck,const char ** missingFeature)177 bool isIntegerDotProductFeaturesSupported(const Context& context, const vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR& toCheck, const char **missingFeature)
178 {
179 	const VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR& extensionFeatures = context.getShaderIntegerDotProductFeatures();
180 
181 	IS_AVAIL("ShaderIntegerDotProduct.", shaderIntegerDotProduct);
182 
183 	return true;
184 }
185 #endif // CTS_USES_VULKANSC
186 
187 #undef IS_AVAIL
188 
isFloatControlsFeaturesSupported(const Context & context,const vk::VkPhysicalDeviceFloatControlsProperties & toCheck,const char ** missingFeature)189 bool isFloatControlsFeaturesSupported (const Context& context, const vk::VkPhysicalDeviceFloatControlsProperties& toCheck, const char **missingFeature)
190 {
191 	// if all flags are set to false then no float control features are actualy requested by the test
192 	if ((toCheck.shaderSignedZeroInfNanPreserveFloat16 ||
193 		 toCheck.shaderSignedZeroInfNanPreserveFloat32 ||
194 		 toCheck.shaderSignedZeroInfNanPreserveFloat64 ||
195 		 toCheck.shaderDenormPreserveFloat16 ||
196 		 toCheck.shaderDenormPreserveFloat32 ||
197 		 toCheck.shaderDenormPreserveFloat64 ||
198 		 toCheck.shaderDenormFlushToZeroFloat16 ||
199 		 toCheck.shaderDenormFlushToZeroFloat32 ||
200 		 toCheck.shaderDenormFlushToZeroFloat64 ||
201 		 toCheck.shaderRoundingModeRTEFloat16 ||
202 		 toCheck.shaderRoundingModeRTEFloat32 ||
203 		 toCheck.shaderRoundingModeRTEFloat64 ||
204 		 toCheck.shaderRoundingModeRTZFloat16 ||
205 		 toCheck.shaderRoundingModeRTZFloat32 ||
206 		 toCheck.shaderRoundingModeRTZFloat64) == false)
207 		return true;
208 
209 	*missingFeature = "Float controls properties";
210 
211 	// return false when float control features are requested and proper extension is not supported
212 	if (!context.isDeviceFunctionalitySupported("VK_KHR_shader_float_controls"))
213 		return false;
214 
215 	// perform query to get supported float control properties
216    vk::VkPhysicalDeviceFloatControlsProperties refControls;
217 	{
218 		refControls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES;
219 		refControls.pNext = DE_NULL;
220 
221 		VkPhysicalDeviceProperties2 deviceProperties;
222 		deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
223 		deviceProperties.pNext = &refControls;
224 
225 		const VkPhysicalDevice			physicalDevice		= context.getPhysicalDevice();
226 		const vk::InstanceInterface&	instanceInterface	= context.getInstanceInterface();
227 
228 		instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
229 	}
230 
231 	using FCIndependence = VkShaderFloatControlsIndependence;
232 	FCIndependence fcInd32		= VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY;
233 	FCIndependence fcIndAll		= VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
234 	FCIndependence fcIndNone	= VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE;
235 
236 	bool requiredDenormBehaviorNotSupported =
237 		((toCheck.denormBehaviorIndependence == fcIndAll) && (refControls.denormBehaviorIndependence != fcIndAll)) ||
238 		((toCheck.denormBehaviorIndependence == fcInd32)  && (refControls.denormBehaviorIndependence == fcIndNone));
239 
240 	bool requiredRoundingModeNotSupported =
241 		((toCheck.roundingModeIndependence == fcIndAll) && (refControls.roundingModeIndependence != fcIndAll)) ||
242 		((toCheck.roundingModeIndependence == fcInd32)  && (refControls.roundingModeIndependence == fcIndNone));
243 
244 	// check if flags needed by the test are not supported by the device
245 	bool requiredFeaturesNotSupported =
246 		requiredDenormBehaviorNotSupported ||
247 		requiredRoundingModeNotSupported ||
248 		(toCheck.shaderDenormFlushToZeroFloat16			&& !refControls.shaderDenormFlushToZeroFloat16) ||
249 		(toCheck.shaderDenormPreserveFloat16			&& !refControls.shaderDenormPreserveFloat16) ||
250 		(toCheck.shaderRoundingModeRTEFloat16			&& !refControls.shaderRoundingModeRTEFloat16) ||
251 		(toCheck.shaderRoundingModeRTZFloat16			&& !refControls.shaderRoundingModeRTZFloat16) ||
252 		(toCheck.shaderSignedZeroInfNanPreserveFloat16	&& !refControls.shaderSignedZeroInfNanPreserveFloat16) ||
253 		(toCheck.shaderDenormFlushToZeroFloat32			&& !refControls.shaderDenormFlushToZeroFloat32) ||
254 		(toCheck.shaderDenormPreserveFloat32			&& !refControls.shaderDenormPreserveFloat32) ||
255 		(toCheck.shaderRoundingModeRTEFloat32			&& !refControls.shaderRoundingModeRTEFloat32) ||
256 		(toCheck.shaderRoundingModeRTZFloat32			&& !refControls.shaderRoundingModeRTZFloat32) ||
257 		(toCheck.shaderSignedZeroInfNanPreserveFloat32	&& !refControls.shaderSignedZeroInfNanPreserveFloat32) ||
258 		(toCheck.shaderDenormFlushToZeroFloat64			&& !refControls.shaderDenormFlushToZeroFloat64) ||
259 		(toCheck.shaderDenormPreserveFloat64			&& !refControls.shaderDenormPreserveFloat64) ||
260 		(toCheck.shaderRoundingModeRTEFloat64			&& !refControls.shaderRoundingModeRTEFloat64) ||
261 		(toCheck.shaderRoundingModeRTZFloat64			&& !refControls.shaderRoundingModeRTZFloat64) ||
262 		(toCheck.shaderSignedZeroInfNanPreserveFloat64	&& !refControls.shaderSignedZeroInfNanPreserveFloat64);
263 
264 	// we checked if required features are not supported - we need to
265 	// negate the result to know if all required features are available
266 	return !requiredFeaturesNotSupported;
267 }
268 
isVulkanFeaturesSupported(const Context & context,const VulkanFeatures & requested,const char ** missingFeature)269 bool isVulkanFeaturesSupported(const Context& context, const VulkanFeatures& requested, const char **missingFeature)
270 {
271 	if (!isCoreFeaturesSupported(context, requested.coreFeatures, missingFeature))
272 		return false;
273 
274 	if (!is8BitStorageFeaturesSupported(context, requested.ext8BitStorage, missingFeature))
275 		return false;
276 
277 	if (!is16BitStorageFeaturesSupported(context, requested.ext16BitStorage, missingFeature))
278 		return false;
279 
280 	if (!isVariablePointersFeaturesSupported(context, requested.extVariablePointers, missingFeature))
281 		return false;
282 
283 	if (!isFloat16Int8FeaturesSupported(context, requested.extFloat16Int8, missingFeature))
284 		return false;
285 
286 	if (!isVulkanMemoryModelFeaturesSupported(context, requested.extVulkanMemoryModel, missingFeature))
287 		return false;
288 
289 	if (!isFloatControlsFeaturesSupported(context, requested.floatControlsProperties, missingFeature))
290 		return false;
291 
292 #ifndef CTS_USES_VULKANSC
293 	if (!isIntegerDotProductFeaturesSupported(context, requested.extIntegerDotProduct, missingFeature))
294 		return false;
295 #endif // CTS_USES_VULKANSC
296 
297 	return true;
298 }
299 
getMinRequiredVulkanVersion(const SpirvVersion version)300 deUint32 getMinRequiredVulkanVersion (const SpirvVersion version)
301 {
302 	switch(version)
303 	{
304 	case SPIRV_VERSION_1_0:
305 		return VK_API_VERSION_1_0;
306 	case SPIRV_VERSION_1_1:
307 	case SPIRV_VERSION_1_2:
308 	case SPIRV_VERSION_1_3:
309 	case SPIRV_VERSION_1_4:
310 		return VK_API_VERSION_1_1;
311 	case SPIRV_VERSION_1_5:
312 		return VK_API_VERSION_1_2;
313 	case SPIRV_VERSION_1_6:
314 #ifndef CTS_USES_VULKANSC
315 		return VK_API_VERSION_1_3;
316 #else// CTS_USES_VULKANSC
317 		TCU_THROW(NotSupportedError, "Unsupported SPIR-V version");
318 #endif // CTS_USES_VULKANSC
319 	default:
320 		DE_ASSERT(0);
321 	}
322 	return 0u;
323 }
324 
getVulkanName(const deUint32 version)325 std::string	getVulkanName (const deUint32 version)
326 {
327 	if (version == VK_API_VERSION_1_1)	return "1.1";
328 	if (version == VK_API_VERSION_1_2)	return "1.2";
329 #ifndef CTS_USES_VULKANSC
330 	if (version == VK_API_VERSION_1_3)	return "1.3";
331 #endif // CTS_USES_VULKANSC
332 
333 	return "1.0";
334 }
335 
336 // Generate and return 64-bit integers.
337 //
338 // Expected count to be at least 16.
getInt64s(de::Random & rnd,const deUint32 count)339 std::vector<deInt64> getInt64s (de::Random& rnd, const deUint32 count)
340 {
341 	std::vector<deInt64> data;
342 
343 	data.reserve(count);
344 
345 	// Make sure we have boundary numbers.
346 	data.push_back(deInt64(0x0000000000000000));  // 0
347 	data.push_back(deInt64(0x0000000000000001));  // 1
348 	data.push_back(deInt64(0x000000000000002a));  // 42
349 	data.push_back(deInt64(0x000000007fffffff));  // 2147483647
350 	data.push_back(deInt64(0x0000000080000000));  // 2147483648
351 	data.push_back(deInt64(0x00000000ffffffff));  // 4294967295
352 	data.push_back(deInt64(0x0000000100000000));  // 4294967296
353 	data.push_back(deInt64(0x7fffffffffffffff));  // 9223372036854775807
354 	data.push_back(deInt64(0x8000000000000000));  // -9223372036854775808
355 	data.push_back(deInt64(0x8000000000000001));  // -9223372036854775807
356 	data.push_back(deInt64(0xffffffff00000000));  // -4294967296
357 	data.push_back(deInt64(0xffffffff00000001));  // -4294967295
358 	data.push_back(deInt64(0xffffffff80000000));  // -2147483648
359 	data.push_back(deInt64(0xffffffff80000001));  // -2147483647
360 	data.push_back(deInt64(0xffffffffffffffd6));  // -42
361 	data.push_back(deInt64(0xffffffffffffffff));  // -1
362 
363 	DE_ASSERT(count >= data.size());
364 
365 	for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
366 		data.push_back(static_cast<deInt64>(rnd.getUint64()));
367 
368 	return data;
369 }
370 
371 // Generate and return 32-bit integers.
372 //
373 // Expected count to be at least 16.
getInt32s(de::Random & rnd,const deUint32 count)374 std::vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count)
375 {
376 	std::vector<deInt32> data;
377 
378 	data.reserve(count);
379 
380 	// Make sure we have boundary numbers.
381 	data.push_back(deInt32(0x00000000));  // 0
382 	data.push_back(deInt32(0x00000001));  // 1
383 	data.push_back(deInt32(0x0000002a));  // 42
384 	data.push_back(deInt32(0x00007fff));  // 32767
385 	data.push_back(deInt32(0x00008000));  // 32768
386 	data.push_back(deInt32(0x0000ffff));  // 65535
387 	data.push_back(deInt32(0x00010000));  // 65536
388 	data.push_back(deInt32(0x7fffffff));  // 2147483647
389 	data.push_back(deInt32(0x80000000));  // -2147483648
390 	data.push_back(deInt32(0x80000001));  // -2147483647
391 	data.push_back(deInt32(0xffff0000));  // -65536
392 	data.push_back(deInt32(0xffff0001));  // -65535
393 	data.push_back(deInt32(0xffff8000));  // -32768
394 	data.push_back(deInt32(0xffff8001));  // -32767
395 	data.push_back(deInt32(0xffffffd6));  // -42
396 	data.push_back(deInt32(0xffffffff));  // -1
397 
398 	DE_ASSERT(count >= data.size());
399 
400 	for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
401 		data.push_back(static_cast<deInt32>(rnd.getUint32()));
402 
403 	return data;
404 }
405 
406 // Generate and return 16-bit integers.
407 //
408 // Expected count to be at least 8.
getInt16s(de::Random & rnd,const deUint32 count)409 std::vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count)
410 {
411 	std::vector<deInt16> data;
412 
413 	data.reserve(count);
414 
415 	// Make sure we have boundary numbers.
416 	data.push_back(deInt16(0x0000));  // 0
417 	data.push_back(deInt16(0x0001));  // 1
418 	data.push_back(deInt16(0x002a));  // 42
419 	data.push_back(deInt16(0x7fff));  // 32767
420 	data.push_back(deInt16(0x8000));  // -32868
421 	data.push_back(deInt16(0x8001));  // -32767
422 	data.push_back(deInt16(0xffd6));  // -42
423 	data.push_back(deInt16(0xffff));  // -1
424 
425 	DE_ASSERT(count >= data.size());
426 
427 	for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
428 		data.push_back(static_cast<deInt16>(rnd.getUint16()));
429 
430 	return data;
431 }
432 
433 // Generate and return 8-bit integers.
434 //
435 // Expected count to be at least 8.
getInt8s(de::Random & rnd,const deUint32 count)436 std::vector<deInt8> getInt8s (de::Random& rnd, const deUint32 count)
437 {
438 	std::vector<deInt8> data;
439 
440 	data.reserve(count);
441 
442 	// Make sure we have boundary numbers.
443 	data.push_back(deInt8(0x00));  // 0
444 	data.push_back(deInt8(0x01));  // 1
445 	data.push_back(deInt8(0x2a));  // 42
446 	data.push_back(deInt8(0x7f));  // 127
447 	data.push_back(deInt8(0x80));  // -128
448 	data.push_back(deInt8(0x81));  // -127
449 	data.push_back(deInt8(0xd6));  // -42
450 	data.push_back(deInt8(0xff));  // -1
451 
452 	DE_ASSERT(count >= data.size());
453 
454 	for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
455 		data.push_back(static_cast<deInt8>(rnd.getUint8()));
456 
457 	return data;
458 }
459 
460 // IEEE-754 floating point numbers:
461 // +--------+------+----------+-------------+
462 // | binary | sign | exponent | significand |
463 // +--------+------+----------+-------------+
464 // | 64-bit |  1   |    11    |     52      |
465 // +--------+------+----------+-------------+
466 // | 32-bit |  1   |    8     |     23      |
467 // +--------+------+----------+-------------+
468 // | 16-bit |  1   |    5     |     10      |
469 // +--------+------+----------+-------------+
470 //
471 // 64-bit floats:
472 //
473 // (0x3FD2000000000000: 0.28125: with exact match in 16-bit normalized)
474 // (0x3F10060000000000: exact half way within two 16-bit normalized; round to zero: 0x0401)
475 // (0xBF10060000000000: exact half way within two 16-bit normalized; round to zero: 0x8402)
476 // (0x3F100C0000000000: not exact half way within two 16-bit normalized; round to zero: 0x0403)
477 // (0xBF100C0000000000: not exact half way within two 16-bit normalized; round to zero: 0x8404)
478 
479 // Generate and return 64-bit floats
480 //
481 // If includeSpecialFloat16Values is false, random float64 that can be converted to float16 inf/nan/denormal must be excluded
482 // since inf may be clamped, and nan/denormal be flushed without float control features.
483 // And expected count to be at least 14 (numPicks).
484 // Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
485 // And expected count to be at least 24 (numPicks).
getFloat64s(de::Random & rnd,deUint32 count,deBool includeSpecialFloat16Values)486 std::vector<double> getFloat64s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values)
487 {
488 	std::vector<double> float64;
489 
490 	float64.reserve(count);
491 
492 	if (includeSpecialFloat16Values)
493 	{
494 		// Infinity
495 		float64.push_back(std::numeric_limits<double>::infinity());
496 		float64.push_back(-std::numeric_limits<double>::infinity());
497 		// SNaN
498 		float64.push_back(std::numeric_limits<double>::signaling_NaN());
499 		float64.push_back(-std::numeric_limits<double>::signaling_NaN());
500 		// QNaN
501 		float64.push_back(std::numeric_limits<double>::quiet_NaN());
502 		float64.push_back(-std::numeric_limits<double>::quiet_NaN());
503 		// Normalized 64-bit float with exact denormalized match in 16-bit
504 		float64.push_back(bitwiseCast<double>(deUint64(0x3B0357C299A88EA8)));
505 		float64.push_back(bitwiseCast<double>(deUint64(0xBB0357C299A88EA8)));
506 		// Normalized 64-bit float matching infinity in 16-bit
507 		float64.push_back(ldexp((double)1.f, 100));
508 		float64.push_back(-ldexp((double)1.f, 100));
509 	}
510 	// Zero
511 	float64.push_back(0.f);
512 	float64.push_back(-0.f);
513 	// Denormalized 64-bit float matching 0 in 16-bit
514 	float64.push_back(ldexp((double)1.f, -1023));
515 	float64.push_back(-ldexp((double)1.f, -1023));
516 	// Normalized 64-bit float matching 0 in 16-bit
517 	float64.push_back(ldexp((double)1.f, -100));
518 	float64.push_back(-ldexp((double)1.f, -100));
519 	// Normalized 64-bit float with exact normalized match in 16-bit
520 	float64.push_back(ldexp((double)1.f, -14));  // 2e-14: minimum 16-bit positive normalized
521 	float64.push_back(-ldexp((double)1.f, -14)); // 2e-14: maximum 16-bit negative normalized
522 	// Normalized 64-bit float falling above half way within two 16-bit normalized
523 	float64.push_back(bitwiseCast<double>(deUint64(0x3FD2000000000000)));
524 	float64.push_back(bitwiseCast<double>(deUint64(0xBFD2000000000000)));
525 	// Normalized 64-bit float falling exact half way within two 16-bit normalized
526 	float64.push_back(bitwiseCast<double>(deUint64(0x3F100C0000000000)));
527 	float64.push_back(bitwiseCast<double>(deUint64(0xBF100C0000000000)));
528 	// Some number
529 	float64.push_back((double)0.28125f);
530 	float64.push_back((double)-0.28125f);
531 
532 	const deUint32		numPicks	= static_cast<deUint32>(float64.size());
533 
534 	DE_ASSERT(count >= numPicks);
535 	count -= numPicks;
536 
537 	for (deUint32 numNdx = 0; numNdx < count;)
538 	{
539 		double rndFloat = rnd.getDouble();
540 		// If special float16 values must be excluded, generated double values that result in inf/nan/denormal of float16 should be removed.
541 		if (!includeSpecialFloat16Values)
542 		{
543 			deFloat16 rndFloat16 = deFloat64To16(rndFloat);
544 			if (deHalfIsInf(rndFloat16) || deHalfIsIEEENaN(rndFloat16) || deHalfIsDenormal(rndFloat16))
545 				continue;
546 		}
547 		float64.push_back(rndFloat);
548 		++numNdx;
549 	}
550 
551 	return float64;
552 }
553 
554 // IEEE-754 floating point numbers:
555 // +--------+------+----------+-------------+
556 // | binary | sign | exponent | significand |
557 // +--------+------+----------+-------------+
558 // | 16-bit |  1   |    5     |     10      |
559 // +--------+------+----------+-------------+
560 // | 32-bit |  1   |    8     |     23      |
561 // +--------+------+----------+-------------+
562 //
563 // 16-bit floats:
564 //
565 // 0   000 00   00 0000 0001 (0x0001: 2e-24:         minimum positive denormalized)
566 // 0   000 00   11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
567 // 0   000 01   00 0000 0000 (0x0400: 2e-14:         minimum positive normalized)
568 //
569 // 32-bit floats:
570 //
571 // 0   011 1110 1   001 0000 0000 0000 0000 0000 (0x3e900000: 0.28125: with exact match in 16-bit normalized)
572 // 0   011 1000 1   000 0000 0011 0000 0000 0000 (0x38803000: exact half way within two 16-bit normalized; round to zero: 0x0401)
573 // 1   011 1000 1   000 0000 0011 0000 0000 0000 (0xb8803000: exact half way within two 16-bit normalized; round to zero: 0x8402)
574 // 0   011 1000 1   000 0000 1111 1111 0000 0000 (0x3880ff00: not exact half way within two 16-bit normalized; round to zero: 0x0403)
575 // 1   011 1000 1   000 0000 1111 1111 0000 0000 (0xb880ff00: not exact half way within two 16-bit normalized; round to zero: 0x8404)
576 
577 // Generate and return 32-bit floats
578 //
579 // If includeSpecialFloat16Values is false, random float32 that can be converted to float16 inf/nan/denormal must be excluded
580 // since inf may be clamped, and nan/denormal be flushed without float control features.
581 // And expected count to be at least 14 (numPicks).
582 // Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
583 // And expected count to be at least 24 (numPicks).
getFloat32s(de::Random & rnd,deUint32 count,deBool includeSpecialFloat16Values)584 std::vector<float> getFloat32s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values)
585 {
586 	std::vector<float> float32;
587 
588 	float32.reserve(count);
589 
590 	if (includeSpecialFloat16Values)
591 	{
592 		// Infinity
593 		float32.push_back(std::numeric_limits<float>::infinity());
594 		float32.push_back(-std::numeric_limits<float>::infinity());
595 		// SNaN
596 		float32.push_back(std::numeric_limits<float>::signaling_NaN());
597 		float32.push_back(-std::numeric_limits<float>::signaling_NaN());
598 		// QNaN
599 		float32.push_back(std::numeric_limits<float>::quiet_NaN());
600 		float32.push_back(-std::numeric_limits<float>::quiet_NaN());
601 		// Normalized 32-bit float with exact denormalized match in 16-bit
602 		float32.push_back(deFloatLdExp(1.f, -24));  // 2e-24: minimum 16-bit positive denormalized
603 		float32.push_back(-deFloatLdExp(1.f, -24)); // 2e-24: maximum 16-bit negative denormalized
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 	// Zero
609 	float32.push_back(0.f);
610 	float32.push_back(-0.f);
611 	// Denormalized 32-bit float matching 0 in 16-bit
612 	float32.push_back(deFloatLdExp(1.f, -127));
613 	float32.push_back(-deFloatLdExp(1.f, -127));
614 	// Normalized 32-bit float matching 0 in 16-bit
615 	float32.push_back(deFloatLdExp(1.f, -100));
616 	float32.push_back(-deFloatLdExp(1.f, -100));
617 	// Normalized 32-bit float with exact normalized match in 16-bit
618 	float32.push_back(deFloatLdExp(1.f, -14));  // 2e-14: minimum 16-bit positive normalized
619 	float32.push_back(-deFloatLdExp(1.f, -14)); // 2e-14: maximum 16-bit negative normalized
620 	// Normalized 32-bit float falling above half way within two 16-bit normalized
621 	float32.push_back(bitwiseCast<float>(deUint32(0x3880ff00)));
622 	float32.push_back(bitwiseCast<float>(deUint32(0xb880ff00)));
623 	// Normalized 32-bit float falling exact half way within two 16-bit normalized
624 	float32.push_back(bitwiseCast<float>(deUint32(0x38803000)));
625 	float32.push_back(bitwiseCast<float>(deUint32(0xb8803000)));
626 	// Some number
627 	float32.push_back(0.28125f);
628 	float32.push_back(-0.28125f);
629 
630 	const deUint32		numPicks	= static_cast<deUint32>(float32.size());
631 
632 	DE_ASSERT(count >= numPicks);
633 	count -= numPicks;
634 
635 	for (deUint32 numNdx = 0; numNdx < count;)
636 	{
637 		float rndFloat = rnd.getFloat();
638 		// If special float16 values must be excluded, generated float values that result in inf/nan/denormal of float16 should be removed.
639 		if (!includeSpecialFloat16Values)
640 		{
641 			deFloat16 rndFloat16 = deFloat32To16(rndFloat);
642 			if (deHalfIsInf(rndFloat16) || deHalfIsIEEENaN(rndFloat16) || deHalfIsDenormal(rndFloat16))
643 				continue;
644 		}
645 
646 		float32.push_back(rndFloat);
647 		++numNdx;
648 	}
649 
650 	return float32;
651 }
652 
653 // IEEE-754 floating point numbers:
654 // +--------+------+----------+-------------+
655 // | binary | sign | exponent | significand |
656 // +--------+------+----------+-------------+
657 // | 16-bit |  1   |    5     |     10      |
658 // +--------+------+----------+-------------+
659 // | 32-bit |  1   |    8     |     23      |
660 // +--------+------+----------+-------------+
661 //
662 // 16-bit floats:
663 //
664 // 0   000 00   00 0000 0001 (0x0001: 2e-24:         minimum positive denormalized)
665 // 0   000 00   11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
666 // 0   000 01   00 0000 0000 (0x0400: 2e-14:         minimum positive normalized)
667 //
668 // 0   000 00   00 0000 0000 (0x0000: +0)
669 // 0   111 11   00 0000 0000 (0x7c00: +Inf)
670 // 0   000 00   11 1111 0000 (0x03f0: +Denorm)
671 // 0   000 01   00 0000 0001 (0x0401: +Norm)
672 // 0   111 11   00 0000 1111 (0x7c0f: +SNaN)
673 // 0   111 11   00 1111 0000 (0x7c0f: +QNaN)
674 
675 // Generate and return 16-bit floats
676 //
677 // If includeSpecialFloat16Values is false, float16 inf/nan/denormal must be excluded since inf may be clamped,
678 // and nan/denormal be flushed without float control features. And expected count to be at least 6 (numPicks).
679 // Otherwise, the first 14 number pairs are manually picked, while the rest are randomly generated.
680 // And expected count to be at least 14 (numPicks).
getFloat16s(de::Random & rnd,deUint32 count,deBool includeSpecialFloat16Values)681 std::vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values)
682 {
683 	std::vector<deFloat16> float16;
684 
685 	float16.reserve(count);
686 
687 	if (includeSpecialFloat16Values)
688 	{
689 		// Infinity
690 		float16.push_back(deUint16(0x7c00));
691 		float16.push_back(deUint16(0xfc00));
692 		// SNaN
693 		float16.push_back(deUint16(0x7c0f));
694 		float16.push_back(deUint16(0xfc0f));
695 		// QNaN
696 		float16.push_back(deUint16(0x7cf0));
697 		float16.push_back(deUint16(0xfcf0));
698 		// Denormalized
699 		float16.push_back(deUint16(0x03f0));
700 		float16.push_back(deUint16(0x83f0));
701 	}
702 	// Zero
703 	float16.push_back(deUint16(0x0000));
704 	float16.push_back(deUint16(0x8000));
705 	// Normalized
706 	float16.push_back(deUint16(0x0401));
707 	float16.push_back(deUint16(0x8401));
708 	// Some normal number
709 	float16.push_back(deUint16(0x14cb));
710 	float16.push_back(deUint16(0x94cb));
711 
712 	const deUint32		numPicks	= static_cast<deUint32>(float16.size());
713 
714 	DE_ASSERT(count >= numPicks);
715 	count -= numPicks;
716 
717 	for (deUint32 numIdx = 0; numIdx < count;)
718 	{
719 		deFloat16 rndFloat = rnd.getUint16();
720 		// If special float16 values must be excluded, generated values in inf/nan/denormal should be removed.
721 		if (!includeSpecialFloat16Values && (deHalfIsInf(rndFloat) || deHalfIsIEEENaN(rndFloat) || deHalfIsDenormal(rndFloat)))
722 			continue;
723 		float16.push_back(rndFloat);
724 		++numIdx;
725 	}
726 
727 	return float16;
728 }
729 
getOpCapabilityShader()730 std::string getOpCapabilityShader()
731 {
732 	return	"OpCapability Shader\n";
733 }
734 
getUnusedEntryPoint()735 std::string getUnusedEntryPoint()
736 {
737 	return	"OpEntryPoint Vertex %unused_func \"unused_func\"\n";
738 }
739 
getUnusedDecorations(const VariableLocation & location)740 std::string getUnusedDecorations(const VariableLocation& location)
741 {
742 	return	"OpMemberDecorate %UnusedBufferType 0 Offset 0\n"
743             "OpMemberDecorate %UnusedBufferType 1 Offset 4\n"
744             "OpDecorate %UnusedBufferType BufferBlock\n"
745             "OpDecorate %unused_buffer DescriptorSet " + de::toString(location.set) + "\n"
746             "OpDecorate %unused_buffer Binding " + de::toString(location.binding) + "\n";
747 }
748 
getUnusedTypesAndConstants()749 std::string getUnusedTypesAndConstants()
750 {
751 	return	"%c_f32_101 = OpConstant %f32 101\n"
752 			"%c_i32_201 = OpConstant %i32 201\n"
753 			"%UnusedBufferType = OpTypeStruct %f32 %i32\n"
754 			"%unused_ptr_Uniform_UnusedBufferType = OpTypePointer Uniform %UnusedBufferType\n"
755 			"%unused_ptr_Uniform_float = OpTypePointer Uniform %f32\n"
756 			"%unused_ptr_Uniform_int = OpTypePointer Uniform %i32\n";
757 }
758 
getUnusedBuffer()759 std::string getUnusedBuffer()
760 {
761 	return	"%unused_buffer = OpVariable %unused_ptr_Uniform_UnusedBufferType Uniform\n";
762 }
763 
getUnusedFunctionBody()764 std::string getUnusedFunctionBody()
765 {
766 	return	"%unused_func = OpFunction %void None %voidf\n"
767 			"%unused_func_label = OpLabel\n"
768 			"%unused_out_float_ptr = OpAccessChain %unused_ptr_Uniform_float %unused_buffer %c_i32_0\n"
769             "OpStore %unused_out_float_ptr %c_f32_101\n"
770 			"%unused_out_int_ptr = OpAccessChain %unused_ptr_Uniform_int %unused_buffer %c_i32_1\n"
771             "OpStore %unused_out_int_ptr %c_i32_201\n"
772             "OpReturn\n"
773             "OpFunctionEnd\n";
774 }
775 
776 } // SpirVAssembly
777 } // vkt
778