xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
41 namespace vkt
42 {
43 namespace 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  *//*--------------------------------------------------------------------*/
132 class BufferInterface
133 {
134 public:
~BufferInterface(void)135     virtual ~BufferInterface(void)
136     {
137     }
138 
139     virtual void getBytes(std::vector<uint8_t> &bytes) const       = 0;
140     virtual void getPackedBytes(std::vector<uint8_t> &bytes) const = 0;
141     virtual size_t getByteSize(void) const                         = 0;
142 };
143 
144 typedef de::SharedPtr<BufferInterface> BufferSp;
145 typedef de::MovePtr<vk::Allocation> AllocationMp;
146 typedef de::SharedPtr<vk::Allocation> AllocationSp;
147 
148 class Resource
149 {
150 public:
Resource(const BufferSp & buffer_,vk::VkDescriptorType descriptorType_=vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,void * userData_=NULL)151     Resource(const BufferSp &buffer_, vk::VkDescriptorType descriptorType_ = vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
152              void *userData_ = NULL)
153         : buffer(buffer_)
154         , descriptorType(descriptorType_)
155         , userData(userData_)
156     {
157     }
158 
~Resource()159     virtual ~Resource()
160     {
161     }
162 
getBuffer() const163     virtual const BufferSp &getBuffer() const
164     {
165         return buffer;
166     }
getBytes(std::vector<uint8_t> & bytes) const167     virtual void getBytes(std::vector<uint8_t> &bytes) const
168     {
169         buffer->getBytes(bytes);
170     }
getByteSize(void) const171     virtual size_t getByteSize(void) const
172     {
173         return buffer->getByteSize();
174     }
175 
setDescriptorType(vk::VkDescriptorType type)176     virtual void setDescriptorType(vk::VkDescriptorType type)
177     {
178         descriptorType = type;
179     }
getDescriptorType() const180     virtual vk::VkDescriptorType getDescriptorType() const
181     {
182         return descriptorType;
183     }
184 
setUserData(void * data)185     virtual void setUserData(void *data)
186     {
187         userData = data;
188     }
getUserData() const189     virtual void *getUserData() const
190     {
191         return userData;
192     }
193 
194 private:
195     BufferSp buffer;
196     vk::VkDescriptorType descriptorType;
197     void *userData;
198 };
199 
200 typedef bool (*VerifyIOFunc)(const std::vector<Resource> &inputs, const std::vector<AllocationSp> &outputAllocations,
201                              const std::vector<Resource> &expectedOutputs, tcu::TestLog &log);
202 
203 struct SpecConstants
204 {
205 public:
SpecConstantsvkt::SpirVAssembly::SpecConstants206     SpecConstants(void)
207     {
208     }
209 
emptyvkt::SpirVAssembly::SpecConstants210     bool empty(void) const
211     {
212         return valuesBuffer.empty();
213     }
214 
getValuesCountvkt::SpirVAssembly::SpecConstants215     size_t getValuesCount(void) const
216     {
217         return sizesBuffer.size();
218     }
219 
getValueSizevkt::SpirVAssembly::SpecConstants220     size_t getValueSize(const size_t valueIndex) const
221     {
222         return sizesBuffer[valueIndex];
223     }
224 
getValuesBuffervkt::SpirVAssembly::SpecConstants225     const void *getValuesBuffer(void) const
226     {
227         if (valuesBuffer.size() == 0)
228             return DE_NULL;
229         else
230             return static_cast<const void *>(&valuesBuffer[0]);
231     }
232 
233     template <typename T>
appendvkt::SpirVAssembly::SpecConstants234     void append(const T value)
235     {
236         append(&value, sizeof(value));
237     }
238 
appendvkt::SpirVAssembly::SpecConstants239     void append(const void *buf, const size_t byteSize)
240     {
241         DE_ASSERT(byteSize > 0);
242 
243         valuesBuffer.resize(valuesBuffer.size() + byteSize);
244         deMemcpy(&valuesBuffer[valuesBuffer.size() - byteSize], buf, byteSize);
245 
246         sizesBuffer.push_back(byteSize);
247     }
248 
249 private:
250     std::vector<uint8_t> valuesBuffer;
251     std::vector<size_t> sizesBuffer;
252 };
253 
254 struct VulkanFeatures
255 {
256     vk::VkPhysicalDeviceFeatures coreFeatures;
257     vk::VkPhysicalDeviceShaderFloat16Int8Features extFloat16Int8;
258     vk::VkPhysicalDevice8BitStorageFeatures ext8BitStorage;
259     vk::VkPhysicalDevice16BitStorageFeatures ext16BitStorage;
260     vk::VkPhysicalDeviceVariablePointersFeatures extVariablePointers;
261     vk::VkPhysicalDeviceVulkanMemoryModelFeatures extVulkanMemoryModel;
262 #ifndef CTS_USES_VULKANSC
263     vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR extIntegerDotProduct;
264     vk::VkPhysicalDeviceShaderFloatControls2FeaturesKHR extFloatControls2;
265 #endif // CTS_USES_VULKANSC
266     vk::VkPhysicalDeviceFloatControlsProperties floatControlsProperties;
267 
VulkanFeaturesvkt::SpirVAssembly::VulkanFeatures268     VulkanFeatures(void)
269     {
270         deMemset(&coreFeatures, 0, sizeof(coreFeatures));
271         deMemset(&extFloat16Int8, 0, sizeof(vk::VkPhysicalDeviceShaderFloat16Int8Features));
272         deMemset(&ext8BitStorage, 0, sizeof(vk::VkPhysicalDevice8BitStorageFeatures));
273         deMemset(&ext16BitStorage, 0, sizeof(vk::VkPhysicalDevice16BitStorageFeatures));
274         deMemset(&extVariablePointers, 0, sizeof(vk::VkPhysicalDeviceVariablePointersFeatures));
275         deMemset(&extVulkanMemoryModel, 0, sizeof(vk::VkPhysicalDeviceVulkanMemoryModelFeatures));
276 #ifndef CTS_USES_VULKANSC
277         deMemset(&extIntegerDotProduct, 0, sizeof(vk::VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR));
278         deMemset(&extFloatControls2, 0, sizeof(vk::VkPhysicalDeviceShaderFloatControls2FeaturesKHR));
279 #endif // CTS_USES_VULKANSC
280         deMemset(&floatControlsProperties, 0, sizeof(vk::VkPhysicalDeviceFloatControlsProperties));
281         floatControlsProperties.denormBehaviorIndependence = vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE;
282         floatControlsProperties.roundingModeIndependence   = vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE;
283     }
284 };
285 
286 // Returns true if the whole VulkanFeatures is supported. If not, missingFeature will contain one feature that was missing.
287 bool isVulkanFeaturesSupported(const Context &context, const VulkanFeatures &toCheck, const char **missingFeature);
288 
289 struct VariableLocation
290 {
291     uint32_t set;
292     uint32_t binding;
293 
294     // Returns a string representation of the structure suitable for test names.
295     std::string toString() const;
296 
297     // Returns a string representation of the structure suitable for test descriptions.
298     std::string toDescription() const;
299 };
300 
301 // Returns true if the given float controls features in `toCheck` are all supported.
302 bool isFloatControlsFeaturesSupported(const Context &context,
303                                       const vk::VkPhysicalDeviceFloatControlsProperties &toCheck,
304                                       const char **missingFeature);
305 
306 uint32_t getMinRequiredVulkanVersion(const vk::SpirvVersion version);
307 
308 std::string getVulkanName(const uint32_t version);
309 
310 // Performs a bitwise copy of source to the destination type Dest.
311 template <typename Dest, typename Src>
bitwiseCast(Src source)312 Dest bitwiseCast(Src source)
313 {
314     Dest dest;
315     DE_STATIC_ASSERT(sizeof(source) == sizeof(dest));
316     deMemcpy(&dest, &source, sizeof(dest));
317     return dest;
318 }
319 
320 // Generate and return 64-bit integers.
321 //
322 // Expected count to be at least 16.
323 std::vector<int64_t> getInt64s(de::Random &rnd, const uint32_t count);
324 
325 // Generate and return 32-bit integers.
326 //
327 // Expected count to be at least 16.
328 std::vector<int32_t> getInt32s(de::Random &rnd, const uint32_t count);
329 
330 // Generate and return 16-bit integers.
331 //
332 // Expected count to be at least 8.
333 std::vector<int16_t> getInt16s(de::Random &rnd, const uint32_t count);
334 
335 // Generate and return 8-bit integers.
336 //
337 // Expected count to be at least 8.
338 std::vector<int8_t> getInt8s(de::Random &rnd, const uint32_t count);
339 
340 // Generate and return 64-bit floats
341 //
342 // If includeSpecialFloat16Values is false, random float64 that can be converted to float16 inf/nan/denormal must be excluded
343 // since inf may be clamped, and nan/denormal be flushed without float control features.
344 // And expected count to be at least 14 (numPicks).
345 // Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
346 // And expected count to be at least 24 (numPicks).
347 std::vector<double> getFloat64s(de::Random &rnd, uint32_t count, bool includeSpecialFloat16Values = true);
348 
349 // Generate and return 32-bit floats
350 //
351 // If includeSpecialFloat16Values is false, random float32 that can be converted to float16 inf/nan/denormal must be excluded
352 // since inf may be clamped, and nan/denormal be flushed without float control features.
353 // And expected count to be at least 14 (numPicks).
354 // Otherwise, the first 24 number pairs are manually picked, while the rest are randomly generated.
355 // And expected count to be at least 24 (numPicks).
356 std::vector<float> getFloat32s(de::Random &rnd, uint32_t count, bool includeSpecialFloat16Values = true);
357 
358 // Generate and return 16-bit floats
359 //
360 // If includeSpecialFloat16Values is false, float16 inf/nan/denormal must be excluded since inf may be clamped,
361 // and nan/denormal be flushed without float control features. And expected count to be at least 6 (numPicks).
362 // Otherwise, the first 14 number pairs are manually picked, while the rest are randomly generated.
363 // And expected count to be at least 14 (numPicks).
364 std::vector<deFloat16> getFloat16s(de::Random &rnd, uint32_t count, bool includeSpecialFloat16Values = true);
365 
366 // Generate an OpCapability Shader line.
367 std::string getOpCapabilityShader();
368 
369 // Generate an unused Vertex entry point.
370 std::string getUnusedEntryPoint();
371 
372 // Generate unused decorations for an input/output buffer.
373 std::string getUnusedDecorations(const VariableLocation &location);
374 
375 // Generate unused types and constants, including a buffer type.
376 std::string getUnusedTypesAndConstants();
377 
378 // Generate the declaration of an unused buffer variable.
379 std::string getUnusedBuffer();
380 
381 // Generate the body of an unused function that uses the previous buffer.
382 std::string getUnusedFunctionBody();
383 
384 } // namespace SpirVAssembly
385 } // namespace vkt
386 
387 #endif // _VKTSPVASMUTILS_HPP
388