diff options
| -rw-r--r-- | source/slang/emit.cpp | 31 | ||||
| -rw-r--r-- | source/slang/ir-insts.h | 14 | ||||
| -rw-r--r-- | source/slang/ir-serialize.cpp | 30 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 16 | ||||
| -rw-r--r-- | source/slang/ir.h | 2 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 17 |
6 files changed, 109 insertions, 1 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 4961518f1..c9e19dffc 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -3466,9 +3466,38 @@ struct EmitVisitor IREmitMode mode, EOpInfo outerPrec) { + auto funcValue = inst->getOperand(0); + + // Does this function declare any requirements on GLSL version or + // extensions, which should affect our output? + if(getTarget(ctx) == CodeGenTarget::GLSL) + { + auto decoratedValue = funcValue; + while (auto specInst = as<IRSpecialize>(decoratedValue)) + { + decoratedValue = getSpecializedValue(specInst); + } + + for( auto decoration = decoratedValue->firstDecoration; decoration; decoration = decoration->next ) + { + switch(decoration->op) + { + default: + break; + + case kIRDecorationOp_RequireGLSLExtension: + requireGLSLExtension(String(((IRRequireGLSLExtensionDecoration*)decoration)->extensionName)); + break; + + case kIRDecorationOp_RequireGLSLVersion: + requireGLSLVersion(int(((IRRequireGLSLVersionDecoration*)decoration)->languageVersion)); + break; + } + } + } + // We want to detect any call to an intrinsic operation, // that we can emit it directly without mangling, etc. - auto funcValue = inst->getOperand(0); if(auto irFunc = asTargetIntrinsic(ctx, funcValue)) { emitIntrinsicCallExpr(ctx, inst, irFunc, mode, outerPrec); diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h index 1bce75b88..8d1c4708a 100644 --- a/source/slang/ir-insts.h +++ b/source/slang/ir-insts.h @@ -133,6 +133,20 @@ struct IRVulkanHitAttributesDecoration : IRDecoration enum { kDecorationOp = kIRDecorationOp_VulkanHitAttributes }; }; +struct IRRequireGLSLVersionDecoration : IRDecoration +{ + enum { kDecorationOp = kIRDecorationOp_RequireGLSLVersion }; + + Int languageVersion; +}; + +struct IRRequireGLSLExtensionDecoration : IRDecoration +{ + enum { kDecorationOp = kIRDecorationOp_RequireGLSLExtension }; + + StringRepresentation* extensionName; +}; + // An instruction that specializes another IR value // (representing a generic) to a particular set of generic arguments // (instructions representing types, witness tables, etc.) diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp index 3b0e45e23..e204944a7 100644 --- a/source/slang/ir-serialize.cpp +++ b/source/slang/ir-serialize.cpp @@ -531,6 +531,22 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt dstInst.m_payloadType = PayloadType::Empty; break; } + case kIRDecorationOp_RequireGLSLExtension: + { + auto extDecor = static_cast<IRRequireGLSLExtensionDecoration*>(srcDecor); + + dstInst.m_payloadType = PayloadType::String_1; + dstInst.m_payload.m_stringIndices[0] = getStringIndex(extDecor->extensionName); + break; + } + case kIRDecorationOp_RequireGLSLVersion: + { + auto verDecor = static_cast<IRRequireGLSLVersionDecoration*>(srcDecor); + + dstInst.m_payloadType = PayloadType::UInt32; + dstInst.m_payload.m_uint32 = uint32_t(verDecor->languageVersion); + break; + } default: { SLANG_ASSERT(!"Unhandled decoration type"); @@ -1513,6 +1529,20 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst) SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty); return decor; } + case kIRDecorationOp_RequireGLSLExtension: + { + auto decor = createEmptyDecoration<IRRequireGLSLExtensionDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); + decor->extensionName = getStringRepresentation(srcInst.m_payload.m_stringIndices[0]); + return decor; + } + case kIRDecorationOp_RequireGLSLVersion: + { + auto decor = createEmptyDecoration<IRRequireGLSLVersionDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == Ser::Inst::PayloadType::UInt32); + decor->languageVersion = Int(srcInst.m_payload.m_uint32); + return decor; + } default: { SLANG_ASSERT(!"Unhandled decoration type"); diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 3ba2aa0dd..f05aeabf6 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -5344,6 +5344,22 @@ namespace Slang } break; + case kIRDecorationOp_RequireGLSLExtension: + { + auto originalDecoration = (IRRequireGLSLExtensionDecoration*)dd; + auto newDecoration = context->builder->addDecoration<IRRequireGLSLExtensionDecoration>(clonedValue); + newDecoration->extensionName = originalDecoration->extensionName; + } + break; + + case kIRDecorationOp_RequireGLSLVersion: + { + auto originalDecoration = (IRRequireGLSLVersionDecoration*)dd; + auto newDecoration = context->builder->addDecoration<IRRequireGLSLVersionDecoration>(clonedValue); + newDecoration->languageVersion = originalDecoration->languageVersion; + } + break; + default: // Don't clone any decorations we don't understand. break; diff --git a/source/slang/ir.h b/source/slang/ir.h index ef257a759..e54a32043 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -154,6 +154,8 @@ enum IRDecorationOp : uint16_t kIRDecorationOp_Transitory, kIRDecorationOp_VulkanRayPayload, kIRDecorationOp_VulkanHitAttributes, + kIRDecorationOp_RequireGLSLVersion, + kIRDecorationOp_RequireGLSLExtension, kIRDecorationOp_CountOf }; diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 7b63f510f..5f3b00b24 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -5112,6 +5112,23 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // for a particular target, then handle that here. addTargetIntrinsicDecorations(irFunc, decl); + // If this declaration requires certain GLSL extension (or a particular GLSL version) + // for it to be usable, then declare that here. + // + // TODO: We should wrap this an `SpecializedForTargetModifier` together into a single + // case for enumerating the "capabilities" that a declaration requires. + // + for(auto extensionMod : decl->GetModifiersOfType<RequiredGLSLExtensionModifier>()) + { + auto decoration = getBuilder()->addDecoration<IRRequireGLSLExtensionDecoration>(irFunc); + decoration->extensionName = getBuilder()->addStringToFree(extensionMod->extensionNameToken.Content); + } + for(auto versionMod : decl->GetModifiersOfType<RequiredGLSLVersionModifier>()) + { + auto decoration = getBuilder()->addDecoration<IRRequireGLSLVersionDecoration>(irFunc); + decoration->languageVersion = Int(getIntegerLiteralValue(versionMod->versionNumberToken)); + } + // For convenience, ensure that any additional global // values that were emitted while outputting the function // body appear before the function itself in the list |
