Update glslang
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcSpirvUtils.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group 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  glcSpirvUtils.cpp
21  * \brief Utility functions for using Glslang and Spirv-tools to work with
22  *  SPIR-V shaders.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcSpirvUtils.hpp"
26 #include "deArrayUtil.hpp"
27 #include "deSingleton.h"
28 #include "deStringUtil.hpp"
29 #include "gluContextInfo.hpp"
30 #include "tcuTestLog.hpp"
31
32 #include "SPIRV/GlslangToSpv.h"
33 #include "SPIRV/disassemble.h"
34 #include "SPIRV/doc.h"
35 #include "glslang/MachineIndependent/localintermediate.h"
36 #include "glslang/Public/ShaderLang.h"
37
38 #include "spirv-tools/libspirv.hpp"
39 #include "spirv-tools/optimizer.hpp"
40
41 using namespace glu;
42
43 namespace glc
44 {
45
46 namespace spirvUtils
47 {
48
49 void checkGlSpirvSupported(deqp::Context& m_context)
50 {
51         bool is_at_least_gl_46 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 6)));
52         bool is_arb_gl_spirv   = m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv");
53
54         if ((!is_at_least_gl_46) && (!is_arb_gl_spirv))
55                 TCU_THROW(NotSupportedError, "GL 4.6 or GL_ARB_gl_spirv is not supported");
56 }
57
58 EShLanguage getGlslangStage(glu::ShaderType type)
59 {
60         static const EShLanguage stageMap[] = {
61                 EShLangVertex, EShLangFragment, EShLangGeometry, EShLangTessControl, EShLangTessEvaluation, EShLangCompute,
62         };
63
64         return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
65 }
66
67 static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
68
69 void initGlslang(void*)
70 {
71         // Main compiler
72         glslang::InitializeProcess();
73
74         // SPIR-V disassembly
75         spv::Parameterize();
76 }
77
78 void prepareGlslang(void)
79 {
80         deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
81 }
82
83 void getDefaultLimits(TLimits* limits)
84 {
85         limits->nonInductiveForLoops                             = true;
86         limits->whileLoops                                                       = true;
87         limits->doWhileLoops                                             = true;
88         limits->generalUniformIndexing                           = true;
89         limits->generalAttributeMatrixVectorIndexing = true;
90         limits->generalVaryingIndexing                           = true;
91         limits->generalSamplerIndexing                           = true;
92         limits->generalVariableIndexing                          = true;
93         limits->generalConstantMatrixVectorIndexing  = true;
94 }
95
96 void getDefaultBuiltInResources(TBuiltInResource* builtin)
97 {
98         getDefaultLimits(&builtin->limits);
99
100         builtin->maxLights                                                                 = 32;
101         builtin->maxClipPlanes                                                     = 6;
102         builtin->maxTextureUnits                                                   = 32;
103         builtin->maxTextureCoords                                                  = 32;
104         builtin->maxVertexAttribs                                                  = 64;
105         builtin->maxVertexUniformComponents                                = 4096;
106         builtin->maxVaryingFloats                                                  = 64;
107         builtin->maxVertexTextureImageUnits                                = 32;
108         builtin->maxCombinedTextureImageUnits                      = 80;
109         builtin->maxTextureImageUnits                                      = 32;
110         builtin->maxFragmentUniformComponents                      = 4096;
111         builtin->maxDrawBuffers                                                    = 32;
112         builtin->maxVertexUniformVectors                                   = 128;
113         builtin->maxVaryingVectors                                                 = 8;
114         builtin->maxFragmentUniformVectors                                 = 16;
115         builtin->maxVertexOutputVectors                                    = 16;
116         builtin->maxFragmentInputVectors                                   = 15;
117         builtin->minProgramTexelOffset                                     = -8;
118         builtin->maxProgramTexelOffset                                     = 7;
119         builtin->maxClipDistances                                                  = 8;
120         builtin->maxComputeWorkGroupCountX                                 = 65535;
121         builtin->maxComputeWorkGroupCountY                                 = 65535;
122         builtin->maxComputeWorkGroupCountZ                                 = 65535;
123         builtin->maxComputeWorkGroupSizeX                                  = 1024;
124         builtin->maxComputeWorkGroupSizeY                                  = 1024;
125         builtin->maxComputeWorkGroupSizeZ                                  = 64;
126         builtin->maxComputeUniformComponents                       = 1024;
127         builtin->maxComputeTextureImageUnits                       = 16;
128         builtin->maxComputeImageUniforms                                   = 8;
129         builtin->maxComputeAtomicCounters                                  = 8;
130         builtin->maxComputeAtomicCounterBuffers                    = 1;
131         builtin->maxVaryingComponents                                      = 60;
132         builtin->maxVertexOutputComponents                                 = 64;
133         builtin->maxGeometryInputComponents                                = 64;
134         builtin->maxGeometryOutputComponents                       = 128;
135         builtin->maxFragmentInputComponents                                = 128;
136         builtin->maxImageUnits                                                     = 8;
137         builtin->maxCombinedImageUnitsAndFragmentOutputs   = 8;
138         builtin->maxCombinedShaderOutputResources                  = 8;
139         builtin->maxImageSamples                                                   = 0;
140         builtin->maxVertexImageUniforms                                    = 0;
141         builtin->maxTessControlImageUniforms                       = 0;
142         builtin->maxTessEvaluationImageUniforms                    = 0;
143         builtin->maxGeometryImageUniforms                                  = 0;
144         builtin->maxFragmentImageUniforms                                  = 8;
145         builtin->maxCombinedImageUniforms                                  = 8;
146         builtin->maxGeometryTextureImageUnits                      = 16;
147         builtin->maxGeometryOutputVertices                                 = 256;
148         builtin->maxGeometryTotalOutputComponents                  = 1024;
149         builtin->maxGeometryUniformComponents                      = 1024;
150         builtin->maxGeometryVaryingComponents                      = 64;
151         builtin->maxTessControlInputComponents                     = 128;
152         builtin->maxTessControlOutputComponents                    = 128;
153         builtin->maxTessControlTextureImageUnits                   = 16;
154         builtin->maxTessControlUniformComponents                   = 1024;
155         builtin->maxTessControlTotalOutputComponents       = 4096;
156         builtin->maxTessEvaluationInputComponents                  = 128;
157         builtin->maxTessEvaluationOutputComponents                 = 128;
158         builtin->maxTessEvaluationTextureImageUnits                = 16;
159         builtin->maxTessEvaluationUniformComponents                = 1024;
160         builtin->maxTessPatchComponents                                    = 120;
161         builtin->maxPatchVertices                                                  = 32;
162         builtin->maxTessGenLevel                                                   = 64;
163         builtin->maxViewports                                                      = 16;
164         builtin->maxVertexAtomicCounters                                   = 0;
165         builtin->maxTessControlAtomicCounters                      = 0;
166         builtin->maxTessEvaluationAtomicCounters                   = 0;
167         builtin->maxGeometryAtomicCounters                                 = 0;
168         builtin->maxFragmentAtomicCounters                                 = 8;
169         builtin->maxCombinedAtomicCounters                                 = 8;
170         builtin->maxAtomicCounterBindings                                  = 1;
171         builtin->maxVertexAtomicCounterBuffers                     = 0;
172         builtin->maxTessControlAtomicCounterBuffers                = 0;
173         builtin->maxTessEvaluationAtomicCounterBuffers   = 0;
174         builtin->maxGeometryAtomicCounterBuffers                   = 0;
175         builtin->maxFragmentAtomicCounterBuffers                   = 1;
176         builtin->maxCombinedAtomicCounterBuffers                   = 1;
177         builtin->maxAtomicCounterBufferSize                                = 16384;
178         builtin->maxTransformFeedbackBuffers                       = 4;
179         builtin->maxTransformFeedbackInterleavedComponents = 64;
180         builtin->maxCullDistances                                                  = 8;
181         builtin->maxCombinedClipAndCullDistances                   = 8;
182         builtin->maxSamples                                                                = 4;
183         builtin->maxMeshOutputVerticesNV                                   = 256;
184         builtin->maxMeshOutputPrimitivesNV                                 = 256;
185         builtin->maxMeshWorkGroupSizeX_NV                                  = 32;
186         builtin->maxMeshWorkGroupSizeY_NV                                  = 1;
187         builtin->maxMeshWorkGroupSizeZ_NV                                  = 1;
188         builtin->maxTaskWorkGroupSizeX_NV                                  = 32;
189         builtin->maxTaskWorkGroupSizeY_NV                                  = 1;
190         builtin->maxTaskWorkGroupSizeZ_NV                                  = 1;
191         builtin->maxMeshViewCountNV                                                = 4;
192         builtin->maxDualSourceDrawBuffersEXT                       = 1;
193 };
194
195 glslang::EShTargetLanguageVersion getSpirvTargetVersion(SpirvVersion version)
196 {
197     switch(version)
198     {
199     default:
200         DE_FATAL("unhandled SPIRV target version");
201         // fall-through
202     case SPIRV_VERSION_1_0:
203         return glslang::EShTargetSpv_1_0;
204     case SPIRV_VERSION_1_1:
205         return glslang::EShTargetSpv_1_1;
206     case SPIRV_VERSION_1_2:
207         return glslang::EShTargetSpv_1_2;
208     case SPIRV_VERSION_1_3:
209         return glslang::EShTargetSpv_1_3;
210     }
211 }
212
213 bool compileGlslToSpirV(tcu::TestLog& log, std::string source, glu::ShaderType type, ShaderBinaryDataType* dst, SpirvVersion version)
214 {
215         TBuiltInResource builtinRes;
216
217         prepareGlslang();
218         getDefaultBuiltInResources(&builtinRes);
219
220         const EShLanguage shaderStage = getGlslangStage(type);
221
222         glslang::TShader  shader(shaderStage);
223         glslang::TProgram program;
224
225         const char* src[] = { source.c_str() };
226
227         shader.setStrings(src, 1);
228         shader.setEnvTarget(glslang::EshTargetSpv, getSpirvTargetVersion(version));
229         program.addShader(&shader);
230
231         const int compileRes = shader.parse(&builtinRes, 100, false, EShMsgSpvRules);
232         if (compileRes != 0)
233         {
234                 const int linkRes = program.link(EShMsgSpvRules);
235
236                 if (linkRes != 0)
237                 {
238                         const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
239                         glslang::GlslangToSpv(*intermediate, *dst);
240
241                         return true;
242                 }
243                 else
244                 {
245                         log << tcu::TestLog::Message << "Program linking error:\n"
246                                 << program.getInfoLog() << "\n"
247                                 << "Source:\n"
248                                 << source << "\n"
249                                 << tcu::TestLog::EndMessage;
250                 }
251         }
252         else
253         {
254                 log << tcu::TestLog::Message << "Shader compilation error:\n"
255                         << shader.getInfoLog() << "\n"
256                         << "Source:\n"
257                         << source << "\n"
258                         << tcu::TestLog::EndMessage;
259         }
260
261         return false;
262 }
263
264 void consumer(spv_message_level_t, const char*, const spv_position_t&, const char* m)
265 {
266         std::cerr << "error: " << m << std::endl;
267 }
268
269 void spirvAssemble(ShaderBinaryDataType& dst, const std::string& src)
270 {
271         spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);
272
273         core.SetMessageConsumer(consumer);
274
275         if (!core.Assemble(src, &dst))
276                 TCU_THROW(InternalError, "Failed to assemble Spir-V source.");
277 }
278
279 void spirvDisassemble(std::string& dst, const ShaderBinaryDataType& src)
280 {
281         spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);
282
283         core.SetMessageConsumer(consumer);
284
285         if (!core.Disassemble(src, &dst))
286                 TCU_THROW(InternalError, "Failed to disassemble Spir-V module.");
287 }
288
289 bool spirvValidate(ShaderBinaryDataType& dst, bool throwOnError)
290 {
291         spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);
292
293         if (throwOnError)
294                 core.SetMessageConsumer(consumer);
295
296         if (!core.Validate(dst))
297         {
298                 if (throwOnError)
299                         TCU_THROW(InternalError, "Failed to validate Spir-V module.");
300                 return false;
301         }
302
303         return true;
304 }
305
306 ShaderBinary makeSpirV(tcu::TestLog& log, ShaderSource source, SpirvVersion version)
307 {
308         ShaderBinary binary;
309
310         if (!spirvUtils::compileGlslToSpirV(log, source.source, source.shaderType, &binary.binary, version))
311                 TCU_THROW(InternalError, "Failed to convert GLSL to Spir-V");
312
313         binary << source.shaderType << "main";
314
315         return binary;
316 }
317
318 /** Verifying if GLSL to SpirV mapping was performed correctly
319  *
320  * @param glslSource       GLSL shader template
321  * @param spirVSource      SpirV disassembled source
322  * @param mappings         Glsl to SpirV mappings vector
323  * @param anyOf            any occurence indicator
324  *
325  * @return true if GLSL code occurs as many times as all of SpirV code for each mapping if anyOf is false
326  *         or true if SpirV code occurs at least once if GLSL code found, false otherwise.
327  **/
328 bool verifyMappings(std::string glslSource, std::string spirVSource, SpirVMapping& mappings, bool anyOf)
329 {
330         std::vector<std::string> spirVSourceLines = de::splitString(spirVSource, '\n');
331
332         // Iterate through all glsl functions
333         for (SpirVMapping::iterator it = mappings.begin(); it != mappings.end(); it++)
334         {
335                 int glslCodeCount  = 0;
336                 int spirVCodeCount = 0;
337
338                 // To avoid finding functions with similar names (ie. "cos", "acos", "cosh")
339                 // add characteristic characters that delimits finding results
340                 std::string glslCode = it->first;
341
342                 // Count GLSL code occurrences in GLSL source
343                 size_t codePosition = glslSource.find(glslCode);
344                 while (codePosition != std::string::npos)
345                 {
346                         glslCodeCount++;
347                         codePosition = glslSource.find(glslCode, codePosition + 1);
348                 }
349
350                 if (glslCodeCount > 0)
351                 {
352                         // Count all SpirV code variants occurrences in SpirV source
353                         for (int s = 0; s < (signed)it->second.size(); ++s)
354                         {
355                                 std::vector<std::string> spirVCodes = de::splitString(it->second[s], ' ');
356
357                                 for (int v = 0; v < (signed)spirVSourceLines.size(); ++v)
358                                 {
359                                         std::vector<std::string> spirVLineCodes = de::splitString(spirVSourceLines[v], ' ');
360
361                                         bool matchAll = true;
362                                         for (int j = 0; j < (signed)spirVCodes.size(); ++j)
363                                         {
364                                                 bool match = false;
365                                                 for (int i = 0; i < (signed)spirVLineCodes.size(); ++i)
366                                                 {
367                                                         if (spirVLineCodes[i] == spirVCodes[j])
368                                                                 match = true;
369                                                 }
370
371                                                 matchAll = matchAll && match;
372                                         }
373
374                                         if (matchAll)
375                                                 spirVCodeCount++;
376                                 }
377                         }
378
379                         // Check if both counts match
380                         if (anyOf && (glslCodeCount > 0 && spirVCodeCount == 0))
381                                 return false;
382                         else if (!anyOf && glslCodeCount != spirVCodeCount)
383                                 return false;
384                 }
385         }
386
387         return true;
388 }
389
390 } // namespace spirvUtils
391
392 } // namespace glc