vkGlslToSpirV.cpp revision 601a13635971626206a988077de52e8db405c419
1/*------------------------------------------------------------------------- 2 * Vulkan CTS Framework 3 * -------------------- 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 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: 14 * 15 * The above copyright notice(s) and this permission notice shall be 16 * included in all copies or substantial portions of the Materials. 17 * 18 * The Materials are Confidential Information as defined by the 19 * Khronos Membership Agreement until designated non-confidential by 20 * Khronos, at which point this condition clause shall be removed. 21 * 22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 29 * 30 *//*! 31 * \file 32 * \brief GLSL to SPIR-V. 33 *//*--------------------------------------------------------------------*/ 34 35#include "vkGlslToSpirV.hpp" 36#include "deArrayUtil.hpp" 37#include "deMemory.h" 38#include "deClock.h" 39#include "qpDebugOut.h" 40 41#if defined(DEQP_HAVE_GLSLANG) 42# include "deSingleton.h" 43# include "deMutex.hpp" 44 45# include "SPIRV/GlslangToSpv.h" 46# include "SPIRV/disassemble.h" 47# include "SPIRV/GLSL450Lib.h" 48# include "SPIRV/doc.h" 49# include "glslang/Include/InfoSink.h" 50# include "glslang/Include/ShHandle.h" 51# include "glslang/MachineIndependent/localintermediate.h" 52# include "glslang/Public/ShaderLang.h" 53 54// Required by SPIR-V disassembler 55const char* GlslStd450DebugNames[GLSL_STD_450::Count]; 56 57#endif 58 59namespace vk 60{ 61 62using std::string; 63using std::vector; 64 65#if defined(DEQP_HAVE_GLSLANG) 66 67namespace 68{ 69 70EShLanguage getGlslangStage (glu::ShaderType type) 71{ 72 static const EShLanguage stageMap[] = 73 { 74 EShLangVertex, 75 EShLangFragment, 76 EShLangGeometry, 77 EShLangTessControl, 78 EShLangTessEvaluation, 79 EShLangCompute, 80 }; 81 return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type); 82} 83 84static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED; 85static de::Mutex s_glslangLock; 86 87void initGlslang (void*) 88{ 89 // Main compiler 90 ShInitialize(); 91 92 // SPIR-V disassembly 93 spv::Parameterize(); 94 GLSL_STD_450::GetDebugNames(GlslStd450DebugNames); 95} 96 97void prepareGlslang (void) 98{ 99 deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL); 100} 101 102class SpvGenerator : public TCompiler 103{ 104public: 105 SpvGenerator (EShLanguage language, std::vector<deUint32>& dst, TInfoSink& infoSink) 106 : TCompiler (language, infoSink) 107 , m_dst (dst) 108 { 109 } 110 111 bool compile (TIntermNode* root, int version = 0, EProfile profile = ENoProfile) 112 { 113 glslang::TIntermediate intermediate(getLanguage(), version, profile); 114 intermediate.setTreeRoot(root); 115 glslang::GlslangToSpv(intermediate, m_dst); 116 return true; 117 } 118 119private: 120 std::vector<deUint32>& m_dst; 121}; 122 123// \todo [2015-06-19 pyry] Specialize these per GLSL version 124 125// Fail compilation if more members are added to TLimits or TBuiltInResource 126struct LimitsSizeHelper_s { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; }; 127struct BuiltInResourceSizeHelper_s { int m[83]; LimitsSizeHelper_s l; }; 128 129DE_STATIC_ASSERT(sizeof(TLimits) == sizeof(LimitsSizeHelper_s)); 130DE_STATIC_ASSERT(sizeof(TBuiltInResource) == sizeof(BuiltInResourceSizeHelper_s)); 131 132void getDefaultLimits (TLimits* limits) 133{ 134 limits->nonInductiveForLoops = true; 135 limits->whileLoops = true; 136 limits->doWhileLoops = true; 137 limits->generalUniformIndexing = true; 138 limits->generalAttributeMatrixVectorIndexing = true; 139 limits->generalVaryingIndexing = true; 140 limits->generalSamplerIndexing = true; 141 limits->generalVariableIndexing = true; 142 limits->generalConstantMatrixVectorIndexing = true; 143} 144 145void getDefaultBuiltInResources (TBuiltInResource* builtin) 146{ 147 getDefaultLimits(&builtin->limits); 148 149 builtin->maxLights = 32; 150 builtin->maxClipPlanes = 6; 151 builtin->maxTextureUnits = 32; 152 builtin->maxTextureCoords = 32; 153 builtin->maxVertexAttribs = 64; 154 builtin->maxVertexUniformComponents = 4096; 155 builtin->maxVaryingFloats = 64; 156 builtin->maxVertexTextureImageUnits = 32; 157 builtin->maxCombinedTextureImageUnits = 80; 158 builtin->maxTextureImageUnits = 32; 159 builtin->maxFragmentUniformComponents = 4096; 160 builtin->maxDrawBuffers = 32; 161 builtin->maxVertexUniformVectors = 128; 162 builtin->maxVaryingVectors = 8; 163 builtin->maxFragmentUniformVectors = 16; 164 builtin->maxVertexOutputVectors = 16; 165 builtin->maxFragmentInputVectors = 15; 166 builtin->minProgramTexelOffset = -8; 167 builtin->maxProgramTexelOffset = 7; 168 builtin->maxClipDistances = 8; 169 builtin->maxComputeWorkGroupCountX = 65535; 170 builtin->maxComputeWorkGroupCountY = 65535; 171 builtin->maxComputeWorkGroupCountZ = 65535; 172 builtin->maxComputeWorkGroupSizeX = 1024; 173 builtin->maxComputeWorkGroupSizeX = 1024; 174 builtin->maxComputeWorkGroupSizeZ = 64; 175 builtin->maxComputeUniformComponents = 1024; 176 builtin->maxComputeTextureImageUnits = 16; 177 builtin->maxComputeImageUniforms = 8; 178 builtin->maxComputeAtomicCounters = 8; 179 builtin->maxComputeAtomicCounterBuffers = 1; 180 builtin->maxVaryingComponents = 60; 181 builtin->maxVertexOutputComponents = 64; 182 builtin->maxGeometryInputComponents = 64; 183 builtin->maxGeometryOutputComponents = 128; 184 builtin->maxFragmentInputComponents = 128; 185 builtin->maxImageUnits = 8; 186 builtin->maxCombinedImageUnitsAndFragmentOutputs = 8; 187 builtin->maxCombinedShaderOutputResources = 8; 188 builtin->maxImageSamples = 0; 189 builtin->maxVertexImageUniforms = 0; 190 builtin->maxTessControlImageUniforms = 0; 191 builtin->maxTessEvaluationImageUniforms = 0; 192 builtin->maxGeometryImageUniforms = 0; 193 builtin->maxFragmentImageUniforms = 8; 194 builtin->maxCombinedImageUniforms = 8; 195 builtin->maxGeometryTextureImageUnits = 16; 196 builtin->maxGeometryOutputVertices = 256; 197 builtin->maxGeometryTotalOutputComponents = 1024; 198 builtin->maxGeometryUniformComponents = 1024; 199 builtin->maxGeometryVaryingComponents = 64; 200 builtin->maxTessControlInputComponents = 128; 201 builtin->maxTessControlOutputComponents = 128; 202 builtin->maxTessControlTextureImageUnits = 16; 203 builtin->maxTessControlUniformComponents = 1024; 204 builtin->maxTessControlTotalOutputComponents = 4096; 205 builtin->maxTessEvaluationInputComponents = 128; 206 builtin->maxTessEvaluationOutputComponents = 128; 207 builtin->maxTessEvaluationTextureImageUnits = 16; 208 builtin->maxTessEvaluationUniformComponents = 1024; 209 builtin->maxTessPatchComponents = 120; 210 builtin->maxPatchVertices = 32; 211 builtin->maxTessGenLevel = 64; 212 builtin->maxViewports = 16; 213 builtin->maxVertexAtomicCounters = 0; 214 builtin->maxTessControlAtomicCounters = 0; 215 builtin->maxTessEvaluationAtomicCounters = 0; 216 builtin->maxGeometryAtomicCounters = 0; 217 builtin->maxFragmentAtomicCounters = 8; 218 builtin->maxCombinedAtomicCounters = 8; 219 builtin->maxAtomicCounterBindings = 1; 220 builtin->maxVertexAtomicCounterBuffers = 0; 221 builtin->maxTessControlAtomicCounterBuffers = 0; 222 builtin->maxTessEvaluationAtomicCounterBuffers = 0; 223 builtin->maxGeometryAtomicCounterBuffers = 0; 224 builtin->maxFragmentAtomicCounterBuffers = 1; 225 builtin->maxCombinedAtomicCounterBuffers = 1; 226 builtin->maxAtomicCounterBufferSize = 16384; 227 builtin->maxTransformFeedbackBuffers = 4; 228 builtin->maxTransformFeedbackInterleavedComponents = 64; 229 builtin->maxCullDistances = 8; 230 builtin->maxCombinedClipAndCullDistances = 8; 231 builtin->maxSamples = 4; 232}; 233 234} // anonymous 235 236void glslToSpirV (const glu::ProgramSources& program, std::vector<deUint8>* dst, glu::ShaderProgramInfo* buildInfo) 237{ 238 TBuiltInResource builtinRes; 239 240 prepareGlslang(); 241 getDefaultBuiltInResources(&builtinRes); 242 243 // \note Compiles only first found shader 244 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 245 { 246 if (!program.sources[shaderType].empty()) 247 { 248 de::ScopedLock compileLock (s_glslangLock); 249 const std::string& srcText = program.sources[shaderType][0]; 250 const char* srcPtrs[] = { srcText.c_str() }; 251 int srcLengths[] = { (int)srcText.size() }; 252 vector<deUint32> spvBlob; 253 TInfoSink infoSink; 254 SpvGenerator compiler (getGlslangStage(glu::ShaderType(shaderType)), spvBlob, infoSink); 255 const deUint64 compileStartTime = deGetMicroseconds(); 256 const int compileOk = ShCompile(static_cast<ShHandle>(&compiler), srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs), srcLengths, EShOptNone, &builtinRes, 0); 257 258 { 259 glu::ShaderInfo shaderBuildInfo; 260 261 shaderBuildInfo.type = (glu::ShaderType)shaderType; 262 shaderBuildInfo.source = srcText; 263 shaderBuildInfo.infoLog = infoSink.info.c_str(); // \todo [2015-07-13 pyry] Include debug log? 264 shaderBuildInfo.compileTimeUs = deGetMicroseconds()-compileStartTime; 265 shaderBuildInfo.compileOk = (compileOk != 0); 266 267 buildInfo->shaders.push_back(shaderBuildInfo); 268 } 269 270 buildInfo->program.infoLog = "(No linking performed)"; 271 buildInfo->program.linkOk = (compileOk != 0); 272 buildInfo->program.linkTimeUs = 0; 273 274 if (compileOk == 0) 275 TCU_FAIL("Failed to compile shader"); 276 277 dst->resize(spvBlob.size() * sizeof(deUint32)); 278#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) 279 deMemcpy(&(*dst)[0], &spvBlob[0], dst->size()); 280#else 281# error "Big-endian not supported" 282#endif 283 284 return; 285 } 286 } 287 288 TCU_THROW(InternalError, "Can't compile empty program"); 289} 290 291void disassembleSpirV (size_t binarySize, const deUint8* binary, std::ostream* dst) 292{ 293 std::vector<deUint32> binForDisasm (binarySize/4); 294 295 DE_ASSERT(binarySize%4 == 0); 296 297#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) 298 deMemcpy(&binForDisasm[0], binary, binarySize); 299#else 300# error "Big-endian not supported" 301#endif 302 303 spv::Disassemble(*dst, binForDisasm); 304} 305 306#else // defined(DEQP_HAVE_GLSLANG) 307 308void glslToSpirV (const glu::ProgramSources&, std::vector<deUint8>*, glu::ShaderProgramInfo*) 309{ 310 TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)"); 311} 312 313void disassembleSpirV (size_t, const deUint8*, std::ostream*) 314{ 315 TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_GLSLANG not defined)"); 316} 317 318#endif 319 320} // vk 321