1#ifndef _VKTSPVASMUTILS_HPP
2#define _VKTSPVASMUTILS_HPP
3/*-------------------------------------------------------------------------
4 * Vulkan Conformance Tests
5 * ------------------------
6 *
7 * Copyright (c) 2017 Google Inc.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Utilities for Vulkan SPIR-V assembly tests
24 *//*--------------------------------------------------------------------*/
25
26#include "vkDefs.hpp"
27#include "vkMemUtil.hpp"
28#include "vkRef.hpp"
29#include "vkTypeUtil.hpp"
30#include "vktTestCase.hpp"
31
32#include "deMemory.h"
33#include "deUniquePtr.hpp"
34#include "deSharedPtr.hpp"
35#include "deRandom.hpp"
36#include "deFloat16.h"
37
38#include <string>
39#include <vector>
40
41namespace vkt
42{
43namespace SpirVAssembly
44{
45
46#define SPIRV_ASSEMBLY_TYPES																				\
47	"%void = OpTypeVoid\n"																					\
48	"%bool = OpTypeBool\n"																					\
49																											\
50	"%i32 = OpTypeInt 32 1\n"																				\
51	"%u32 = OpTypeInt 32 0\n"																				\
52																											\
53	"%f32 = OpTypeFloat 32\n"																				\
54	"%v2i32 = OpTypeVector %i32 2\n"																		\
55	"%v2u32 = OpTypeVector %u32 2\n"																		\
56	"%v2f32 = OpTypeVector %f32 2\n"																		\
57	"%v3i32 = OpTypeVector %i32 3\n"																		\
58	"%v3u32 = OpTypeVector %u32 3\n"																		\
59	"%v3f32 = OpTypeVector %f32 3\n"																		\
60	"%v4i32 = OpTypeVector %i32 4\n"																		\
61	"%v4u32 = OpTypeVector %u32 4\n"																		\
62	"%v4f32 = OpTypeVector %f32 4\n"																		\
63	"%v4bool = OpTypeVector %bool 4\n"																		\
64																											\
65	"%v4f32_v4f32_function = OpTypeFunction %v4f32 %v4f32\n"									\
66	"%bool_function = OpTypeFunction %bool\n"																\
67	"%voidf = OpTypeFunction %void\n"																			\
68																											\
69	"%ip_f32 = OpTypePointer Input %f32\n"																	\
70	"%ip_i32 = OpTypePointer Input %i32\n"																	\
71	"%ip_u32 = OpTypePointer Input %u32\n"																	\
72	"%ip_v2f32 = OpTypePointer Input %v2f32\n"																\
73	"%ip_v2i32 = OpTypePointer Input %v2i32\n"																\
74	"%ip_v2u32 = OpTypePointer Input %v2u32\n"																\
75	"%ip_v3f32 = OpTypePointer Input %v3f32\n"																\
76	"%ip_v4f32 = OpTypePointer Input %v4f32\n"																\
77	"%ip_v4i32 = OpTypePointer Input %v4i32\n"																\
78	"%ip_v4u32 = OpTypePointer Input %v4u32\n"																\
79																											\
80	"%op_f32 = OpTypePointer Output %f32\n"																	\
81	"%op_i32 = OpTypePointer Output %i32\n"																	\
82	"%op_u32 = OpTypePointer Output %u32\n"																	\
83	"%op_v2f32 = OpTypePointer Output %v2f32\n"																\
84	"%op_v2i32 = OpTypePointer Output %v2i32\n"																\
85	"%op_v2u32 = OpTypePointer Output %v2u32\n"																\
86	"%op_v4f32 = OpTypePointer Output %v4f32\n"																\
87	"%op_v4i32 = OpTypePointer Output %v4i32\n"																\
88	"%op_v4u32 = OpTypePointer Output %v4u32\n"																\
89																											\
90	"%fp_f32   = OpTypePointer Function %f32\n"																\
91	"%fp_i32   = OpTypePointer Function %i32\n"																\
92	"%fp_v4f32 = OpTypePointer Function %v4f32\n"															\
93
94#define SPIRV_ASSEMBLY_CONSTANTS																			\
95	"%c_f32_1 = OpConstant %f32 1.0\n"																		\
96	"%c_f32_0 = OpConstant %f32 0.0\n"																		\
97	"%c_f32_0_5 = OpConstant %f32 0.5\n"																	\
98	"%c_f32_n1  = OpConstant %f32 -1.\n"																	\
99	"%c_f32_7 = OpConstant %f32 7.0\n"																		\
100	"%c_f32_8 = OpConstant %f32 8.0\n"																		\
101	"%c_i32_0 = OpConstant %i32 0\n"																		\
102	"%c_i32_1 = OpConstant %i32 1\n"																		\
103	"%c_i32_2 = OpConstant %i32 2\n"																		\
104	"%c_i32_3 = OpConstant %i32 3\n"																		\
105	"%c_i32_4 = OpConstant %i32 4\n"																		\
106	"%c_u32_0 = OpConstant %u32 0\n"																		\
107	"%c_u32_1 = OpConstant %u32 1\n"																		\
108	"%c_u32_2 = OpConstant %u32 2\n"																		\
109	"%c_u32_3 = OpConstant %u32 3\n"																		\
110	"%c_u32_32 = OpConstant %u32 32\n"																		\
111	"%c_u32_4 = OpConstant %u32 4\n"																		\
112	"%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n"															\
113	"%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"					\
114	"%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n"					\
115	"%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n"	\
116
117#define SPIRV_ASSEMBLY_ARRAYS																				\
118	"%a1f32 = OpTypeArray %f32 %c_u32_1\n"																	\
119	"%a2f32 = OpTypeArray %f32 %c_u32_2\n"																	\
120	"%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n"																\
121	"%a4f32 = OpTypeArray %f32 %c_u32_4\n"																	\
122	"%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n"															\
123	"%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n"															\
124	"%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n"														\
125	"%op_a2f32 = OpTypePointer Output %a2f32\n"																\
126	"%op_a3v4f32 = OpTypePointer Output %a3v4f32\n"															\
127	"%op_a4f32 = OpTypePointer Output %a4f32\n"																\
128
129/*--------------------------------------------------------------------*//*!
130 * \brief Abstract class for an input/output storage buffer object
131 *//*--------------------------------------------------------------------*/
132class BufferInterface
133{
134public:
135	virtual				~BufferInterface	(void)				{}
136
137	virtual void		getBytes			(std::vector<deUint8>& bytes) const = 0;
138	virtual void		getPackedBytes		(std::vector<deUint8>& bytes) const = 0;
139	virtual size_t		getByteSize			(void) const = 0;
140};
141
142typedef de::SharedPtr<BufferInterface>	BufferSp;
143typedef de::MovePtr<vk::Allocation>		AllocationMp;
144typedef de::SharedPtr<vk::Allocation>	AllocationSp;
145
146class Resource
147{
148public:
149	Resource(const BufferSp& buffer_, vk::VkDescriptorType descriptorType_ = vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, void* userData_ = NULL)
150		: buffer(buffer_)
151		, descriptorType(descriptorType_)
152		, userData(userData_)
153	{
154	}
155
156	virtual const BufferSp&			getBuffer			() const							{ return buffer; }
157	virtual void					getBytes			(std::vector<deUint8>& bytes) const	{ buffer->getBytes(bytes); }
158	virtual size_t					getByteSize			(void) const						{ return buffer->getByteSize(); }
159
160	virtual void					setDescriptorType	(vk::VkDescriptorType type)		{ descriptorType = type; }
161	virtual vk::VkDescriptorType	getDescriptorType	()	const						{ return descriptorType; }
162
163	virtual void					setUserData			(void* data)					{ userData = data; }
164	virtual void*					getUserData			() const						{ return userData; }
165
166private:
167	BufferSp				buffer;
168	vk::VkDescriptorType	descriptorType;
169	void*					userData;
170};
171
172typedef bool (*VerifyIOFunc) (const std::vector<Resource>&		inputs,
173							  const std::vector<AllocationSp>&	outputAllocations,
174							  const std::vector<Resource>&		expectedOutputs,
175							  tcu::TestLog&						log);
176
177struct SpecConstants
178{
179public:
180							SpecConstants (void)
181							{}
182
183	bool					empty (void) const
184							{
185								return valuesBuffer.empty();
186							}
187
188	size_t					getValuesCount (void) const
189							{
190								return sizesBuffer.size();
191							}
192
193	size_t					getValueSize (const size_t valueIndex) const
194							{
195								return sizesBuffer[valueIndex];
196							}
197
198	const void*				getValuesBuffer (void) const
199							{
200								if (valuesBuffer.size() == 0)
201									return DE_NULL;
202								else
203									return static_cast<const void*>(&valuesBuffer[0]);
204							}
205
206	template<typename T>
207	void					append (const T value)
208							{
209								append(&value, sizeof(value));
210							}
211
212	void					append (const void* buf, const size_t byteSize)
213							{
214								DE_ASSERT(byteSize > 0);
215
216								valuesBuffer.resize(valuesBuffer.size() + byteSize);
217								deMemcpy(&valuesBuffer[valuesBuffer.size() - byteSize], buf, byteSize);
218
219								sizesBuffer.push_back(byteSize);
220							}
221
222private:
223	std::vector<deUint8>	valuesBuffer;
224	std::vector<size_t>		sizesBuffer;
225};
226
227struct VulkanFeatures
228{
229	vk::VkPhysicalDeviceFeatures							coreFeatures;
230	vk::VkPhysicalDeviceShaderFloat16Int8Features			extFloat16Int8;
231	vk::VkPhysicalDevice8BitStorageFeatures					ext8BitStorage;
232	vk::VkPhysicalDevice16BitStorageFeatures				ext16BitStorage;
233	vk::VkPhysicalDeviceVariablePointersFeatures			extVariablePointers;
234	vk::VkPhysicalDeviceVulkanMemoryModelFeatures			extVulkanMemoryModel;
235#ifndef CTS_USES_VULKANSC
236	vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR	extIntegerDotProduct;
237#endif // CTS_USES_VULKANSC
238	vk::VkPhysicalDeviceFloatControlsProperties				floatControlsProperties;
239
240	VulkanFeatures				(void)
241	{
242		deMemset(&coreFeatures,				0, sizeof(coreFeatures));
243		deMemset(&extFloat16Int8,			0, sizeof(vk::VkPhysicalDeviceShaderFloat16Int8Features));
244		deMemset(&ext8BitStorage,			0, sizeof(vk::VkPhysicalDevice8BitStorageFeatures));
245		deMemset(&ext16BitStorage,			0, sizeof(vk::VkPhysicalDevice16BitStorageFeatures));
246		deMemset(&extVariablePointers,		0, sizeof(vk::VkPhysicalDeviceVariablePointersFeatures));
247		deMemset(&extVulkanMemoryModel,		0, sizeof(vk::VkPhysicalDeviceVulkanMemoryModelFeatures));
248#ifndef CTS_USES_VULKANSC
249		deMemset(&extIntegerDotProduct,		0, sizeof(vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR));
250#endif // CTS_USES_VULKANSC
251		deMemset(&floatControlsProperties,	0, sizeof(vk::VkPhysicalDeviceFloatControlsProperties));
252		floatControlsProperties.denormBehaviorIndependence	= vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE;
253		floatControlsProperties.roundingModeIndependence	= vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE;
254	}
255};
256
257// Returns true if the whole VulkanFeatures is supported. If not, missingFeature will contain one feature that was missing.
258bool isVulkanFeaturesSupported(const Context& context, const VulkanFeatures& toCheck, const char** missingFeature);
259
260struct VariableLocation
261{
262	deUint32 set;
263	deUint32 binding;
264
265	// Returns a string representation of the structure suitable for test names.
266	std::string toString() const ;
267
268	// Returns a string representation of the structure suitable for test descriptions.
269	std::string toDescription() const;
270};
271
272// Returns true if the given float controls features in `toCheck` are all supported.
273bool isFloatControlsFeaturesSupported(	const Context&										context,
274										const vk::VkPhysicalDeviceFloatControlsProperties&	toCheck,
275										const char**										missingFeature);
276
277deUint32 getMinRequiredVulkanVersion (const vk::SpirvVersion version);
278
279std::string	getVulkanName (const deUint32 version);
280
281// Performs a bitwise copy of source to the destination type Dest.
282template <typename Dest, typename Src>
283Dest bitwiseCast (Src source)
284{
285  Dest dest;
286  DE_STATIC_ASSERT(sizeof(source) == sizeof(dest));
287  deMemcpy(&dest, &source, sizeof(dest));
288  return dest;
289}
290
291// Generate and return 64-bit integers.
292//
293// Expected count to be at least 16.
294std::vector<deInt64> getInt64s (de::Random& rnd, const deUint32 count);
295
296// Generate and return 32-bit integers.
297//
298// Expected count to be at least 16.
299std::vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count);
300
301// Generate and return 16-bit integers.
302//
303// Expected count to be at least 8.
304std::vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count);
305
306// Generate and return 8-bit integers.
307//
308// Expected count to be at least 8.
309std::vector<deInt8> getInt8s (de::Random& rnd, const deUint32 count);
310
311// Generate and return 64-bit floats
312//
313// If includeSpecialFloat16Values is false, random float64 that can be converted to float16 inf/nan/denormal must be excluded
314// since inf may be clamped, and nan/denormal be flushed without float control features.
315// And expected count to be at least 14 (numPicks).
316// Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
317// And expected count to be at least 24 (numPicks).
318std::vector<double> getFloat64s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values = DE_TRUE);
319
320// Generate and return 32-bit floats
321//
322// If includeSpecialFloat16Values is false, random float32 that can be converted to float16 inf/nan/denormal must be excluded
323// since inf may be clamped, and nan/denormal be flushed without float control features.
324// And expected count to be at least 14 (numPicks).
325// Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
326// And expected count to be at least 24 (numPicks).
327std::vector<float> getFloat32s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values = DE_TRUE);
328
329// Generate and return 16-bit floats
330//
331// If includeSpecialFloat16Values is false, float16 inf/nan/denormal must be excluded since inf may be clamped,
332// and nan/denormal be flushed without float control features. And expected count to be at least 6 (numPicks).
333// Otherwise, the first 14 number pairs are manually picked, while the rest are randomly generated.
334// And expected count to be at least 14 (numPicks).
335std::vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count, deBool includeSpecialFloat16Values = DE_TRUE);
336
337// Generate an OpCapability Shader line.
338std::string getOpCapabilityShader();
339
340// Generate an unused Vertex entry point.
341std::string getUnusedEntryPoint();
342
343// Generate unused decorations for an input/output buffer.
344std::string getUnusedDecorations(const VariableLocation& location);
345
346// Generate unused types and constants, including a buffer type.
347std::string getUnusedTypesAndConstants();
348
349// Generate the declaration of an unused buffer variable.
350std::string getUnusedBuffer();
351
352// Generate the body of an unused function that uses the previous buffer.
353std::string getUnusedFunctionBody();
354
355} // SpirVAssembly
356} // vkt
357
358#endif // _VKTSPVASMUTILS_HPP
359