Merge branch '286-extend-device-feature-limit-validation' into 'master'
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / framework / vulkan / vkGlslToSpirV.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
3  * --------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
18  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
25  *
26  *//*!
27  * \file
28  * \brief GLSL to SPIR-V.
29  *//*--------------------------------------------------------------------*/
30
31 #include "vkGlslToSpirV.hpp"
32 #include "deArrayUtil.hpp"
33 #include "deMemory.h"
34 #include "deClock.h"
35 #include "qpDebugOut.h"
36
37 #if defined(DEQP_HAVE_GLSLANG)
38 #       include "deSingleton.h"
39 #       include "deMutex.hpp"
40
41 #       include "SPIRV/GlslangToSpv.h"
42 #       include "SPIRV/disassemble.h"
43 #       include "SPIRV/doc.h"
44 #       include "glslang/Include/InfoSink.h"
45 #       include "glslang/Include/ShHandle.h"
46 #       include "glslang/MachineIndependent/localintermediate.h"
47 #       include "glslang/Public/ShaderLang.h"
48 #endif
49
50 #if defined(DEQP_HAVE_SPIRV_TOOLS)
51 #       include "libspirv/libspirv.h"
52 #endif
53
54 namespace vk
55 {
56
57 using std::string;
58 using std::vector;
59
60 #if defined(DEQP_HAVE_GLSLANG)
61
62 namespace
63 {
64
65 EShLanguage getGlslangStage (glu::ShaderType type)
66 {
67         static const EShLanguage stageMap[] =
68         {
69                 EShLangVertex,
70                 EShLangFragment,
71                 EShLangGeometry,
72                 EShLangTessControl,
73                 EShLangTessEvaluation,
74                 EShLangCompute,
75         };
76         return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
77 }
78
79 static volatile deSingletonState        s_glslangInitState      = DE_SINGLETON_STATE_NOT_INITIALIZED;
80 static de::Mutex                                        s_glslangLock;
81
82 void initGlslang (void*)
83 {
84         // Main compiler
85         glslang::InitializeProcess();
86
87         // SPIR-V disassembly
88         spv::Parameterize();
89 }
90
91 void prepareGlslang (void)
92 {
93         deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
94 }
95
96 // \todo [2015-06-19 pyry] Specialize these per GLSL version
97
98 // Fail compilation if more members are added to TLimits or TBuiltInResource
99 struct LimitsSizeHelper_s                       { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; };
100 struct BuiltInResourceSizeHelper_s      { int m[83]; LimitsSizeHelper_s l; };
101
102 DE_STATIC_ASSERT(sizeof(TLimits)                        == sizeof(LimitsSizeHelper_s));
103 DE_STATIC_ASSERT(sizeof(TBuiltInResource)       == sizeof(BuiltInResourceSizeHelper_s));
104
105 void getDefaultLimits (TLimits* limits)
106 {
107         limits->nonInductiveForLoops                                    = true;
108         limits->whileLoops                                                              = true;
109         limits->doWhileLoops                                                    = true;
110         limits->generalUniformIndexing                                  = true;
111         limits->generalAttributeMatrixVectorIndexing    = true;
112         limits->generalVaryingIndexing                                  = true;
113         limits->generalSamplerIndexing                                  = true;
114         limits->generalVariableIndexing                                 = true;
115         limits->generalConstantMatrixVectorIndexing             = true;
116 }
117
118 void getDefaultBuiltInResources (TBuiltInResource* builtin)
119 {
120         getDefaultLimits(&builtin->limits);
121
122         builtin->maxLights                                                                      = 32;
123         builtin->maxClipPlanes                                                          = 6;
124         builtin->maxTextureUnits                                                        = 32;
125         builtin->maxTextureCoords                                                       = 32;
126         builtin->maxVertexAttribs                                                       = 64;
127         builtin->maxVertexUniformComponents                                     = 4096;
128         builtin->maxVaryingFloats                                                       = 64;
129         builtin->maxVertexTextureImageUnits                                     = 32;
130         builtin->maxCombinedTextureImageUnits                           = 80;
131         builtin->maxTextureImageUnits                                           = 32;
132         builtin->maxFragmentUniformComponents                           = 4096;
133         builtin->maxDrawBuffers                                                         = 32;
134         builtin->maxVertexUniformVectors                                        = 128;
135         builtin->maxVaryingVectors                                                      = 8;
136         builtin->maxFragmentUniformVectors                                      = 16;
137         builtin->maxVertexOutputVectors                                         = 16;
138         builtin->maxFragmentInputVectors                                        = 15;
139         builtin->minProgramTexelOffset                                          = -8;
140         builtin->maxProgramTexelOffset                                          = 7;
141         builtin->maxClipDistances                                                       = 8;
142         builtin->maxComputeWorkGroupCountX                                      = 65535;
143         builtin->maxComputeWorkGroupCountY                                      = 65535;
144         builtin->maxComputeWorkGroupCountZ                                      = 65535;
145         builtin->maxComputeWorkGroupSizeX                                       = 1024;
146         builtin->maxComputeWorkGroupSizeY                                       = 1024;
147         builtin->maxComputeWorkGroupSizeZ                                       = 64;
148         builtin->maxComputeUniformComponents                            = 1024;
149         builtin->maxComputeTextureImageUnits                            = 16;
150         builtin->maxComputeImageUniforms                                        = 8;
151         builtin->maxComputeAtomicCounters                                       = 8;
152         builtin->maxComputeAtomicCounterBuffers                         = 1;
153         builtin->maxVaryingComponents                                           = 60;
154         builtin->maxVertexOutputComponents                                      = 64;
155         builtin->maxGeometryInputComponents                                     = 64;
156         builtin->maxGeometryOutputComponents                            = 128;
157         builtin->maxFragmentInputComponents                                     = 128;
158         builtin->maxImageUnits                                                          = 8;
159         builtin->maxCombinedImageUnitsAndFragmentOutputs        = 8;
160         builtin->maxCombinedShaderOutputResources                       = 8;
161         builtin->maxImageSamples                                                        = 0;
162         builtin->maxVertexImageUniforms                                         = 0;
163         builtin->maxTessControlImageUniforms                            = 0;
164         builtin->maxTessEvaluationImageUniforms                         = 0;
165         builtin->maxGeometryImageUniforms                                       = 0;
166         builtin->maxFragmentImageUniforms                                       = 8;
167         builtin->maxCombinedImageUniforms                                       = 8;
168         builtin->maxGeometryTextureImageUnits                           = 16;
169         builtin->maxGeometryOutputVertices                                      = 256;
170         builtin->maxGeometryTotalOutputComponents                       = 1024;
171         builtin->maxGeometryUniformComponents                           = 1024;
172         builtin->maxGeometryVaryingComponents                           = 64;
173         builtin->maxTessControlInputComponents                          = 128;
174         builtin->maxTessControlOutputComponents                         = 128;
175         builtin->maxTessControlTextureImageUnits                        = 16;
176         builtin->maxTessControlUniformComponents                        = 1024;
177         builtin->maxTessControlTotalOutputComponents            = 4096;
178         builtin->maxTessEvaluationInputComponents                       = 128;
179         builtin->maxTessEvaluationOutputComponents                      = 128;
180         builtin->maxTessEvaluationTextureImageUnits                     = 16;
181         builtin->maxTessEvaluationUniformComponents                     = 1024;
182         builtin->maxTessPatchComponents                                         = 120;
183         builtin->maxPatchVertices                                                       = 32;
184         builtin->maxTessGenLevel                                                        = 64;
185         builtin->maxViewports                                                           = 16;
186         builtin->maxVertexAtomicCounters                                        = 0;
187         builtin->maxTessControlAtomicCounters                           = 0;
188         builtin->maxTessEvaluationAtomicCounters                        = 0;
189         builtin->maxGeometryAtomicCounters                                      = 0;
190         builtin->maxFragmentAtomicCounters                                      = 8;
191         builtin->maxCombinedAtomicCounters                                      = 8;
192         builtin->maxAtomicCounterBindings                                       = 1;
193         builtin->maxVertexAtomicCounterBuffers                          = 0;
194         builtin->maxTessControlAtomicCounterBuffers                     = 0;
195         builtin->maxTessEvaluationAtomicCounterBuffers          = 0;
196         builtin->maxGeometryAtomicCounterBuffers                        = 0;
197         builtin->maxFragmentAtomicCounterBuffers                        = 1;
198         builtin->maxCombinedAtomicCounterBuffers                        = 1;
199         builtin->maxAtomicCounterBufferSize                                     = 16384;
200         builtin->maxTransformFeedbackBuffers                            = 4;
201         builtin->maxTransformFeedbackInterleavedComponents      = 64;
202         builtin->maxCullDistances                                                       = 8;
203         builtin->maxCombinedClipAndCullDistances                        = 8;
204         builtin->maxSamples                                                                     = 4;
205 };
206
207 } // anonymous
208
209 void glslToSpirV (const glu::ProgramSources& program, std::vector<deUint8>* dst, glu::ShaderProgramInfo* buildInfo)
210 {
211         TBuiltInResource        builtinRes;
212
213         prepareGlslang();
214         getDefaultBuiltInResources(&builtinRes);
215
216         // \note Compiles only first found shader
217         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
218         {
219                 if (!program.sources[shaderType].empty())
220                 {
221                         const de::ScopedLock    compileLock                     (s_glslangLock);
222                         const std::string&              srcText                         = program.sources[shaderType][0];
223                         const char*                             srcPtrs[]                       = { srcText.c_str() };
224                         const int                               srcLengths[]            = { (int)srcText.size() };
225                         vector<deUint32>                spvBlob;
226                         const EShLanguage               shaderStage                     = getGlslangStage(glu::ShaderType(shaderType));
227                         glslang::TShader                shader                          (shaderStage);
228                         glslang::TProgram               program;
229
230                         shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
231                         program.addShader(&shader);
232
233                         {
234                                 const deUint64  compileStartTime        = deGetMicroseconds();
235                                 const int               compileRes                      = shader.parse(&builtinRes, 110, false, (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
236                                 glu::ShaderInfo shaderBuildInfo;
237
238                                 shaderBuildInfo.type                    = (glu::ShaderType)shaderType;
239                                 shaderBuildInfo.source                  = srcText;
240                                 shaderBuildInfo.infoLog                 = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
241                                 shaderBuildInfo.compileTimeUs   = deGetMicroseconds()-compileStartTime;
242                                 shaderBuildInfo.compileOk               = (compileRes != 0);
243
244                                 buildInfo->shaders.push_back(shaderBuildInfo);
245
246                                 if (compileRes == 0)
247                                         TCU_FAIL("Failed to compile shader");
248                         }
249
250                         {
251                                 const deUint64  linkStartTime   = deGetMicroseconds();
252                                 const int               linkRes                 = program.link((EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
253
254                                 buildInfo->program.infoLog              = program.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
255                                 buildInfo->program.linkOk               = (linkRes != 0);
256                                 buildInfo->program.linkTimeUs   = deGetMicroseconds()-linkStartTime;
257
258                                 if (linkRes == 0)
259                                         TCU_FAIL("Failed to link shader");
260                         }
261
262                         {
263                                 const glslang::TIntermediate* const     intermediate    = program.getIntermediate(shaderStage);
264                                 glslang::GlslangToSpv(*intermediate, spvBlob);
265                         }
266
267                         dst->resize(spvBlob.size() * sizeof(deUint32));
268 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
269                         deMemcpy(&(*dst)[0], &spvBlob[0], dst->size());
270 #else
271 #       error "Big-endian not supported"
272 #endif
273
274                         return;
275                 }
276         }
277
278         TCU_THROW(InternalError, "Can't compile empty program");
279 }
280
281 #else // defined(DEQP_HAVE_GLSLANG)
282
283 void glslToSpirV (const glu::ProgramSources&, std::vector<deUint8>*, glu::ShaderProgramInfo*)
284 {
285         TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
286 }
287
288 #endif // defined(DEQP_HAVE_GLSLANG)
289
290 #if defined(DEQP_HAVE_SPIRV_TOOLS)
291 void disassembleSpirV (size_t binarySize, const deUint8* binary, std::ostream* dst)
292 {
293         std::vector<deUint32>   binForDisasm    (binarySize/4);
294
295         DE_ASSERT(binarySize%4 == 0);
296
297 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
298         deMemcpy(&binForDisasm[0], binary, binarySize);
299 #else
300 #       error "Big-endian not supported"
301 #endif
302
303         const spv_context       context         = spvContextCreate();
304         if (!context)
305                 throw std::bad_alloc();
306         spv_text                        text            = DE_NULL;
307         spv_diagnostic          diagnostic;
308         try
309         {
310                 const spv_result_t      error   = spvBinaryToText(context, &binForDisasm[0], binForDisasm.size() , 0, &text, &diagnostic);
311                 TCU_CHECK_INTERNAL(!error);
312                 *dst << text->str;
313         }
314         catch (...)
315         {
316                 spvTextDestroy(text);
317                 spvContextDestroy(context);
318                 throw;
319         }
320         spvTextDestroy(text);
321         spvContextDestroy(context);
322 }
323 #else // defined(DEQP_HAVE_SPIRV_TOOLS)
324
325 void disassembleSpirV (size_t, const deUint8*, std::ostream*)
326 {
327         TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
328 }
329 #endif // defined(DEQP_HAVE_SPIRV_TOOLS)
330
331 } // vk