summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-09-02 12:21:28 -0700
committerGitHub <noreply@github.com>2020-09-02 12:21:28 -0700
commita2a7c4d988b2b7126130d9dcbe4ec94e1ce8424b (patch)
tree5e9559abd79b9e2f7d4f22f65a77daaaae3eed16 /source
parent7f567df6937b33c653c424af3abb20d32eb80561 (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-xsource/slang/slang-compiler.cpp7
-rwxr-xr-xsource/slang/slang-compiler.h6
-rw-r--r--source/slang/slang-emit-c-like.cpp5
-rw-r--r--source/slang/slang-emit-cpp.cpp19
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp6
-rw-r--r--source/slang/slang-ir-insts.h6
-rw-r--r--source/slang/slang-ir-lower-generic-type.cpp30
-rw-r--r--source/slang/slang-lower-to-ir.cpp31
-rw-r--r--source/slang/slang-options.cpp4
-rw-r--r--source/slang/slang-type-layout.cpp16
-rw-r--r--source/slang/slang.cpp14
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)
{