Merge vk-gl-cts/vulkan-cts-1.1.4 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / framework / vulkan / vkShaderToSpirV.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
3  * --------------------
4  *
5  * Copyright (c) 2015 Google 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
21  * \brief Shading language (GLSL/HLSL) to SPIR-V.
22  *//*--------------------------------------------------------------------*/
23
24 #include "vkShaderToSpirV.hpp"
25 #include "deArrayUtil.hpp"
26 #include "deSingleton.h"
27 #include "deMemory.h"
28 #include "deClock.h"
29 #include "qpDebugOut.h"
30
31 #if defined(DEQP_HAVE_GLSLANG)
32 #       include "SPIRV/GlslangToSpv.h"
33 #       include "SPIRV/disassemble.h"
34 #       include "SPIRV/SPVRemapper.h"
35 #       include "SPIRV/doc.h"
36 #       include "glslang/Include/InfoSink.h"
37 #       include "glslang/Include/ShHandle.h"
38 #       include "glslang/MachineIndependent/localintermediate.h"
39 #       include "glslang/Public/ShaderLang.h"
40 #endif
41
42 namespace vk
43 {
44
45 using std::string;
46 using std::vector;
47
48 #if defined(DEQP_HAVE_GLSLANG)
49
50 namespace
51 {
52
53 EShLanguage getGlslangStage (glu::ShaderType type)
54 {
55         static const EShLanguage stageMap[] =
56         {
57                 EShLangVertex,
58                 EShLangFragment,
59                 EShLangGeometry,
60                 EShLangTessControl,
61                 EShLangTessEvaluation,
62                 EShLangCompute,
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 // \todo [2015-06-19 pyry] Specialize these per GLSL version
84
85 // Fail compilation if more members are added to TLimits or TBuiltInResource
86 struct LimitsSizeHelper_s                       { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; };
87 struct BuiltInResourceSizeHelper_s      { int m[92]; LimitsSizeHelper_s l; };
88
89 DE_STATIC_ASSERT(sizeof(TLimits)                        == sizeof(LimitsSizeHelper_s));
90 DE_STATIC_ASSERT(sizeof(TBuiltInResource)       == sizeof(BuiltInResourceSizeHelper_s));
91
92 void getDefaultLimits (TLimits* limits)
93 {
94         limits->nonInductiveForLoops                                    = true;
95         limits->whileLoops                                                              = true;
96         limits->doWhileLoops                                                    = true;
97         limits->generalUniformIndexing                                  = true;
98         limits->generalAttributeMatrixVectorIndexing    = true;
99         limits->generalVaryingIndexing                                  = true;
100         limits->generalSamplerIndexing                                  = true;
101         limits->generalVariableIndexing                                 = true;
102         limits->generalConstantMatrixVectorIndexing             = true;
103 }
104
105 void getDefaultBuiltInResources (TBuiltInResource* builtin)
106 {
107         getDefaultLimits(&builtin->limits);
108
109         builtin->maxLights                                                                      = 32;
110         builtin->maxClipPlanes                                                          = 6;
111         builtin->maxTextureUnits                                                        = 32;
112         builtin->maxTextureCoords                                                       = 32;
113         builtin->maxVertexAttribs                                                       = 64;
114         builtin->maxVertexUniformComponents                                     = 4096;
115         builtin->maxVaryingFloats                                                       = 64;
116         builtin->maxVertexTextureImageUnits                                     = 32;
117         builtin->maxCombinedTextureImageUnits                           = 80;
118         builtin->maxTextureImageUnits                                           = 32;
119         builtin->maxFragmentUniformComponents                           = 4096;
120         builtin->maxDrawBuffers                                                         = 32;
121         builtin->maxVertexUniformVectors                                        = 128;
122         builtin->maxVaryingVectors                                                      = 8;
123         builtin->maxFragmentUniformVectors                                      = 16;
124         builtin->maxVertexOutputVectors                                         = 16;
125         builtin->maxFragmentInputVectors                                        = 15;
126         builtin->minProgramTexelOffset                                          = -8;
127         builtin->maxProgramTexelOffset                                          = 7;
128         builtin->maxClipDistances                                                       = 8;
129         builtin->maxComputeWorkGroupCountX                                      = 65535;
130         builtin->maxComputeWorkGroupCountY                                      = 65535;
131         builtin->maxComputeWorkGroupCountZ                                      = 65535;
132         builtin->maxComputeWorkGroupSizeX                                       = 1024;
133         builtin->maxComputeWorkGroupSizeY                                       = 1024;
134         builtin->maxComputeWorkGroupSizeZ                                       = 64;
135         builtin->maxComputeUniformComponents                            = 1024;
136         builtin->maxComputeTextureImageUnits                            = 16;
137         builtin->maxComputeImageUniforms                                        = 8;
138         builtin->maxComputeAtomicCounters                                       = 8;
139         builtin->maxComputeAtomicCounterBuffers                         = 1;
140         builtin->maxVaryingComponents                                           = 60;
141         builtin->maxVertexOutputComponents                                      = 64;
142         builtin->maxGeometryInputComponents                                     = 64;
143         builtin->maxGeometryOutputComponents                            = 128;
144         builtin->maxFragmentInputComponents                                     = 128;
145         builtin->maxImageUnits                                                          = 8;
146         builtin->maxCombinedImageUnitsAndFragmentOutputs        = 8;
147         builtin->maxCombinedShaderOutputResources                       = 8;
148         builtin->maxImageSamples                                                        = 0;
149         builtin->maxVertexImageUniforms                                         = 0;
150         builtin->maxTessControlImageUniforms                            = 0;
151         builtin->maxTessEvaluationImageUniforms                         = 0;
152         builtin->maxGeometryImageUniforms                                       = 0;
153         builtin->maxFragmentImageUniforms                                       = 8;
154         builtin->maxCombinedImageUniforms                                       = 8;
155         builtin->maxGeometryTextureImageUnits                           = 16;
156         builtin->maxGeometryOutputVertices                                      = 256;
157         builtin->maxGeometryTotalOutputComponents                       = 1024;
158         builtin->maxGeometryUniformComponents                           = 1024;
159         builtin->maxGeometryVaryingComponents                           = 64;
160         builtin->maxTessControlInputComponents                          = 128;
161         builtin->maxTessControlOutputComponents                         = 128;
162         builtin->maxTessControlTextureImageUnits                        = 16;
163         builtin->maxTessControlUniformComponents                        = 1024;
164         builtin->maxTessControlTotalOutputComponents            = 4096;
165         builtin->maxTessEvaluationInputComponents                       = 128;
166         builtin->maxTessEvaluationOutputComponents                      = 128;
167         builtin->maxTessEvaluationTextureImageUnits                     = 16;
168         builtin->maxTessEvaluationUniformComponents                     = 1024;
169         builtin->maxTessPatchComponents                                         = 120;
170         builtin->maxPatchVertices                                                       = 32;
171         builtin->maxTessGenLevel                                                        = 64;
172         builtin->maxViewports                                                           = 16;
173         builtin->maxVertexAtomicCounters                                        = 0;
174         builtin->maxTessControlAtomicCounters                           = 0;
175         builtin->maxTessEvaluationAtomicCounters                        = 0;
176         builtin->maxGeometryAtomicCounters                                      = 0;
177         builtin->maxFragmentAtomicCounters                                      = 8;
178         builtin->maxCombinedAtomicCounters                                      = 8;
179         builtin->maxAtomicCounterBindings                                       = 1;
180         builtin->maxVertexAtomicCounterBuffers                          = 0;
181         builtin->maxTessControlAtomicCounterBuffers                     = 0;
182         builtin->maxTessEvaluationAtomicCounterBuffers          = 0;
183         builtin->maxGeometryAtomicCounterBuffers                        = 0;
184         builtin->maxFragmentAtomicCounterBuffers                        = 1;
185         builtin->maxCombinedAtomicCounterBuffers                        = 1;
186         builtin->maxAtomicCounterBufferSize                                     = 16384;
187         builtin->maxTransformFeedbackBuffers                            = 8;
188         builtin->maxTransformFeedbackInterleavedComponents      = 16382;
189         builtin->maxCullDistances                                                       = 8;
190         builtin->maxCombinedClipAndCullDistances                        = 8;
191         builtin->maxSamples                                                                     = 4;
192         builtin->maxMeshOutputVerticesNV                                        = 256;
193         builtin->maxMeshOutputPrimitivesNV                                      = 256;
194         builtin->maxMeshWorkGroupSizeX_NV                                       = 32;
195         builtin->maxMeshWorkGroupSizeY_NV                                       = 1;
196         builtin->maxMeshWorkGroupSizeZ_NV                                       = 1;
197         builtin->maxTaskWorkGroupSizeX_NV                                       = 32;
198         builtin->maxTaskWorkGroupSizeY_NV                                       = 1;
199         builtin->maxTaskWorkGroupSizeZ_NV                                       = 1;
200         builtin->maxMeshViewCountNV                                                     = 4;
201 };
202
203 int getNumShaderStages (const std::vector<std::string>* sources)
204 {
205         int numShaderStages = 0;
206
207         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
208         {
209                 if (!sources[shaderType].empty())
210                         numShaderStages += 1;
211         }
212
213         return numShaderStages;
214 }
215
216 std::string getShaderStageSource (const std::vector<std::string>* sources, const ShaderBuildOptions buildOptions, glu::ShaderType shaderType)
217 {
218         if (sources[shaderType].size() != 1)
219                 TCU_THROW(InternalError, "Linking multiple compilation units is not supported");
220
221         if ((buildOptions.flags & ShaderBuildOptions::FLAG_USE_STORAGE_BUFFER_STORAGE_CLASS) != 0)
222         {
223                 // Hack to inject #pragma right after first #version statement
224                 std::string src                 = sources[shaderType][0];
225                 size_t          injectPos       = 0;
226
227                 if (de::beginsWith(src, "#version"))
228                         injectPos = src.find('\n') + 1;
229
230                 src.insert(injectPos, "#pragma use_storage_buffer\n");
231
232                 return src;
233         }
234         else
235                 return sources[shaderType][0];
236 }
237
238 EShMessages getCompileFlags (const ShaderBuildOptions& buildOpts, const ShaderLanguage shaderLanguage)
239 {
240         EShMessages             flags   = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
241
242         if ((buildOpts.flags & ShaderBuildOptions::FLAG_ALLOW_RELAXED_OFFSETS) != 0)
243                 flags = (EShMessages)(flags | EShMsgHlslOffsets);
244
245         if (shaderLanguage == SHADER_LANGUAGE_HLSL)
246                 flags = (EShMessages)(flags | EShMsgReadHlsl);
247
248         return flags;
249 }
250
251 } // anonymous
252
253 bool compileShaderToSpirV (const std::vector<std::string>* sources, const ShaderBuildOptions& buildOptions, const ShaderLanguage shaderLanguage, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
254 {
255         TBuiltInResource        builtinRes = {};
256         const EShMessages       compileFlags    = getCompileFlags(buildOptions, shaderLanguage);
257
258         if (buildOptions.targetVersion >= SPIRV_VERSION_LAST)
259                 TCU_THROW(InternalError, "Unsupported SPIR-V target version");
260
261         if (getNumShaderStages(sources) > 1)
262                 TCU_THROW(InternalError, "Linking multiple shader stages into a single SPIR-V binary is not supported");
263
264         prepareGlslang();
265         getDefaultBuiltInResources(&builtinRes);
266
267         // \note Compiles only first found shader
268         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
269         {
270                 if (!sources[shaderType].empty())
271                 {
272                         const std::string&              srcText                         = getShaderStageSource(sources, buildOptions, (glu::ShaderType)shaderType);
273                         const char*                             srcPtrs[]                       = { srcText.c_str() };
274                         const EShLanguage               shaderStage                     = getGlslangStage(glu::ShaderType(shaderType));
275                         glslang::TShader                shader                          (shaderStage);
276                         glslang::TProgram               glslangProgram;
277
278                         shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
279
280                         switch ( buildOptions.targetVersion )
281                         {
282                         case SPIRV_VERSION_1_0:
283                                 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10000);
284                                 break;
285                         case SPIRV_VERSION_1_1:
286                                 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10100);
287                                 break;
288                         case SPIRV_VERSION_1_2:
289                                 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10200);
290                                 break;
291                         case SPIRV_VERSION_1_3:
292                                 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10300);
293                                 break;
294                         default:
295                                 TCU_THROW(InternalError, "Unsupported SPIR-V target version");
296                         }
297
298                         glslangProgram.addShader(&shader);
299
300                         if (shaderLanguage == SHADER_LANGUAGE_HLSL)
301                         {
302                                 // Entry point assumed to be named main.
303                                 shader.setEntryPoint("main");
304                         }
305
306                         {
307                                 const deUint64  compileStartTime        = deGetMicroseconds();
308                                 const int               compileRes                      = shader.parse(&builtinRes, 110, false, compileFlags);
309                                 glu::ShaderInfo shaderBuildInfo;
310
311                                 shaderBuildInfo.type                    = (glu::ShaderType)shaderType;
312                                 shaderBuildInfo.source                  = srcText;
313                                 shaderBuildInfo.infoLog                 = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
314                                 shaderBuildInfo.compileTimeUs   = deGetMicroseconds()-compileStartTime;
315                                 shaderBuildInfo.compileOk               = (compileRes != 0);
316
317                                 buildInfo->shaders.push_back(shaderBuildInfo);
318                         }
319
320                         DE_ASSERT(buildInfo->shaders.size() == 1);
321                         if (buildInfo->shaders[0].compileOk)
322                         {
323                                 const deUint64  linkStartTime   = deGetMicroseconds();
324                                 const int               linkRes                 = glslangProgram.link(compileFlags);
325
326                                 buildInfo->program.infoLog              = glslangProgram.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
327                                 buildInfo->program.linkOk               = (linkRes != 0);
328                                 buildInfo->program.linkTimeUs   = deGetMicroseconds()-linkStartTime;
329                         }
330
331                         if (buildInfo->program.linkOk)
332                         {
333                                 const glslang::TIntermediate* const     intermediate    = glslangProgram.getIntermediate(shaderStage);
334                                 glslang::GlslangToSpv(*intermediate, *dst);
335                         }
336
337                         return buildInfo->program.linkOk;
338                 }
339         }
340
341         TCU_THROW(InternalError, "Can't compile empty program");
342 }
343
344 bool compileGlslToSpirV (const GlslSource& program, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
345 {
346         return compileShaderToSpirV(program.sources, program.buildOptions, program.shaderLanguage, dst, buildInfo);
347 }
348
349 bool compileHlslToSpirV (const HlslSource& program, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
350 {
351         return compileShaderToSpirV(program.sources, program.buildOptions, program.shaderLanguage, dst, buildInfo);
352 }
353
354 void stripSpirVDebugInfo (const size_t numSrcInstrs, const deUint32* srcInstrs, std::vector<deUint32>* dst)
355 {
356         spv::spirvbin_t remapper;
357
358         // glslang operates in-place
359         dst->resize(numSrcInstrs);
360         std::copy(srcInstrs, srcInstrs+numSrcInstrs, dst->begin());
361         remapper.remap(*dst, spv::spirvbin_base_t::STRIP);
362 }
363
364 #else // defined(DEQP_HAVE_GLSLANG)
365
366 bool compileGlslToSpirV (const GlslSource&, std::vector<deUint32>*, glu::ShaderProgramInfo*)
367 {
368         TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
369 }
370
371 bool compileHlslToSpirV (const HlslSource&, std::vector<deUint32>*, glu::ShaderProgramInfo*)
372 {
373         TCU_THROW(NotSupportedError, "HLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
374 }
375
376 void stripSpirVDebugInfo (const size_t, const deUint32*, std::vector<deUint32>*)
377 {
378         TCU_THROW(NotSupportedError, "SPIR-V stripping not supported (DEQP_HAVE_GLSLANG not defined)");
379 }
380
381 #endif // defined(DEQP_HAVE_GLSLANG)
382
383 } // vk