From d6130baa8528c0a5b2e1b10b87fe02d8fc1a1b1a Mon Sep 17 00:00:00 2001 From: Yong He Date: Mon, 20 Nov 2017 05:28:22 -0500 Subject: fixup global generic parameters 1. simplify RoundUpToAlignment() 2. add new a render-compute test case to cover the situation where the entry-point interface (parameter/return types of an entry-point function) is dependent on the global generic type. 3. initial fixes to get this test case to compile (but is not producing correct HLSL output yet) --- source/slang/ir.cpp | 23 ++++++++++++++++++++++- source/slang/parameter-binding.cpp | 38 ++++++++++++++++++++++++++------------ source/slang/syntax.cpp | 17 ++++++++++++++++- source/slang/syntax.h | 1 + source/slang/type-layout.h | 2 +- 5 files changed, 66 insertions(+), 15 deletions(-) (limited to 'source/slang') diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 2d3127a61..f5f52e08a 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -3103,10 +3103,22 @@ namespace Slang IRGlobalVar* cloneGlobalVar(IRSpecContext* context, IRGlobalVar* originalVar); IRFunc* cloneFunc(IRSpecContext* context, IRFunc* originalFunc); IRWitnessTable* cloneWitnessTable(IRSpecContext* context, IRWitnessTable* originalVar); + RefPtr cloneSubstitutions( + IRSpecContext* context, + Substitutions* subst); RefPtr IRSpecContext::maybeCloneType(Type* originalType) { - return originalType->Substitute(subst).As(); + auto rsType = originalType->Substitute(subst).As(); + if (auto declRefType = rsType.As()) + { + if (subst) + { + auto newSubst = cloneSubstitutions(this, subst); + insertSubstAtBottom(declRefType->declRef.substitutions, newSubst); + } + } + return rsType; } IRValue* IRSpecContext::maybeCloneValue(IRValue* originalValue) @@ -3243,6 +3255,15 @@ namespace Slang newSubst->outer = cloneSubstitutions(context, subst->outer); return newSubst; } + else if (auto genTypeSubst = dynamic_cast(subst)) + { + RefPtr newSubst = new GlobalGenericParamSubstitution(); + newSubst->actualType = genTypeSubst->actualType; + newSubst->paramDecl = genTypeSubst->paramDecl; + newSubst->witnessTables = genTypeSubst->witnessTables; + newSubst->outer = cloneSubstitutions(context, subst->outer); + return newSubst; + } else SLANG_UNREACHABLE("unimplemented cloneSubstitution"); UNREACHABLE_RETURN(nullptr); diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index 836ed254f..0daa2abc7 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -1425,6 +1425,16 @@ static RefPtr processEntryPointParameter( return structLayout; } + else if (auto globalGenericParam = declRef.As()) + { + auto genParamTypeLayout = new GenericParamTypeLayout(); + // we should have already populated ProgramLayout::genericEntryPointParams list at this point, + // so we can find the index of this generic param decl in the list + genParamTypeLayout->type = type; + genParamTypeLayout->paramIndex = findGenericParam(context->shared->programLayout->globalGenericParams, globalGenericParam.getDecl()); + genParamTypeLayout->findOrAddResourceInfo(LayoutResourceKind::GenericResource)->count++; + return genParamTypeLayout; + } else { SLANG_UNEXPECTED("unhandled type kind"); @@ -1442,7 +1452,8 @@ static RefPtr processEntryPointParameter( static void collectEntryPointParameters( ParameterBindingContext* context, - EntryPointRequest* entryPoint) + EntryPointRequest* entryPoint, + Substitutions* typeSubst) { FuncDecl* entryPointFuncDecl = entryPoint->decl; if (!entryPointFuncDecl) @@ -1507,7 +1518,7 @@ static void collectEntryPointParameters( auto paramTypeLayout = processEntryPointParameterWithPossibleSemantic( context, paramDecl.Ptr(), - paramDecl->type.type, + paramDecl->type.type->Substitute(typeSubst).As(), state, paramVarLayout); @@ -1539,7 +1550,7 @@ static void collectEntryPointParameters( auto resultTypeLayout = processEntryPointParameterWithPossibleSemantic( context, entryPointFuncDecl, - resultType, + resultType->Substitute(typeSubst).As(), state, resultLayout); @@ -1632,7 +1643,7 @@ static void collectParameters( for( auto& entryPoint : translationUnit->entryPoints ) { context->stage = entryPoint->profile.GetStage(); - collectEntryPointParameters(context, entryPoint.Ptr()); + collectEntryPointParameters(context, entryPoint.Ptr(), nullptr); } } @@ -1891,13 +1902,7 @@ RefPtr specializeProgramLayout( newProgramLayout = new ProgramLayout(); newProgramLayout->bindingForHackSampler = programLayout->bindingForHackSampler; newProgramLayout->hackSamplerVar = programLayout->hackSamplerVar; - for (auto & entryPoint : programLayout->entryPoints) - { - RefPtr newEntryPoint = new EntryPointLayout(*entryPoint); - // TODO: for now just copy existing entry point layouts, but we eventually need to - // specialize these as well... - newProgramLayout->entryPoints.Add(newEntryPoint); - } + newProgramLayout->globalGenericParams = programLayout->globalGenericParams; List> paramTypeLayouts; auto globalStructLayout = getGlobalStructLayout(programLayout); @@ -1919,7 +1924,7 @@ RefPtr specializeProgramLayout( SharedParameterBindingContext sharedContext; sharedContext.compileRequest = targetReq->compileRequest; sharedContext.defaultLayoutRules = layoutContext.getRulesFamily(); - sharedContext.programLayout = programLayout; + sharedContext.programLayout = newProgramLayout; // Create a sub-context to collect parameters that get // declared into the global scope @@ -1928,6 +1933,15 @@ RefPtr specializeProgramLayout( context.translationUnit = nullptr; context.layoutContext = layoutContext; + + for (auto & translationUnit : targetReq->compileRequest->translationUnits) + { + for (auto & entryPoint : translationUnit->entryPoints) + { + collectEntryPointParameters(&context, entryPoint, typeSubst); + } + } + auto constantBufferRules = context.getRulesFamily()->getConstantBufferRules(); structLayout->rules = constantBufferRules; diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index e43dd9074..badfaea4f 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -1709,7 +1709,22 @@ void Type::accept(IValVisitor* visitor, void* extra) return sb.ProduceString(); } - + void insertSubstAtBottom(RefPtr & substHead, RefPtr substToInsert) + { + if (!substHead) + { + substHead = substToInsert; + return; + } + auto subst = substHead; + RefPtr lastSubst = subst; + while (subst->outer) + { + lastSubst = subst; + subst = subst->outer; + } + lastSubst->outer = substToInsert; + } void insertSubstAtTop(DeclRefBase & declRef, RefPtr substToInsert) { diff --git a/source/slang/syntax.h b/source/slang/syntax.h index b4d550ef5..f3690d9ae 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -1156,6 +1156,7 @@ namespace Slang Session* session, Decl* decl); + void insertSubstAtBottom(RefPtr & substHead, RefPtr substToInsert); RefPtr getNewThisTypeSubst(DeclRefBase & declRef); RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry); void removeSubstitution(DeclRefBase & declRef, RefPtr subst); diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h index 4ce6dc355..07530bdfc 100644 --- a/source/slang/type-layout.h +++ b/source/slang/type-layout.h @@ -676,7 +676,7 @@ createStructuredBufferTypeLayout( RefPtr structuredBufferType, RefPtr elementType); - +int findGenericParam(List> & genericParameters, GlobalGenericParamDecl * decl); // } -- cgit v1.2.3 From 64108c88836ed6b0335b000d4d127113f6840010 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 21 Nov 2017 19:26:17 -0500 Subject: Add logic to propagate GlobalGenericParamSubstitution --- source/slang/ir.cpp | 10 +++++++++- source/slang/syntax.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'source/slang') diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index f5f52e08a..109bae353 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -3109,7 +3109,7 @@ namespace Slang RefPtr IRSpecContext::maybeCloneType(Type* originalType) { - auto rsType = originalType->Substitute(subst).As(); + auto rsType = originalType->GetCanonicalType()->Substitute(subst).As(); if (auto declRefType = rsType.As()) { if (subst) @@ -3118,6 +3118,14 @@ namespace Slang insertSubstAtBottom(declRefType->declRef.substitutions, newSubst); } } + else if (auto funcType = rsType.As()) + { + RefPtr newFuncType = new FuncType(); + newFuncType->setSession(funcType->getSession()); + newFuncType->resultType = maybeCloneType(funcType->resultType); + for (auto paramType : funcType->paramTypes) + newFuncType->paramTypes.Add(maybeCloneType(paramType)); + } return rsType; } diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index badfaea4f..2c214a332 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -1309,9 +1309,39 @@ void Type::accept(IValVisitor* visitor, void* extra) UNREACHABLE_RETURN(expr); } + bool hasGlobalGenericSubst(Substitutions * destSubst, GlobalGenericParamSubstitution * genSubst) + { + while (destSubst) + { + if (auto globalParamSubst = dynamic_cast(destSubst)) + { + if (globalParamSubst->paramDecl == genSubst->paramDecl) + return true; + } + destSubst = destSubst->outer; + } + return false; + } + void insertGlobalGenericSubstitutions(RefPtr & destSubst, Substitutions * srcSubst) + { + while (srcSubst) + { + if (auto globalGenSubst = dynamic_cast(srcSubst)) + { + if (!hasGlobalGenericSubst(destSubst, globalGenSubst)) + { + RefPtr cpyGlobalGenSubst = new GlobalGenericParamSubstitution(*globalGenSubst); + cpyGlobalGenSubst->outer = nullptr; + insertSubstAtBottom(destSubst, cpyGlobalGenSubst); + } + } + srcSubst = srcSubst->outer; + } + } DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff) { + insertGlobalGenericSubstitutions(substitutions, subst); if (!substitutions) return *this; int diff = 0; -- cgit v1.2.3