1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
18 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
28 * \brief GLSL to SPIR-V.
29 *//*--------------------------------------------------------------------*/
31 #include "vkGlslToSpirV.hpp"
32 #include "deArrayUtil.hpp"
35 #include "qpDebugOut.h"
37 #if defined(DEQP_HAVE_GLSLANG)
38 # include "deSingleton.h"
39 # include "deMutex.hpp"
41 # include "SPIRV/GlslangToSpv.h"
42 # include "SPIRV/disassemble.h"
43 # include "SPIRV/doc.h"
44 # include "glslang/Include/InfoSink.h"
45 # include "glslang/Include/ShHandle.h"
46 # include "glslang/MachineIndependent/localintermediate.h"
47 # include "glslang/Public/ShaderLang.h"
50 #if defined(DEQP_HAVE_SPIRV_TOOLS)
51 # include "libspirv/libspirv.h"
60 #if defined(DEQP_HAVE_GLSLANG)
65 EShLanguage getGlslangStage (glu::ShaderType type)
67 static const EShLanguage stageMap[] =
73 EShLangTessEvaluation,
76 return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
79 static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
80 static de::Mutex s_glslangLock;
82 void initGlslang (void*)
85 glslang::InitializeProcess();
91 void prepareGlslang (void)
93 deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
96 // \todo [2015-06-19 pyry] Specialize these per GLSL version
98 // Fail compilation if more members are added to TLimits or TBuiltInResource
99 struct LimitsSizeHelper_s { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; };
100 struct BuiltInResourceSizeHelper_s { int m[83]; LimitsSizeHelper_s l; };
102 DE_STATIC_ASSERT(sizeof(TLimits) == sizeof(LimitsSizeHelper_s));
103 DE_STATIC_ASSERT(sizeof(TBuiltInResource) == sizeof(BuiltInResourceSizeHelper_s));
105 void getDefaultLimits (TLimits* limits)
107 limits->nonInductiveForLoops = true;
108 limits->whileLoops = true;
109 limits->doWhileLoops = true;
110 limits->generalUniformIndexing = true;
111 limits->generalAttributeMatrixVectorIndexing = true;
112 limits->generalVaryingIndexing = true;
113 limits->generalSamplerIndexing = true;
114 limits->generalVariableIndexing = true;
115 limits->generalConstantMatrixVectorIndexing = true;
118 void getDefaultBuiltInResources (TBuiltInResource* builtin)
120 getDefaultLimits(&builtin->limits);
122 builtin->maxLights = 32;
123 builtin->maxClipPlanes = 6;
124 builtin->maxTextureUnits = 32;
125 builtin->maxTextureCoords = 32;
126 builtin->maxVertexAttribs = 64;
127 builtin->maxVertexUniformComponents = 4096;
128 builtin->maxVaryingFloats = 64;
129 builtin->maxVertexTextureImageUnits = 32;
130 builtin->maxCombinedTextureImageUnits = 80;
131 builtin->maxTextureImageUnits = 32;
132 builtin->maxFragmentUniformComponents = 4096;
133 builtin->maxDrawBuffers = 32;
134 builtin->maxVertexUniformVectors = 128;
135 builtin->maxVaryingVectors = 8;
136 builtin->maxFragmentUniformVectors = 16;
137 builtin->maxVertexOutputVectors = 16;
138 builtin->maxFragmentInputVectors = 15;
139 builtin->minProgramTexelOffset = -8;
140 builtin->maxProgramTexelOffset = 7;
141 builtin->maxClipDistances = 8;
142 builtin->maxComputeWorkGroupCountX = 65535;
143 builtin->maxComputeWorkGroupCountY = 65535;
144 builtin->maxComputeWorkGroupCountZ = 65535;
145 builtin->maxComputeWorkGroupSizeX = 1024;
146 builtin->maxComputeWorkGroupSizeY = 1024;
147 builtin->maxComputeWorkGroupSizeZ = 64;
148 builtin->maxComputeUniformComponents = 1024;
149 builtin->maxComputeTextureImageUnits = 16;
150 builtin->maxComputeImageUniforms = 8;
151 builtin->maxComputeAtomicCounters = 8;
152 builtin->maxComputeAtomicCounterBuffers = 1;
153 builtin->maxVaryingComponents = 60;
154 builtin->maxVertexOutputComponents = 64;
155 builtin->maxGeometryInputComponents = 64;
156 builtin->maxGeometryOutputComponents = 128;
157 builtin->maxFragmentInputComponents = 128;
158 builtin->maxImageUnits = 8;
159 builtin->maxCombinedImageUnitsAndFragmentOutputs = 8;
160 builtin->maxCombinedShaderOutputResources = 8;
161 builtin->maxImageSamples = 0;
162 builtin->maxVertexImageUniforms = 0;
163 builtin->maxTessControlImageUniforms = 0;
164 builtin->maxTessEvaluationImageUniforms = 0;
165 builtin->maxGeometryImageUniforms = 0;
166 builtin->maxFragmentImageUniforms = 8;
167 builtin->maxCombinedImageUniforms = 8;
168 builtin->maxGeometryTextureImageUnits = 16;
169 builtin->maxGeometryOutputVertices = 256;
170 builtin->maxGeometryTotalOutputComponents = 1024;
171 builtin->maxGeometryUniformComponents = 1024;
172 builtin->maxGeometryVaryingComponents = 64;
173 builtin->maxTessControlInputComponents = 128;
174 builtin->maxTessControlOutputComponents = 128;
175 builtin->maxTessControlTextureImageUnits = 16;
176 builtin->maxTessControlUniformComponents = 1024;
177 builtin->maxTessControlTotalOutputComponents = 4096;
178 builtin->maxTessEvaluationInputComponents = 128;
179 builtin->maxTessEvaluationOutputComponents = 128;
180 builtin->maxTessEvaluationTextureImageUnits = 16;
181 builtin->maxTessEvaluationUniformComponents = 1024;
182 builtin->maxTessPatchComponents = 120;
183 builtin->maxPatchVertices = 32;
184 builtin->maxTessGenLevel = 64;
185 builtin->maxViewports = 16;
186 builtin->maxVertexAtomicCounters = 0;
187 builtin->maxTessControlAtomicCounters = 0;
188 builtin->maxTessEvaluationAtomicCounters = 0;
189 builtin->maxGeometryAtomicCounters = 0;
190 builtin->maxFragmentAtomicCounters = 8;
191 builtin->maxCombinedAtomicCounters = 8;
192 builtin->maxAtomicCounterBindings = 1;
193 builtin->maxVertexAtomicCounterBuffers = 0;
194 builtin->maxTessControlAtomicCounterBuffers = 0;
195 builtin->maxTessEvaluationAtomicCounterBuffers = 0;
196 builtin->maxGeometryAtomicCounterBuffers = 0;
197 builtin->maxFragmentAtomicCounterBuffers = 1;
198 builtin->maxCombinedAtomicCounterBuffers = 1;
199 builtin->maxAtomicCounterBufferSize = 16384;
200 builtin->maxTransformFeedbackBuffers = 4;
201 builtin->maxTransformFeedbackInterleavedComponents = 64;
202 builtin->maxCullDistances = 8;
203 builtin->maxCombinedClipAndCullDistances = 8;
204 builtin->maxSamples = 4;
209 void glslToSpirV (const glu::ProgramSources& program, std::vector<deUint8>* dst, glu::ShaderProgramInfo* buildInfo)
211 TBuiltInResource builtinRes;
214 getDefaultBuiltInResources(&builtinRes);
216 // \note Compiles only first found shader
217 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
219 if (!program.sources[shaderType].empty())
221 const de::ScopedLock compileLock (s_glslangLock);
222 const std::string& srcText = program.sources[shaderType][0];
223 const char* srcPtrs[] = { srcText.c_str() };
224 const int srcLengths[] = { (int)srcText.size() };
225 vector<deUint32> spvBlob;
226 const EShLanguage shaderStage = getGlslangStage(glu::ShaderType(shaderType));
227 glslang::TShader shader (shaderStage);
228 glslang::TProgram program;
230 shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
231 program.addShader(&shader);
234 const deUint64 compileStartTime = deGetMicroseconds();
235 const int compileRes = shader.parse(&builtinRes, 110, false, (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
236 glu::ShaderInfo shaderBuildInfo;
238 shaderBuildInfo.type = (glu::ShaderType)shaderType;
239 shaderBuildInfo.source = srcText;
240 shaderBuildInfo.infoLog = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
241 shaderBuildInfo.compileTimeUs = deGetMicroseconds()-compileStartTime;
242 shaderBuildInfo.compileOk = (compileRes != 0);
244 buildInfo->shaders.push_back(shaderBuildInfo);
247 TCU_FAIL("Failed to compile shader");
251 const deUint64 linkStartTime = deGetMicroseconds();
252 const int linkRes = program.link((EShMessages)(EShMsgSpvRules | EShMsgVulkanRules));
254 buildInfo->program.infoLog = program.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
255 buildInfo->program.linkOk = (linkRes != 0);
256 buildInfo->program.linkTimeUs = deGetMicroseconds()-linkStartTime;
259 TCU_FAIL("Failed to link shader");
263 const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
264 glslang::GlslangToSpv(*intermediate, spvBlob);
267 dst->resize(spvBlob.size() * sizeof(deUint32));
268 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
269 deMemcpy(&(*dst)[0], &spvBlob[0], dst->size());
271 # error "Big-endian not supported"
278 TCU_THROW(InternalError, "Can't compile empty program");
281 #else // defined(DEQP_HAVE_GLSLANG)
283 void glslToSpirV (const glu::ProgramSources&, std::vector<deUint8>*, glu::ShaderProgramInfo*)
285 TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
288 #endif // defined(DEQP_HAVE_GLSLANG)
290 #if defined(DEQP_HAVE_SPIRV_TOOLS)
291 void disassembleSpirV (size_t binarySize, const deUint8* binary, std::ostream* dst)
293 std::vector<deUint32> binForDisasm (binarySize/4);
295 DE_ASSERT(binarySize%4 == 0);
297 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
298 deMemcpy(&binForDisasm[0], binary, binarySize);
300 # error "Big-endian not supported"
303 const spv_context context = spvContextCreate();
305 throw std::bad_alloc();
306 spv_text text = DE_NULL;
307 spv_diagnostic diagnostic;
310 const spv_result_t error = spvBinaryToText(context, &binForDisasm[0], binForDisasm.size() , 0, &text, &diagnostic);
311 TCU_CHECK_INTERNAL(!error);
316 spvTextDestroy(text);
317 spvContextDestroy(context);
320 spvTextDestroy(text);
321 spvContextDestroy(context);
323 #else // defined(DEQP_HAVE_SPIRV_TOOLS)
325 void disassembleSpirV (size_t, const deUint8*, std::ostream*)
327 TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
329 #endif // defined(DEQP_HAVE_SPIRV_TOOLS)