diff options
Diffstat (limited to 'thirdparty/glslang/SPIRV/GlslangToSpv.cpp')
-rw-r--r-- | thirdparty/glslang/SPIRV/GlslangToSpv.cpp | 350 |
1 files changed, 272 insertions, 78 deletions
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp index 39941d3752..ccb4602be2 100644 --- a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -260,6 +260,7 @@ protected: std::unordered_map<std::string, spv::Id> extBuiltinMap; std::unordered_map<long long, spv::Id> symbolValues; + std::unordered_map<uint32_t, spv::Id> builtInVariableIds; std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues, // rather than a pointer std::unordered_map<std::string, spv::Function*> functionMap; @@ -279,6 +280,9 @@ protected: // Used later for generating OpTraceKHR/OpExecuteCallableKHR std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[2]; + + // Used by Task shader while generating opearnds for OpEmitMeshTasksEXT + spv::Id taskPayloadID; }; // @@ -314,7 +318,7 @@ spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile } // Translate glslang language (stage) to SPIR-V execution model. -spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) +spv::ExecutionModel TranslateExecutionModel(EShLanguage stage, bool isMeshShaderEXT = false) { switch (stage) { case EShLangVertex: return spv::ExecutionModelVertex; @@ -330,8 +334,8 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR; case EShLangMiss: return spv::ExecutionModelMissKHR; case EShLangCallable: return spv::ExecutionModelCallableKHR; - case EShLangTaskNV: return spv::ExecutionModelTaskNV; - case EShLangMeshNV: return spv::ExecutionModelMeshNV; + case EShLangTask: return (isMeshShaderEXT)? spv::ExecutionModelTaskEXT : spv::ExecutionModelTaskNV; + case EShLangMesh: return (isMeshShaderEXT)? spv::ExecutionModelMeshEXT: spv::ExecutionModelMeshNV; #endif default: assert(0); @@ -762,7 +766,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInSampleMask; case glslang::EbvLayer: - if (glslangIntermediate->getStage() == EShLangMeshNV) { + if (glslangIntermediate->getStage() == EShLangMesh) { return spv::BuiltInLayer; } if (glslangIntermediate->getStage() == EShLangGeometry || @@ -1007,6 +1011,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInRayTminKHR; case glslang::EbvRayTmax: return spv::BuiltInRayTmaxKHR; + case glslang::EbvCullMask: + return spv::BuiltInCullMaskKHR; case glslang::EbvInstanceCustomIndex: return spv::BuiltInInstanceCustomIndexKHR; case glslang::EbvHitT: @@ -1048,6 +1054,15 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addCapability(spv::CapabilityFragmentBarycentricNV); return spv::BuiltInBaryCoordNoPerspNV; + case glslang::EbvBaryCoordEXT: + builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); + builder.addCapability(spv::CapabilityFragmentBarycentricKHR); + return spv::BuiltInBaryCoordKHR; + case glslang::EbvBaryCoordNoPerspEXT: + builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); + builder.addCapability(spv::CapabilityFragmentBarycentricKHR); + return spv::BuiltInBaryCoordNoPerspKHR; + // mesh shaders case glslang::EbvTaskCountNV: return spv::BuiltInTaskCountNV; @@ -1066,6 +1081,16 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI case glslang::EbvMeshViewIndicesNV: return spv::BuiltInMeshViewIndicesNV; + // SPV_EXT_mesh_shader + case glslang::EbvPrimitivePointIndicesEXT: + return spv::BuiltInPrimitivePointIndicesEXT; + case glslang::EbvPrimitiveLineIndicesEXT: + return spv::BuiltInPrimitiveLineIndicesEXT; + case glslang::EbvPrimitiveTriangleIndicesEXT: + return spv::BuiltInPrimitiveTriangleIndicesEXT; + case glslang::EbvCullPrimitiveEXT: + return spv::BuiltInCullPrimitiveEXT; + // sm builtins case glslang::EbvWarpsPerSM: builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); @@ -1309,6 +1334,7 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR; case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR; case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR; + case glslang::EvqtaskPayloadSharedEXT : return spv::StorageClassTaskPayloadWorkgroupEXT; case glslang::EvqSpirvStorageClass: return static_cast<spv::StorageClass>(type.getQualifier().spirvStorageClass); #endif default: @@ -1326,7 +1352,9 @@ void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector<const glsl for (auto constant : constants) { if (constant->getBasicType() == glslang::EbtFloat) { float floatValue = static_cast<float>(constant->getConstArray()[0].getDConst()); - unsigned literal = *reinterpret_cast<unsigned*>(&floatValue); + unsigned literal; + static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); + memcpy(&literal, &floatValue, sizeof(literal)); literals.push_back(literal); } else if (constant->getBasicType() == glslang::EbtInt) { unsigned literal = constant->getConstArray()[0].getIConst(); @@ -1452,6 +1480,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa child.perViewNV = true; if (parent.perTaskNV) child.perTaskNV = true; + if (parent.storage == glslang::EvqtaskPayloadSharedEXT) + child.storage = glslang::EvqtaskPayloadSharedEXT; if (parent.patch) child.patch = true; if (parent.sample) @@ -1511,9 +1541,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), glslangIntermediate(glslangIntermediate), nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()), - nonSemanticDebugPrintf(0) + nonSemanticDebugPrintf(0), + taskPayloadID(0) { - spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); + bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != + glslangIntermediate->getRequestedExtensions().end()); + spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage(), isMeshShaderExt); builder.clearAccessChain(); builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), @@ -1545,6 +1578,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr) builder.addInclude(iItr->first, iItr->second); } + + builder.setEmitNonSemanticShaderDebugInfo(options.emitNonSemanticShaderDebugInfo); + builder.setEmitNonSemanticShaderDebugSource(options.emitNonSemanticShaderDebugSource); + stdBuiltins = builder.import("GLSL.std.450"); spv::AddressingModel addressingModel = spv::AddressingModelLogical; @@ -1611,6 +1648,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, if (glslangIntermediate->getEarlyFragmentTests()) builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); + if (glslangIntermediate->getEarlyAndLateFragmentTestsAMD()) + { + builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyAndLateFragmentTestsAMD); + builder.addExtension(spv::E_SPV_AMD_shader_early_and_late_fragment_tests); + } + if (glslangIntermediate->getPostDepthCoverage()) { builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); @@ -1620,6 +1663,9 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, if (glslangIntermediate->isDepthReplacing()) builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); + if (glslangIntermediate->isStencilReplacing()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModeStencilRefReplacingEXT); + #ifndef GLSLANG_WEB switch(glslangIntermediate->getDepth()) { @@ -1628,6 +1674,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break; default: mode = spv::ExecutionModeMax; break; } + + if (mode != spv::ExecutionModeMax) + builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); + + switch (glslangIntermediate->getStencil()) { + case glslang::ElsRefUnchangedFrontAMD: mode = spv::ExecutionModeStencilRefUnchangedFrontAMD; break; + case glslang::ElsRefGreaterFrontAMD: mode = spv::ExecutionModeStencilRefGreaterFrontAMD; break; + case glslang::ElsRefLessFrontAMD: mode = spv::ExecutionModeStencilRefLessFrontAMD; break; + case glslang::ElsRefUnchangedBackAMD: mode = spv::ExecutionModeStencilRefUnchangedBackAMD; break; + case glslang::ElsRefGreaterBackAMD: mode = spv::ExecutionModeStencilRefGreaterBackAMD; break; + case glslang::ElsRefLessBackAMD: mode = spv::ExecutionModeStencilRefLessBackAMD; break; + default: mode = spv::ExecutionModeMax; break; + } + if (mode != spv::ExecutionModeMax) builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); switch (glslangIntermediate->getInterlockOrdering()) { @@ -1766,7 +1826,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, case EShLangAnyHit: case EShLangClosestHit: case EShLangMiss: - case EShLangCallable: + case EShLangCallable: { auto& extensions = glslangIntermediate->getRequestedExtensions(); if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { @@ -1777,12 +1837,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, builder.addCapability(spv::CapabilityRayTracingNV); builder.addExtension("SPV_NV_ray_tracing"); } + if (glslangIntermediate->getStage() != EShLangRayGen && glslangIntermediate->getStage() != EShLangCallable) + { + if (extensions.find("GL_EXT_ray_cull_mask") != extensions.end()) { + builder.addCapability(spv::CapabilityRayCullMaskKHR); + builder.addExtension("SPV_KHR_ray_cull_mask"); + } + } break; } - case EShLangTaskNV: - case EShLangMeshNV: - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); + case EShLangTask: + case EShLangMesh: + if(isMeshShaderExt) { + builder.addCapability(spv::CapabilityMeshShadingEXT); + builder.addExtension(spv::E_SPV_EXT_mesh_shader); + } else { + builder.addCapability(spv::CapabilityMeshShadingNV); + builder.addExtension(spv::E_SPV_NV_mesh_shader); + } if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { std::vector<spv::Id> dimConstId; for (int dim = 0; dim < 3; ++dim) { @@ -1799,7 +1871,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, glslangIntermediate->getLocalSize(1), glslangIntermediate->getLocalSize(2)); } - if (glslangIntermediate->getStage() == EShLangMeshNV) { + if (glslangIntermediate->getStage() == EShLangMesh) { builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, @@ -1918,7 +1990,6 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) if (symbol->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - #ifdef ENABLE_HLSL // Skip symbol handling if it is string-typed if (symbol->getBasicType() == glslang::EbtString) @@ -1929,6 +2000,9 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) // Formal function parameters were mapped during makeFunctions(). spv::Id id = getSymbolId(symbol); + if (symbol->getType().getQualifier().isTaskPayload()) + taskPayloadID = id; // cache the taskPayloadID to be used it as operand for OpEmitMeshTasksEXT + if (builder.isPointer(id)) { if (!symbol->getType().getQualifier().isParamInput() && !symbol->getType().getQualifier().isParamOutput()) { @@ -2456,6 +2530,14 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI return false; } + // Force variable declaration - Debug Mode Only + if (node->getOp() == glslang::EOpDeclare) { + builder.clearAccessChain(); + node->getOperand()->traverse(this); + builder.clearAccessChain(); + return false; + } + // Start by evaluating the operand // Does it need a swizzle inversion? If so, evaluation is inverted; @@ -2472,7 +2554,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI operandNode = node->getOperand()->getAsBinaryNode()->getLeft(); else operandNode = node->getOperand(); - + operandNode->traverse(this); spv::Id operand = spv::NoResult; @@ -2716,32 +2798,38 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); switch (node->getOp()) { + case glslang::EOpScope: case glslang::EOpSequence: { - if (preVisit) + if (visit == glslang::EvPreVisit) { ++sequenceDepth; - else - --sequenceDepth; - - if (sequenceDepth == 1) { - // If this is the parent node of all the functions, we want to see them - // early, so all call points have actual SPIR-V functions to reference. - // In all cases, still let the traverser visit the children for us. - makeFunctions(node->getAsAggregate()->getSequence()); + if (sequenceDepth == 1) { + // If this is the parent node of all the functions, we want to see them + // early, so all call points have actual SPIR-V functions to reference. + // In all cases, still let the traverser visit the children for us. + makeFunctions(node->getAsAggregate()->getSequence()); - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); + // Also, we want all globals initializers to go into the beginning of the entry point, before + // anything else gets there, so visit out of order, doing them all now. + makeGlobalInitializers(node->getAsAggregate()->getSequence()); - //Pre process linker objects for ray tracing stages - if (glslangIntermediate->isRayTracingStage()) - collectRayTracingLinkerObjects(); + //Pre process linker objects for ray tracing stages + if (glslangIntermediate->isRayTracingStage()) + collectRayTracingLinkerObjects(); - // Initializers are done, don't want to visit again, but functions and link objects need to be processed, - // so do them manually. - visitFunctions(node->getAsAggregate()->getSequence()); + // Initializers are done, don't want to visit again, but functions and link objects need to be processed, + // so do them manually. + visitFunctions(node->getAsAggregate()->getSequence()); - return false; + return false; + } else { + if (node->getOp() == glslang::EOpScope) + builder.enterScope(0); + } + } else { + if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope) + builder.leaveScope(); + --sequenceDepth; } return true; @@ -2770,10 +2858,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt if (isShaderEntryPoint(node)) { inEntryPoint = true; builder.setBuildPoint(shaderEntry->getLastBlock()); + builder.enterFunction(shaderEntry); currentFunction = shaderEntry; } else { handleFunctionEntry(node); } + if (options.generateDebugInfo) { + const auto& loc = node->getLoc(); + const char* sourceFileName = loc.getFilename(); + spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getSourceFile(); + currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column); + } } else { if (inEntryPoint) entryPointTerminated = true; @@ -2913,9 +3008,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt std::vector<spv::Id> arguments; translateArguments(*node, arguments, lvalueCoherentFlags); spv::Id constructed; - if (node->getOp() == glslang::EOpConstructTextureSampler) - constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); - else if (node->getOp() == glslang::EOpConstructStruct || + if (node->getOp() == glslang::EOpConstructTextureSampler) { + const glslang::TType& texType = node->getSequence()[0]->getAsTyped()->getType(); + if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && + texType.getSampler().isBuffer()) { + // SamplerBuffer is not supported in spirv1.6 so + // `samplerBuffer(textureBuffer, sampler)` is a no-op + // and textureBuffer is the result going forward + constructed = arguments[0]; + } else + constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); + } else if (node->getOp() == glslang::EOpConstructStruct || node->getOp() == glslang::EOpConstructCooperativeMatrix || node->getType().isArray()) { std::vector<spv::Id> constituents; @@ -3055,6 +3158,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpExecuteCallableNV: case glslang::EOpExecuteCallableKHR: case glslang::EOpWritePackedPrimitiveIndices4x8NV: + case glslang::EOpEmitMeshTasksEXT: + case glslang::EOpSetMeshOutputsEXT: noReturnValue = true; break; case glslang::EOpRayQueryInitialize: @@ -3449,7 +3554,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; case 1: { - OpDecorations decorations = { precision, + OpDecorations decorations = { precision, TranslateNoContractionDecoration(node->getType().getQualifier()), TranslateNonUniformDecoration(node->getType().getQualifier()) }; result = createUnaryOperation( @@ -3571,7 +3676,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang // smear condition to vector, if necessary (AST is always scalar) // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) { - condition = builder.smearScalar(spv::NoPrecision, condition, + condition = builder.smearScalar(spv::NoPrecision, condition, builder.makeVectorType(builder.makeBoolType(), builder.getNumComponents(trueValue))); } @@ -3742,8 +3847,8 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn // by a block-ending branch. But we don't want to put any other body/test // instructions in it, since the body/test may have arbitrary instructions, // including merges of its own. - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setBuildPoint(&blocks.head); + builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands); if (node->testFirst() && node->getTest()) { spv::Block& test = builder.makeNewBlock(); @@ -3962,7 +4067,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* initializer = builder.makeNullConstant(spvType); } - return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer); + return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false); } // Return type Id of the sampled type. @@ -4050,7 +4155,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty if (explicitLayout != glslang::ElpNone) spvType = builder.makeUintType(32); else - spvType = builder.makeBoolType(); + spvType = builder.makeBoolType(false); break; case glslang::EbtInt: spvType = builder.makeIntType(32); @@ -4150,8 +4255,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(), sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type)); - if (sampler.isCombined()) { - // already has both image and sampler, make the combined type + if (sampler.isCombined() && + (!sampler.isBuffer() || glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6)) { + // Already has both image and sampler, make the combined type. Only combine sampler to + // buffer if before SPIR-V 1.6. spvType = builder.makeSampledImageType(spvType); } } @@ -4191,7 +4298,9 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty if (typeParam.constant->isLiteral()) { if (typeParam.constant->getBasicType() == glslang::EbtFloat) { float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst()); - unsigned literal = *reinterpret_cast<unsigned*>(&floatValue); + unsigned literal; + static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); + memcpy(&literal, &floatValue, sizeof(literal)); operands.push_back({false, literal}); } else if (typeParam.constant->getBasicType() == glslang::EbtInt) { unsigned literal = typeParam.constant->getConstArray()[0].getIConst(); @@ -4336,7 +4445,7 @@ bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) return true; - if (glslangIntermediate->getStage() != EShLangMeshNV) { + if (glslangIntermediate->getStage() != EShLangMesh) { if (member.getFieldName() == "gl_ViewportMask" && extensions.find("GL_NV_viewport_array2") == extensions.end()) return true; @@ -4366,14 +4475,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy // except sometimes for blocks std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers; for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - if (glslangMember.hiddenMember()) { + auto& glslangMember = (*glslangMembers)[i]; + if (glslangMember.type->hiddenMember()) { ++memberDelta; if (type.getBasicType() == glslang::EbtBlock) memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; } else { if (type.getBasicType() == glslang::EbtBlock) { - if (filterMember(glslangMember)) { + if (filterMember(*glslangMember.type)) { memberDelta++; memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; continue; @@ -4381,7 +4490,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; } // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); + glslang::TQualifier memberQualifier = glslangMember.type->getQualifier(); InheritQualifiers(memberQualifier, qualifier); // manually inherit location @@ -4392,25 +4501,38 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer && i == (int)glslangMembers->size() - 1; - // Make forward pointers for any pointer members, and create a list of members to - // convert to spirv types after creating the struct. - if (glslangMember.isReference()) { - if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) { - deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier)); - } - spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, - true)); - } else { - spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, - false)); + // Make forward pointers for any pointer members. + if (glslangMember.type->isReference() && + forwardPointers.find(glslangMember.type->getReferentType()) == forwardPointers.end()) { + deferredForwardPointers.push_back(std::make_pair(glslangMember.type, memberQualifier)); + } + + // Create the member type. + auto const spvMember = convertGlslangToSpvType(*glslangMember.type, explicitLayout, memberQualifier, lastBufferBlockMember, + glslangMember.type->isReference()); + spvMembers.push_back(spvMember); + + // Update the builder with the type's location so that we can create debug types for the structure members. + // There doesn't exist a "clean" entry point for this information to be passed along to the builder so, for now, + // it is stored in the builder and consumed during the construction of composite debug types. + // TODO: This probably warrants further investigation. This approach was decided to be the least ugly of the + // quick and dirty approaches that were tried. + // Advantages of this approach: + // + Relatively clean. No direct calls into debug type system. + // + Handles nested recursive structures. + // Disadvantages of this approach: + // + Not as clean as desired. Traverser queries/sets persistent state. This is fragile. + // + Table lookup during creation of composite debug types. This really shouldn't be necessary. + if(options.emitNonSemanticShaderDebugInfo) { + builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str(); + builder.debugTypeLocs[spvMember].line = glslangMember.loc.line; + builder.debugTypeLocs[spvMember].column = glslangMember.loc.column; } } } // Make the SPIR-V type - spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str()); + spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false); if (! HasNonLayoutQualifiers(type, qualifier)) structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; @@ -5004,6 +5126,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. std::vector<spv::Id> paramTypes; + std::vector<char const*> paramNames; std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); @@ -5028,10 +5151,14 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF paramTypes.push_back(typeId); } + for (auto const parameter:parameters) { + paramNames.push_back(parameter->getAsSymbolNode()->getName().c_str()); + } + spv::Block* functionBlock; spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), paramTypes, + glslFunction->getName().c_str(), paramTypes, paramNames, paramDecorations, &functionBlock); if (implicitThis) function->setImplicitThis(); @@ -5121,6 +5248,7 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate currentFunction = functionMap[node->getName().c_str()]; spv::Block* functionBlock = currentFunction->getEntryBlock(); builder.setBuildPoint(functionBlock); + builder.enterFunction(currentFunction); } void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, @@ -5548,10 +5676,12 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO operands.push_back(sample); spv::Id resultTypeId; + glslang::TBasicType typeProxy = node->getBasicType(); // imageAtomicStore has a void return type so base the pointer type on // the type of the value operand. if (node->getOp() == glslang::EOpImageAtomicStore) { resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt)); + typeProxy = node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler().type; } else { resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); } @@ -5565,7 +5695,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO for (; opIt != arguments.end(); ++opIt) operands.push_back(*opIt); - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), + return createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, lvalueCoherentFlags); } } @@ -5769,10 +5899,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO assert(builder.isStructType(resultStructType)); //resType (SPIR-V type) contains 6 elements: - //Member 0 must be a Boolean type scalar(LOD), - //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), - //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), - //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), + //Member 0 must be a Boolean type scalar(LOD), + //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), + //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), + //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), //Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod), //Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity). std::vector<spv::Id> members; @@ -5785,7 +5915,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO //call ImageFootprintNV spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params, signExtensionMask()); - + //copy resType (SPIR-V type) to resultStructType(OpenGL type) for (int i = 0; i < 5; i++) { builder.clearAccessChain(); @@ -5838,7 +5968,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } #endif - std::vector<spv::Id> result( 1, + std::vector<spv::Id> result( 1, builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params, signExtensionMask()) ); @@ -7361,7 +7491,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv } else { scopeId = builder.makeUintConstant(spv::ScopeDevice); } - // semantics default to relaxed + // semantics default to relaxed spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ? spv::MemorySemanticsVolatileMask : @@ -8465,6 +8595,15 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpWritePackedPrimitiveIndices4x8NV: builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); return 0; + case glslang::EOpEmitMeshTasksEXT: + if (taskPayloadID) + operands.push_back(taskPayloadID); + // As per SPV_EXT_mesh_shader make it a terminating instruction in the current block + builder.makeStatementTerminator(spv::OpEmitMeshTasksEXT, operands, "post-OpEmitMeshTasksEXT"); + return 0; + case glslang::EOpSetMeshOutputsEXT: + builder.createNoResultOp(spv::OpSetMeshOutputsEXT, operands); + return 0; case glslang::EOpCooperativeMatrixMulAdd: opCode = spv::OpCooperativeMatrixMulAddNV; break; @@ -8728,7 +8867,32 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol // it was not found, create it spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); + + // There are pairs of symbols that map to the same SPIR-V built-in: + // gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT + // and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables + // with the same BuiltIn in the same storage class, so we must re-use one. + const bool mayNeedToReuseBuiltIn = + builtIn == spv::BuiltInObjectToWorldKHR || + builtIn == spv::BuiltInWorldToObjectKHR; + + if (mayNeedToReuseBuiltIn) { + auto iter = builtInVariableIds.find(uint32_t(builtIn)); + if (builtInVariableIds.end() != iter) { + id = iter->second; + symbolValues[symbol->getId()] = id; + if (forcedType.second != spv::NoType) + forceType[id] = forcedType.second; + return id; + } + } + id = createSpvVariable(symbol, forcedType.first); + + if (mayNeedToReuseBuiltIn) { + builtInVariableIds.insert({uint32_t(builtIn), id}); + } + symbolValues[symbol->getId()] = id; if (forcedType.second != spv::NoType) forceType[id] = forcedType.second; @@ -8857,6 +9021,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); } + if (symbol->getQualifier().pervertexEXT) { + builder.addDecoration(id, spv::DecorationPerVertexKHR); + builder.addCapability(spv::CapabilityFragmentBarycentricKHR); + builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); + } + if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, @@ -8918,13 +9088,21 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol // add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier) { + bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != + glslangIntermediate->getRequestedExtensions().end()); + if (member >= 0) { if (qualifier.perPrimitiveNV) { // Need to add capability/extension for fragment shader. // Mesh shader already adds this by default. if (glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); + if(isMeshShaderExt) { + builder.addCapability(spv::CapabilityMeshShadingEXT); + builder.addExtension(spv::E_SPV_EXT_mesh_shader); + } else { + builder.addCapability(spv::CapabilityMeshShadingNV); + builder.addExtension(spv::E_SPV_NV_mesh_shader); + } } builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV); } @@ -8937,8 +9115,13 @@ void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const g // Need to add capability/extension for fragment shader. // Mesh shader already adds this by default. if (glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); + if(isMeshShaderExt) { + builder.addCapability(spv::CapabilityMeshShadingEXT); + builder.addExtension(spv::E_SPV_EXT_mesh_shader); + } else { + builder.addCapability(spv::CapabilityMeshShadingNV); + builder.addExtension(spv::E_SPV_NV_mesh_shader); + } } builder.addDecoration(id, spv::DecorationPerPrimitiveNV); } @@ -9078,15 +9261,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla break; #ifndef GLSLANG_WEB case glslang::EbtInt8: + builder.addCapability(spv::CapabilityInt8); spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); break; case glslang::EbtUint8: + builder.addCapability(spv::CapabilityInt8); spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const())); break; case glslang::EbtInt16: + builder.addCapability(spv::CapabilityInt16); spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const())); break; case glslang::EbtUint16: + builder.addCapability(spv::CapabilityInt16); spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); break; case glslang::EbtInt64: @@ -9099,6 +9286,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); break; case glslang::EbtFloat16: + builder.addCapability(spv::CapabilityFloat16); spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); break; #endif @@ -9127,15 +9315,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla break; #ifndef GLSLANG_WEB case glslang::EbtInt8: + builder.addCapability(spv::CapabilityInt8); scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); break; case glslang::EbtUint8: + builder.addCapability(spv::CapabilityInt8); scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant); break; case glslang::EbtInt16: + builder.addCapability(spv::CapabilityInt16); scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant); break; case glslang::EbtUint16: + builder.addCapability(spv::CapabilityInt16); scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); break; case glslang::EbtInt64: @@ -9148,6 +9340,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); break; case glslang::EbtFloat16: + builder.addCapability(spv::CapabilityFloat16); scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); break; case glslang::EbtReference: @@ -9345,7 +9538,8 @@ int GetSpirvGeneratorVersion() // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent // return 8; // switch to new dead block eliminator; use OpUnreachable // return 9; // don't include opaque function parameters in OpEntryPoint global's operand list - return 10; // Generate OpFUnordNotEqual for != comparisons + // return 10; // Generate OpFUnordNotEqual for != comparisons + return 11; // Make OpEmitMeshTasksEXT a terminal instruction } // Write SPIR-V out to a binary file |