2e871ef2ee23251df4404476490b3a5f291ec367
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmComputeShaderTestUtil.hpp
1 #ifndef _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP
2 #define _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2015 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 Compute Shader Based Test Case Utility Structs/Functions
24  *//*--------------------------------------------------------------------*/
25
26 #include "deDefs.h"
27 #include "deFloat16.h"
28 #include "deRandom.hpp"
29 #include "deSharedPtr.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuVector.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vktSpvAsmUtils.hpp"
34
35 #include <string>
36 #include <vector>
37 #include <map>
38
39 using namespace vk;
40
41 namespace vkt
42 {
43 namespace SpirVAssembly
44 {
45
46 enum OpAtomicType
47 {
48         OPATOMIC_IADD = 0,
49         OPATOMIC_ISUB,
50         OPATOMIC_IINC,
51         OPATOMIC_IDEC,
52         OPATOMIC_LOAD,
53         OPATOMIC_STORE,
54         OPATOMIC_COMPEX,
55
56         OPATOMIC_LAST
57 };
58
59 enum BufferType
60 {
61         BUFFERTYPE_INPUT = 0,
62         BUFFERTYPE_EXPECTED,
63
64         BUFFERTYPE_LAST
65 };
66
67 static void fillRandomScalars (de::Random& rnd, deInt32 minValue, deInt32 maxValue, deInt32* dst, deInt32 numValues)
68 {
69         for (int i = 0; i < numValues; i++)
70                 dst[i] = rnd.getInt(minValue, maxValue);
71 }
72
73 typedef de::MovePtr<vk::Allocation>                     AllocationMp;
74 typedef de::SharedPtr<vk::Allocation>           AllocationSp;
75
76 /*--------------------------------------------------------------------*//*!
77  * \brief Abstract class for an input/output storage buffer object
78  *//*--------------------------------------------------------------------*/
79 class BufferInterface
80 {
81 public:
82         virtual                         ~BufferInterface        (void)                          {}
83
84         virtual void            getBytes                        (std::vector<deUint8>& bytes) const = 0;
85         virtual size_t          getByteSize                     (void) const = 0;
86 };
87
88 typedef de::SharedPtr<BufferInterface>          BufferSp;
89
90 /*--------------------------------------------------------------------*//*!
91 * \brief Concrete class for an input/output storage buffer object used for OpAtomic tests
92 *//*--------------------------------------------------------------------*/
93 class OpAtomicBuffer : public BufferInterface
94 {
95 public:
96                                                 OpAtomicBuffer          (const deUint32 numInputElements, const deUint32 numOuptutElements, const OpAtomicType opAtomic, const BufferType type)
97                                                         : m_numInputElements    (numInputElements)
98                                                         , m_numOutputElements   (numOuptutElements)
99                                                         , m_opAtomic                    (opAtomic)
100                                                         , m_type                                (type)
101                                                 {}
102
103         void getBytes (std::vector<deUint8>& bytes) const
104         {
105                 std::vector<deInt32>    inputInts       (m_numInputElements, 0);
106                 de::Random                              rnd                     (m_opAtomic);
107
108                 fillRandomScalars(rnd, 1, 100, &inputInts.front(), m_numInputElements);
109
110                 // Return input values as is
111                 if (m_type == BUFFERTYPE_INPUT)
112                 {
113                         size_t                                  inputSize       = m_numInputElements * sizeof(deInt32);
114
115                         bytes.resize(inputSize);
116                         deMemcpy(&bytes.front(), &inputInts.front(), inputSize);
117                 }
118                 // Calculate expected output values
119                 else if (m_type == BUFFERTYPE_EXPECTED)
120                 {
121                         size_t                                  outputSize      = m_numOutputElements * sizeof(deInt32);
122                         bytes.resize(outputSize, 0xffu);
123
124                         for (size_t ndx = 0; ndx < m_numInputElements; ndx++)
125                         {
126                                 deInt32* const bytesAsInt = reinterpret_cast<deInt32* const>(&bytes.front());
127
128                                 switch (m_opAtomic)
129                                 {
130                                         case OPATOMIC_IADD:             bytesAsInt[0] += inputInts[ndx];                                                break;
131                                         case OPATOMIC_ISUB:             bytesAsInt[0] -= inputInts[ndx];                                                break;
132                                         case OPATOMIC_IINC:             bytesAsInt[0]++;                                                                                break;
133                                         case OPATOMIC_IDEC:             bytesAsInt[0]--;                                                                                break;
134                                         case OPATOMIC_LOAD:             bytesAsInt[ndx] = inputInts[ndx];                                               break;
135                                         case OPATOMIC_STORE:    bytesAsInt[ndx] = inputInts[ndx];                                               break;
136                                         case OPATOMIC_COMPEX:   bytesAsInt[ndx] = (inputInts[ndx] % 2) == 0 ? -1 : 1;   break;
137                                         default:                                DE_FATAL("Unknown OpAtomic type");
138                                 }
139                         }
140                 }
141                 else
142                         DE_FATAL("Unknown buffer type");
143         }
144
145         size_t getByteSize (void) const
146         {
147                 switch (m_type)
148                 {
149                         case BUFFERTYPE_INPUT:
150                                 return m_numInputElements * sizeof(deInt32);
151                         case BUFFERTYPE_EXPECTED:
152                                 return m_numOutputElements * sizeof(deInt32);
153                         default:
154                                 DE_FATAL("Unknown buffer type");
155                                 return 0;
156                 }
157         }
158
159 private:
160         const deUint32          m_numInputElements;
161         const deUint32          m_numOutputElements;
162         const OpAtomicType      m_opAtomic;
163         const BufferType        m_type;
164 };
165
166 /*--------------------------------------------------------------------*//*!
167  * \brief Concrete class for an input/output storage buffer object
168  *//*--------------------------------------------------------------------*/
169 template<typename E>
170 class Buffer : public BufferInterface
171 {
172 public:
173                                                 Buffer                          (const std::vector<E>& elements)
174                                                         : m_elements(elements)
175                                                 {}
176
177         void getBytes (std::vector<deUint8>& bytes) const
178         {
179                 const size_t size = m_elements.size() * sizeof(E);
180                 bytes.resize(size);
181                 deMemcpy(&bytes.front(), &m_elements.front(), size);
182         }
183
184         size_t getByteSize (void) const
185         {
186                 return m_elements.size() * sizeof(E);
187         }
188
189 private:
190         std::vector<E>          m_elements;
191 };
192
193 DE_STATIC_ASSERT(sizeof(tcu::Vec4) == 4 * sizeof(float));
194
195 typedef Buffer<float>           Float32Buffer;
196 typedef Buffer<deFloat16>       Float16Buffer;
197 typedef Buffer<deInt64>         Int64Buffer;
198 typedef Buffer<deInt32>         Int32Buffer;
199 typedef Buffer<deInt16>         Int16Buffer;
200 typedef Buffer<tcu::Vec4>       Vec4Buffer;
201
202 typedef bool (*ComputeVerifyIOFunc) (const std::vector<BufferSp>&               inputs,
203                                                                          const std::vector<AllocationSp>&       outputAllocations,
204                                                                          const std::vector<BufferSp>&           expectedOutputs,
205                                                                          tcu::TestLog&                                          log);
206
207 typedef bool (*ComputeVerifyBinaryFunc) (const ProgramBinary&   binary);
208
209 /*--------------------------------------------------------------------*//*!
210  * \brief Specification for a compute shader.
211  *
212  * This struct bundles SPIR-V assembly code, input and expected output
213  * together.
214  *//*--------------------------------------------------------------------*/
215 struct ComputeShaderSpec
216 {
217         std::string                                                             assembly;
218         std::string                                                             entryPoint;
219         std::vector<BufferSp>                                   inputs;
220         // Mapping from input index (in the inputs field) to the descriptor type.
221         std::map<deUint32, VkDescriptorType>    inputTypes;
222         std::vector<BufferSp>                                   outputs;
223         tcu::IVec3                                                              numWorkGroups;
224         std::vector<deUint32>                                   specConstants;
225         BufferSp                                                                pushConstants;
226         std::vector<std::string>                                extensions;
227         VulkanFeatures                                                  requestedVulkanFeatures;
228         qpTestResult                                                    failResult;
229         std::string                                                             failMessage;
230         // If null, a default verification will be performed by comparing the memory pointed to by outputAllocations
231         // and the contents of expectedOutputs. Otherwise the function pointed to by verifyIO will be called.
232         // If true is returned, then the test case is assumed to have passed, if false is returned, then the test
233         // case is assumed to have failed. Exact meaning of failure can be customized with failResult.
234         ComputeVerifyIOFunc                                             verifyIO;
235         ComputeVerifyBinaryFunc                                 verifyBinary;
236         SpirvVersion                                                    spirvVersion;
237
238                                                                                         ComputeShaderSpec (void)
239                                                                                                 : entryPoint                                    ("main")
240                                                                                                 , pushConstants                                 (DE_NULL)
241                                                                                                 , requestedVulkanFeatures               ()
242                                                                                                 , failResult                                    (QP_TEST_RESULT_FAIL)
243                                                                                                 , failMessage                                   ("Output doesn't match with expected")
244                                                                                                 , verifyIO                                              (DE_NULL)
245                                                                                                 , verifyBinary                                  (DE_NULL)
246                                                                                                 , spirvVersion                                  (SPIRV_VERSION_1_0)
247                                                                                         {}
248 };
249
250 /*--------------------------------------------------------------------*//*!
251  * \brief Helper functions for SPIR-V assembly shared by various tests
252  *//*--------------------------------------------------------------------*/
253
254 const char* getComputeAsmShaderPreamble                         (void);
255 std::string getComputeAsmCommonTypes                            (std::string blockStorageClass = "Uniform");
256 const char*     getComputeAsmCommonInt64Types                   (void);
257
258 /*--------------------------------------------------------------------*//*!
259  * Declares two uniform variables (indata, outdata) of type
260  * "struct { float[] }". Depends on type "f32arr" (for "float[]").
261  *//*--------------------------------------------------------------------*/
262 const char* getComputeAsmInputOutputBuffer                      (void);
263 /*--------------------------------------------------------------------*//*!
264  * Declares buffer type and layout for uniform variables indata and
265  * outdata. Both of them are SSBO bounded to descriptor set 0.
266  * indata is at binding point 0, while outdata is at 1.
267  *//*--------------------------------------------------------------------*/
268 const char* getComputeAsmInputOutputBufferTraits        (void);
269
270 } // SpirVAssembly
271 } // vkt
272
273 #endif // _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP