diff options
| author | Yong He <yonghe@outlook.com> | 2020-09-02 12:21:28 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-02 12:21:28 -0700 |
| commit | a2a7c4d988b2b7126130d9dcbe4ec94e1ce8424b (patch) | |
| tree | 5e9559abd79b9e2f7d4f22f65a77daaaae3eed16 /source | |
| parent | 7f567df6937b33c653c424af3abb20d32eb80561 (diff) | |
Allow unspecialized existential shader parameters (dynamic dispatch). (#1529)
* Allow unspecialized existential shader parameters (dynamic dispatch).
* Fixes.
* Fixes
* disable cuda test
Diffstat (limited to 'source')
| -rwxr-xr-x | source/slang/slang-compiler.cpp | 7 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-emit-cpp.cpp | 19 | ||||
| -rw-r--r-- | source/slang/slang-ir-generics-lowering-context.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-generic-type.cpp | 30 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 31 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-type-layout.cpp | 16 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 14 |
11 files changed, 128 insertions, 16 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 53e529cc7..9b567a7d7 100755 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -2483,13 +2483,14 @@ SlangResult dissassembleDXILUsingDXC( BackEndCompileRequest* compileRequest, EndToEndCompileRequest* endToEndReq) { - // If we are about to generate output code, but we still + // When dynamic dispatch is disabled, the program must + // be fully specialized by now. So we check if we still // have unspecialized generic/existential parameters, - // then there is a problem. + // and report them as an error. // auto program = compileRequest->getProgram(); auto specializationParamCount = program->getSpecializationParamCount(); - if( specializationParamCount != 0 ) + if (compileRequest->disableDynamicDispatch && specializationParamCount != 0) { auto sink = compileRequest->getSink(); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 88bf7d2b3..4ced85ec8 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1205,6 +1205,9 @@ namespace Slang SlangInt targetIndex = 0, slang::LayoutRules rules = slang::LayoutRules::Default, ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW SlangResult SLANG_MCALL getTypeRTTIMangledName( + slang::TypeReflection* type, + ISlangBlob** outNameBlob) override; SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName( slang::TypeReflection* type, slang::TypeReflection* interfaceType, @@ -1763,6 +1766,9 @@ namespace Slang // If true will disable generics/existential value specialization pass. bool disableSpecialization = false; + // If true will disable generating dynamic dispatch code. + bool disableDynamicDispatch = false; + String m_dumpIntermediatePrefix; private: diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 4b9c01c55..231207626 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -3888,8 +3888,9 @@ void CLikeSourceEmitter::computeEmitActions(IRModule* module, List<EmitAction>& { if( as<IRType>(inst) ) { - // Don't emit a type unless it is actually used. - continue; + // Don't emit a type unless it is actually used or is marked public. + if (!inst->findDecoration<IRPublicDecoration>()) + continue; } ensureGlobalInst(&ctx, inst, EmitAction::Level::Definition); diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index 1f40a2640..d22b202f5 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -1615,12 +1615,12 @@ void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable) auto witnessTableItems = witnessTable->getChildren(); _maybeEmitWitnessTableTypeDefinition(interfaceType); - // Define a global variable for the witness table. - m_writer->emit("extern \"C\" "); + // Declare a global variable for the witness table. + m_writer->emit("extern \"C\" { SLANG_PRELUDE_SHARED_LIB_EXPORT extern "); emitSimpleType(interfaceType); m_writer->emit(" "); m_writer->emit(getName(witnessTable)); - m_writer->emit(";\n"); + m_writer->emit("; }\n"); // The actual definition of this witness table global variable // is deferred until the entire `Context` class is emitted, so @@ -1636,6 +1636,9 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions() { auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand(0)); List<IRWitnessTableEntry*> sortedWitnessTableEntries = getSortedWitnessTableEntries(witnessTable); + m_writer->emit("extern \"C\"\n{\n"); + m_writer->indent(); + m_writer->emit("SLANG_PRELUDE_SHARED_LIB_EXPORT\n"); emitSimpleType(interfaceType); m_writer->emit(" "); m_writer->emit(getName(witnessTable)); @@ -1679,6 +1682,8 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions() } m_writer->dedent(); m_writer->emit("\n};\n"); + m_writer->dedent(); + m_writer->emit("\n}\n"); } } @@ -1698,18 +1703,18 @@ void CPPSourceEmitter::emitInterface(IRInterfaceType* interfaceType) void CPPSourceEmitter::emitRTTIObject(IRRTTIObject* rttiObject) { // Declare the type info object as `extern "C"` first. - m_writer->emit("extern \"C\" TypeInfo "); + m_writer->emit("extern \"C\"{ SLANG_PRELUDE_SHARED_LIB_EXPORT extern TypeInfo "); m_writer->emit(getName(rttiObject)); - m_writer->emit(";\n"); + m_writer->emit("; }\n"); // Now actually define the object. - m_writer->emit("TypeInfo "); + m_writer->emit("extern \"C\" { SLANG_PRELUDE_SHARED_LIB_EXPORT TypeInfo "); m_writer->emit(getName(rttiObject)); m_writer->emit(" = {"); auto typeSizeDecoration = rttiObject->findDecoration<IRRTTITypeSizeDecoration>(); SLANG_ASSERT(typeSizeDecoration); m_writer->emit(typeSizeDecoration->getTypeSize()); - m_writer->emit("};\n"); + m_writer->emit("}; }\n"); } diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp index 26581c653..b7e2917d5 100644 --- a/source/slang/slang-ir-generics-lowering-context.cpp +++ b/source/slang/slang-ir-generics-lowering-context.cpp @@ -75,6 +75,12 @@ namespace Slang String rttiObjName = exportDecoration->getMangledName(); builder->addExportDecoration(result, rttiObjName.getUnownedSlice()); } + // Make sure the RTTI object for a public struct type has public visiblity. + if (typeInst->findDecoration<IRPublicDecoration>()) + { + builder->addPublicDecoration(result); + builder->addKeepAliveDecoration(result); + } mapTypeToRTTIObject[typeInst] = result; return result; } diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index ecffbd4d7..2197456a1 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -259,6 +259,7 @@ IR_SIMPLE_DECORATION(EarlyDepthStencilDecoration) IR_SIMPLE_DECORATION(GloballyCoherentDecoration) IR_SIMPLE_DECORATION(PreciseDecoration) IR_SIMPLE_DECORATION(PublicDecoration) +IR_SIMPLE_DECORATION(KeepAliveDecoration) struct IROutputControlPointsDecoration : IRDecoration @@ -2431,6 +2432,11 @@ struct IRBuilder addDecoration(value, kIROp_KeepAliveDecoration); } + void addPublicDecoration(IRInst* value) + { + addDecoration(value, kIROp_PublicDecoration); + } + /// Add a decoration that indicates that the given `inst` depends on the given `dependency`. /// /// This decoration can be used to ensure that a value that an instruction diff --git a/source/slang/slang-ir-lower-generic-type.cpp b/source/slang/slang-ir-lower-generic-type.cpp index 0b0973274..caf0f82bf 100644 --- a/source/slang/slang-ir-lower-generic-type.cpp +++ b/source/slang/slang-ir-lower-generic-type.cpp @@ -10,13 +10,22 @@ namespace Slang { // This is a subpass of generics lowering IR transformation. // This pass lowers all generic/polymorphic types into IRAnyValueType. - struct GenericVarLoweringContext + struct GenericTypeLoweringContext { SharedGenericsLoweringContext* sharedContext; void processInst(IRInst* inst) { - // If inst is a type itself, keep its type. + // Ensure public struct types has RTTI object defined. + if (as<IRStructType>(inst)) + { + if (inst->findDecoration<IRPublicDecoration>()) + { + sharedContext->maybeEmitRTTIObject(inst); + } + } + + // Don't modify type insts themselves. if (as<IRType>(inst)) return; @@ -28,6 +37,21 @@ namespace Slang auto newType = sharedContext->lowerType(builder, inst->getFullType()); if (newType != inst->getFullType()) inst->setFullType((IRType*)newType); + + switch (inst->op) + { + default: + break; + case kIROp_StructField: + { + // Translate the struct field type. + auto structField = static_cast<IRStructField*>(inst); + auto loweredFieldType = + sharedContext->lowerType(builder, structField->getFieldType()); + structField->setOperand(1, loweredFieldType); + } + break; + } } void processModule() @@ -62,7 +86,7 @@ namespace Slang void lowerGenericType(SharedGenericsLoweringContext* sharedContext) { - GenericVarLoweringContext context; + GenericTypeLoweringContext context; context.sharedContext = sharedContext; context.processModule(); } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 539027e74..ee5338236 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1038,6 +1038,11 @@ static void addLinkageDecoration( { builder->addExportDecoration(inst, mangledName); } + if (decl->findModifier<PublicModifier>()) + { + builder->addPublicDecoration(inst); + builder->addKeepAliveDecoration(inst); + } } static void addLinkageDecoration( @@ -5161,6 +5166,15 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> return LoweredValInfo::simple(inst); } + bool isPublicType(Type* type) + { + if (auto declRefType = as<DeclRefType>(type)) + { + if (declRefType->declRef.getDecl()->findModifier<PublicModifier>()) + return true; + } + return false; + } void lowerWitnessTable( IRGenContext* subContext, @@ -5211,6 +5225,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> astReqWitnessTable->witnessedType, astReqWitnessTable->baseType); subBuilder->addExportDecoration(irSatisfyingWitnessTable, mangledName.getUnownedSlice()); + if (isPublicType(astReqWitnessTable->witnessedType)) + { + subBuilder->addPublicDecoration(irSatisfyingWitnessTable); + subBuilder->addKeepAliveDecoration(irSatisfyingWitnessTable); + } + // Recursively lower the sub-table. lowerWitnessTable( subContext, @@ -5327,6 +5347,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // Create the IR-level witness table auto irWitnessTable = subBuilder->createWitnessTable(irWitnessTableBaseType); addLinkageDecoration(context, irWitnessTable, inheritanceDecl, mangledName.getUnownedSlice()); + if (parentDecl->findModifier<PublicModifier>()) + { + subBuilder->addPublicDecoration(irWitnessTable); + subBuilder->addKeepAliveDecoration(irWitnessTable); + } // Register the value now, rather than later, to avoid any possible infinite recursion. setGlobalValue(context, inheritanceDecl, LoweredValInfo::simple(irWitnessTable)); @@ -6154,6 +6179,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> SLANG_UNREACHABLE("associatedtype should have been handled by visitAssocTypeDecl."); } + bool isPublicType = decl->findModifier<PublicModifier>() != nullptr; + // Given a declaration of a type, we need to make sure // to output "witness tables" for any interfaces this // type has declared conformance to. @@ -6171,11 +6198,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // Emit any generics that should wrap the actual type. auto outerGeneric = emitOuterGenerics(subContext, decl, decl); - IRStructType* irStruct = subBuilder->createStructType(); addNameHint(context, irStruct, decl); addLinkageDecoration(context, irStruct, decl); + subBuilder->setInsertInto(irStruct); // A `struct` that inherits from another `struct` must start @@ -6183,6 +6210,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // for( auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>() ) { + if (isPublicType) + ensureDecl(context, inheritanceDecl); auto superType = inheritanceDecl->base; if(auto superDeclRefType = as<DeclRefType>(superType)) { diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index cae3397dd..1fe78977a 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -563,6 +563,10 @@ struct OptionsParser { requestImpl->getBackEndReq()->disableSpecialization = true; } + else if (argStr == "-disable-dynamic-dispatch") + { + requestImpl->getBackEndReq()->disableDynamicDispatch = true; + } else if (argStr == "-verbose-paths") { requestImpl->getSink()->setFlag(DiagnosticSink::Flag::VerbosePath); diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 9b00fc88c..dbdfaf79c 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -3613,6 +3613,22 @@ static TypeLayoutResult _createTypeLayout( typeLayout->type = type; typeLayout->rules = rules; + if (isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq)) + { + LayoutSize fixedSize = 16; + if (auto anyValueAttr = + interfaceDeclRef.getDecl()->findModifier<AnyValueSizeAttribute>()) + { + fixedSize += anyValueAttr->size; + } + else + { + // The interface type does not have an `[anyValueSize]` attribute, + // assume a default of 8 bytes. + fixedSize += 8; + } + typeLayout->addResourceUsage(LayoutResourceKind::Uniform, fixedSize); + } typeLayout->addResourceUsage(LayoutResourceKind::ExistentialTypeParam, 1); typeLayout->addResourceUsage(LayoutResourceKind::ExistentialObjectParam, 1); diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 889ac8203..b9381eec3 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -623,6 +623,20 @@ SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL Linkage::getTypeLayout( return asExternal(typeLayout); } +SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::getTypeRTTIMangledName( + slang::TypeReflection* type, ISlangBlob** outNameBlob) +{ + auto internalType = asInternal(type); + if (auto declRefType = as<DeclRefType>(internalType)) + { + auto name = getMangledName(internalType->getASTBuilder(), declRefType->declRef); + Slang::ComPtr<ISlangBlob> blob = Slang::StringUtil::createStringBlob(name); + *outNameBlob = blob.detach(); + return SLANG_OK; + } + return SLANG_FAIL; +} + SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::getTypeConformanceWitnessMangledName( slang::TypeReflection* type, slang::TypeReflection* interfaceType, ISlangBlob** outNameBlob) { |
