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
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
initGlslang(void *)69 void initGlslang (void*)
70 {
71 // Main compiler
72 glslang::InitializeProcess();
73
74 // SPIR-V disassembly
75 spv::Parameterize();
76 }
77
prepareGlslang(void)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
getDefaultLimits(TLimits * limits)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
getDefaultBuiltInResources(TBuiltInResource * builtin)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 = 4;
188 builtin->maxTransformFeedbackInterleavedComponents = 64;
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
getNumShaderStages(const std::vector<std::string> * sources)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
getShaderStageSource(const std::vector<std::string> * sources,const ShaderBuildOptions buildOptions,glu::ShaderType shaderType)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
getCompileFlags(const ShaderBuildOptions & buildOpts,const ShaderLanguage shaderLanguage)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
compileShaderToSpirV(const std::vector<std::string> * sources,const ShaderBuildOptions & buildOptions,const ShaderLanguage shaderLanguage,std::vector<deUint32> * dst,glu::ShaderProgramInfo * buildInfo)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 = {0};
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 int srcLengths[] = { (int)srcText.size() };
275 const EShLanguage shaderStage = getGlslangStage(glu::ShaderType(shaderType));
276 glslang::TShader shader (shaderStage);
277 glslang::TProgram glslangProgram;
278
279 shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
280
281 switch ( buildOptions.targetVersion )
282 {
283 case SPIRV_VERSION_1_0:
284 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10000);
285 break;
286 case SPIRV_VERSION_1_1:
287 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10100);
288 break;
289 case SPIRV_VERSION_1_2:
290 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10200);
291 break;
292 case SPIRV_VERSION_1_3:
293 shader.setEnvTarget(glslang::EshTargetSpv, (glslang::EShTargetLanguageVersion)0x10300);
294 break;
295 }
296
297 glslangProgram.addShader(&shader);
298
299 if (shaderLanguage == SHADER_LANGUAGE_HLSL)
300 {
301 // Entry point assumed to be named main.
302 shader.setEntryPoint("main");
303 }
304
305 {
306 const deUint64 compileStartTime = deGetMicroseconds();
307 const int compileRes = shader.parse(&builtinRes, 110, false, compileFlags);
308 glu::ShaderInfo shaderBuildInfo;
309
310 shaderBuildInfo.type = (glu::ShaderType)shaderType;
311 shaderBuildInfo.source = srcText;
312 shaderBuildInfo.infoLog = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
313 shaderBuildInfo.compileTimeUs = deGetMicroseconds()-compileStartTime;
314 shaderBuildInfo.compileOk = (compileRes != 0);
315
316 buildInfo->shaders.push_back(shaderBuildInfo);
317 }
318
319 DE_ASSERT(buildInfo->shaders.size() == 1);
320 if (buildInfo->shaders[0].compileOk)
321 {
322 const deUint64 linkStartTime = deGetMicroseconds();
323 const int linkRes = glslangProgram.link(compileFlags);
324
325 buildInfo->program.infoLog = glslangProgram.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
326 buildInfo->program.linkOk = (linkRes != 0);
327 buildInfo->program.linkTimeUs = deGetMicroseconds()-linkStartTime;
328 }
329
330 if (buildInfo->program.linkOk)
331 {
332 const glslang::TIntermediate* const intermediate = glslangProgram.getIntermediate(shaderStage);
333 glslang::GlslangToSpv(*intermediate, *dst);
334 }
335
336 return buildInfo->program.linkOk;
337 }
338 }
339
340 TCU_THROW(InternalError, "Can't compile empty program");
341 }
342
compileGlslToSpirV(const GlslSource & program,std::vector<deUint32> * dst,glu::ShaderProgramInfo * buildInfo)343 bool compileGlslToSpirV (const GlslSource& program, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
344 {
345 return compileShaderToSpirV(program.sources, program.buildOptions, program.shaderLanguage, dst, buildInfo);
346 }
347
compileHlslToSpirV(const HlslSource & program,std::vector<deUint32> * dst,glu::ShaderProgramInfo * buildInfo)348 bool compileHlslToSpirV (const HlslSource& program, std::vector<deUint32>* dst, glu::ShaderProgramInfo* buildInfo)
349 {
350 return compileShaderToSpirV(program.sources, program.buildOptions, program.shaderLanguage, dst, buildInfo);
351 }
352
stripSpirVDebugInfo(const size_t numSrcInstrs,const deUint32 * srcInstrs,std::vector<deUint32> * dst)353 void stripSpirVDebugInfo (const size_t numSrcInstrs, const deUint32* srcInstrs, std::vector<deUint32>* dst)
354 {
355 spv::spirvbin_t remapper;
356
357 // glslang operates in-place
358 dst->resize(numSrcInstrs);
359 std::copy(srcInstrs, srcInstrs+numSrcInstrs, dst->begin());
360 remapper.remap(*dst, spv::spirvbin_base_t::STRIP);
361 }
362
363 #else // defined(DEQP_HAVE_GLSLANG)
364
compileGlslToSpirV(const GlslSource &,std::vector<deUint32> *,glu::ShaderProgramInfo *)365 bool compileGlslToSpirV (const GlslSource&, std::vector<deUint32>*, glu::ShaderProgramInfo*)
366 {
367 TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
368 }
369
compileHlslToSpirV(const HlslSource &,std::vector<deUint32> *,glu::ShaderProgramInfo *)370 bool compileHlslToSpirV (const HlslSource&, std::vector<deUint32>*, glu::ShaderProgramInfo*)
371 {
372 TCU_THROW(NotSupportedError, "HLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
373 }
374
stripSpirVDebugInfo(const size_t,const deUint32 *,std::vector<deUint32> *)375 void stripSpirVDebugInfo (const size_t, const deUint32*, std::vector<deUint32>*)
376 {
377 TCU_THROW(NotSupportedError, "SPIR-V stripping not supported (DEQP_HAVE_GLSLANG not defined)");
378 }
379
380 #endif // defined(DEQP_HAVE_GLSLANG)
381
382 } // vk
383