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