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 GLSL to SPIR-V.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vkGlslToSpirV.hpp"
25 #include "deArrayUtil.hpp"
26 #include "deMutex.hpp"
27 #include "deSingleton.h"
28 #include "deMemory.h"
29 #include "deClock.h"
30 #include "qpDebugOut.h"
31
32 #if defined(DEQP_HAVE_GLSLANG)
33 # include "SPIRV/GlslangToSpv.h"
34 # include "SPIRV/disassemble.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
getGlslangStage(glu::ShaderType type)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 static de::Mutex s_glslangLock;
69
initGlslang(void *)70 void initGlslang (void*)
71 {
72 // Main compiler
73 glslang::InitializeProcess();
74
75 // SPIR-V disassembly
76 spv::Parameterize();
77 }
78
prepareGlslang(void)79 void prepareGlslang (void)
80 {
81 deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
82 }
83
84 // \todo [2015-06-19 pyry] Specialize these per GLSL version
85
86 // Fail compilation if more members are added to TLimits or TBuiltInResource
87 struct LimitsSizeHelper_s { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; };
88 struct BuiltInResourceSizeHelper_s { int m[83]; LimitsSizeHelper_s l; };
89
90 DE_STATIC_ASSERT(sizeof(TLimits) == sizeof(LimitsSizeHelper_s));
91 DE_STATIC_ASSERT(sizeof(TBuiltInResource) == sizeof(BuiltInResourceSizeHelper_s));
92
getDefaultLimits(TLimits * limits)93 void getDefaultLimits (TLimits* limits)
94 {
95 limits->nonInductiveForLoops = true;
96 limits->whileLoops = true;
97 limits->doWhileLoops = true;
98 limits->generalUniformIndexing = true;
99 limits->generalAttributeMatrixVectorIndexing = true;
100 limits->generalVaryingIndexing = true;
101 limits->generalSamplerIndexing = true;
102 limits->generalVariableIndexing = true;
103 limits->generalConstantMatrixVectorIndexing = true;
104 }
105
getDefaultBuiltInResources(TBuiltInResource * builtin)106 void getDefaultBuiltInResources (TBuiltInResource* builtin)
107 {
108 getDefaultLimits(&builtin->limits);
109
110 builtin->maxLights = 32;
111 builtin->maxClipPlanes = 6;
112 builtin->maxTextureUnits = 32;
113 builtin->maxTextureCoords = 32;
114 builtin->maxVertexAttribs = 64;
115 builtin->maxVertexUniformComponents = 4096;
116 builtin->maxVaryingFloats = 64;
117 builtin->maxVertexTextureImageUnits = 32;
118 builtin->maxCombinedTextureImageUnits = 80;
119 builtin->maxTextureImageUnits = 32;
120 builtin->maxFragmentUniformComponents = 4096;
121 builtin->maxDrawBuffers = 32;
122 builtin->maxVertexUniformVectors = 128;
123 builtin->maxVaryingVectors = 8;
124 builtin->maxFragmentUniformVectors = 16;
125 builtin->maxVertexOutputVectors = 16;
126 builtin->maxFragmentInputVectors = 15;
127 builtin->minProgramTexelOffset = -8;
128 builtin->maxProgramTexelOffset = 7;
129 builtin->maxClipDistances = 8;
130 builtin->maxComputeWorkGroupCountX = 65535;
131 builtin->maxComputeWorkGroupCountY = 65535;
132 builtin->maxComputeWorkGroupCountZ = 65535;
133 builtin->maxComputeWorkGroupSizeX = 1024;
134 builtin->maxComputeWorkGroupSizeY = 1024;
135 builtin->maxComputeWorkGroupSizeZ = 64;
136 builtin->maxComputeUniformComponents = 1024;
137 builtin->maxComputeTextureImageUnits = 16;
138 builtin->maxComputeImageUniforms = 8;
139 builtin->maxComputeAtomicCounters = 8;
140 builtin->maxComputeAtomicCounterBuffers = 1;
141 builtin->maxVaryingComponents = 60;
142 builtin->maxVertexOutputComponents = 64;
143 builtin->maxGeometryInputComponents = 64;
144 builtin->maxGeometryOutputComponents = 128;
145 builtin->maxFragmentInputComponents = 128;
146 builtin->maxImageUnits = 8;
147 builtin->maxCombinedImageUnitsAndFragmentOutputs = 8;
148 builtin->maxCombinedShaderOutputResources = 8;
149 builtin->maxImageSamples = 0;
150 builtin->maxVertexImageUniforms = 0;
151 builtin->maxTessControlImageUniforms = 0;
152 builtin->maxTessEvaluationImageUniforms = 0;
153 builtin->maxGeometryImageUniforms = 0;
154 builtin->maxFragmentImageUniforms = 8;
155 builtin->maxCombinedImageUniforms = 8;
156 builtin->maxGeometryTextureImageUnits = 16;
157 builtin->maxGeometryOutputVertices = 256;
158 builtin->maxGeometryTotalOutputComponents = 1024;
159 builtin->maxGeometryUniformComponents = 1024;
160 builtin->maxGeometryVaryingComponents = 64;
161 builtin->maxTessControlInputComponents = 128;
162 builtin->maxTessControlOutputComponents = 128;
163 builtin->maxTessControlTextureImageUnits = 16;
164 builtin->maxTessControlUniformComponents = 1024;
165 builtin->maxTessControlTotalOutputComponents = 4096;
166 builtin->maxTessEvaluationInputComponents = 128;
167 builtin->maxTessEvaluationOutputComponents = 128;
168 builtin->maxTessEvaluationTextureImageUnits = 16;
169 builtin->maxTessEvaluationUniformComponents = 1024;
170 builtin->maxTessPatchComponents = 120;
171 builtin->maxPatchVertices = 32;
172 builtin->maxTessGenLevel = 64;
173 builtin->maxViewports = 16;
174 builtin->maxVertexAtomicCounters = 0;
175 builtin->maxTessControlAtomicCounters = 0;
176 builtin->maxTessEvaluationAtomicCounters = 0;
177 builtin->maxGeometryAtomicCounters = 0;
178 builtin->maxFragmentAtomicCounters = 8;
179 builtin->maxCombinedAtomicCounters = 8;
180 builtin->maxAtomicCounterBindings = 1;
181 builtin->maxVertexAtomicCounterBuffers = 0;
182 builtin->maxTessControlAtomicCounterBuffers = 0;
183 builtin->maxTessEvaluationAtomicCounterBuffers = 0;
184 builtin->maxGeometryAtomicCounterBuffers = 0;
185 builtin->maxFragmentAtomicCounterBuffers = 1;
186 builtin->maxCombinedAtomicCounterBuffers = 1;
187 builtin->maxAtomicCounterBufferSize = 16384;
188 builtin->maxTransformFeedbackBuffers = 4;
189 builtin->maxTransformFeedbackInterleavedComponents = 64;
190 builtin->maxCullDistances = 8;
191 builtin->maxCombinedClipAndCullDistances = 8;
192 builtin->maxSamples = 4;
193 };
194
195 } // anonymous
196
getNumShaderStages(const glu::ProgramSources & program)197 int getNumShaderStages (const glu::ProgramSources& program)
198 {
199 int numShaderStages = 0;
200
201 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
202 {
203 if (!program.sources[shaderType].empty())
204 numShaderStages += 1;
205 }
206
207 return numShaderStages;
208 }
209
compileGlslToSpirV(const glu::ProgramSources & program,std::vector<deUint32> * dst,glu::ShaderProgramInfo * buildInfo)210 bool compileGlslToSpirV (const glu::ProgramSources& program, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
211 {
212 TBuiltInResource builtinRes;
213
214 if (getNumShaderStages(program) > 1)
215 TCU_THROW(InternalError, "Linking multiple shader stages into a single SPIR-V binary is not supported");
216
217 prepareGlslang();
218 getDefaultBuiltInResources(&builtinRes);
219
220 // \note Compiles only first found shader
221 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
222 {
223 if (!program.sources[shaderType].empty())
224 {
225 const de::ScopedLock compileLock (s_glslangLock);
226 const std::string& srcText = program.sources[shaderType][0];
227 const char* srcPtrs[] = { srcText.c_str() };
228 const int srcLengths[] = { (int)srcText.size() };
229 const EShLanguage shaderStage = getGlslangStage(glu::ShaderType(shaderType));
230 glslang::TShader shader (shaderStage);
231 glslang::TProgram program;
232
233 shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
234 program.addShader(&shader);
235
236 {
237 const deUint64 compileStartTime = deGetMicroseconds();
238 const int compileRes = shader.parse(&builtinRes, 110, false, (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
239 glu::ShaderInfo shaderBuildInfo;
240
241 shaderBuildInfo.type = (glu::ShaderType)shaderType;
242 shaderBuildInfo.source = srcText;
243 shaderBuildInfo.infoLog = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
244 shaderBuildInfo.compileTimeUs = deGetMicroseconds()-compileStartTime;
245 shaderBuildInfo.compileOk = (compileRes != 0);
246
247 buildInfo->shaders.push_back(shaderBuildInfo);
248 }
249
250 DE_ASSERT(buildInfo->shaders.size() == 1);
251 if (buildInfo->shaders[0].compileOk)
252 {
253 const deUint64 linkStartTime = deGetMicroseconds();
254 const int linkRes = program.link((EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
255
256 buildInfo->program.infoLog = program.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
257 buildInfo->program.linkOk = (linkRes != 0);
258 buildInfo->program.linkTimeUs = deGetMicroseconds()-linkStartTime;
259 }
260
261 if (buildInfo->program.linkOk)
262 {
263 const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
264 glslang::GlslangToSpv(*intermediate, *dst);
265 }
266
267 return buildInfo->program.linkOk;
268 }
269 }
270
271 TCU_THROW(InternalError, "Can't compile empty program");
272 }
273
274 #else // defined(DEQP_HAVE_GLSLANG)
275
compileGlslToSpirV(const glu::ProgramSources &,std::vector<deUint32> *,glu::ShaderProgramInfo *)276 bool compileGlslToSpirV (const glu::ProgramSources&, std::vector<deUint32>*, glu::ShaderProgramInfo*)
277 {
278 TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
279 }
280
281 #endif // defined(DEQP_HAVE_GLSLANG)
282
283 } // vk
284