|
@@ -316,12 +316,18 @@ struct DxilLinkJob {
|
|
DxilLinkJob(LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) : m_ctx(Ctx), m_valMajor(valMajor), m_valMinor(valMinor) {}
|
|
DxilLinkJob(LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) : m_ctx(Ctx), m_valMajor(valMajor), m_valMinor(valMinor) {}
|
|
std::unique_ptr<llvm::Module>
|
|
std::unique_ptr<llvm::Module>
|
|
Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
- StringRef profile);
|
|
|
|
|
|
+ const ShaderModel *pSM);
|
|
|
|
+ std::unique_ptr<llvm::Module> LinkToLib(const ShaderModel *pSM);
|
|
void RunPreparePass(llvm::Module &M);
|
|
void RunPreparePass(llvm::Module &M);
|
|
void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
|
|
void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
|
|
void AddFunction(llvm::Function *F);
|
|
void AddFunction(llvm::Function *F);
|
|
|
|
|
|
private:
|
|
private:
|
|
|
|
+ void AddDxilOperations(Module *pM);
|
|
|
|
+ bool AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap);
|
|
|
|
+ void CloneFunctions(ValueToValueMapTy &vmap);
|
|
|
|
+ void AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap,
|
|
|
|
+ std::unordered_set<Function *> &initFuncSet);
|
|
bool AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV);
|
|
bool AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV);
|
|
void AddResourceToDM(DxilModule &DM);
|
|
void AddResourceToDM(DxilModule &DM);
|
|
std::unordered_map<DxilFunctionLinkInfo *, DxilLib *> m_functionDefs;
|
|
std::unordered_map<DxilFunctionLinkInfo *, DxilLib *> m_functionDefs;
|
|
@@ -491,71 +497,97 @@ void DxilLinkJob::AddResourceToDM(DxilModule &DM) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-std::unique_ptr<Module>
|
|
|
|
-DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
|
|
- StringRef profile) {
|
|
|
|
-
|
|
|
|
- Function *entryFunc = entryLinkPair.first->func;
|
|
|
|
- DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
|
|
|
|
- if (!entryDM.HasDxilFunctionProps(entryFunc)) {
|
|
|
|
- // Cannot get function props.
|
|
|
|
- m_ctx.emitError(Twine(kNoEntryProps) + entryFunc->getName());
|
|
|
|
- return nullptr;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- DxilFunctionProps props = entryDM.GetDxilFunctionProps(entryFunc);
|
|
|
|
- if (props.shaderKind == DXIL::ShaderKind::Library ||
|
|
|
|
- props.shaderKind == DXIL::ShaderKind::Invalid ||
|
|
|
|
- (props.shaderKind >= DXIL::ShaderKind::RayGeneration &&
|
|
|
|
- props.shaderKind <= DXIL::ShaderKind::Callable)) {
|
|
|
|
- m_ctx.emitError(profile + Twine(kInvalidProfile));
|
|
|
|
- // Invalid profile.
|
|
|
|
- return nullptr;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const ShaderModel *pSM = ShaderModel::GetByName(profile.data());
|
|
|
|
- if (pSM->GetKind() != props.shaderKind) {
|
|
|
|
- // Shader kind mismatch.
|
|
|
|
- m_ctx.emitError(Twine(kShaderKindMismatch) + profile + " and " +
|
|
|
|
- ShaderModel::GetKindName(props.shaderKind));
|
|
|
|
- return nullptr;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Create new module.
|
|
|
|
- std::unique_ptr<Module> pM =
|
|
|
|
- llvm::make_unique<Module>(entryFunc->getName(), entryDM.GetCtx());
|
|
|
|
- // Set target.
|
|
|
|
- pM->setTargetTriple(entryDM.GetModule()->getTargetTriple());
|
|
|
|
- // Add dxil operation functions before create DxilModule.
|
|
|
|
|
|
+void DxilLinkJob::AddDxilOperations(Module *pM) {
|
|
for (auto &it : m_dxilFunctions) {
|
|
for (auto &it : m_dxilFunctions) {
|
|
Function *F = it.second;
|
|
Function *F = it.second;
|
|
Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
|
|
Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
|
|
- F->getName(), pM.get());
|
|
|
|
|
|
+ F->getName(), pM);
|
|
NewF->setAttributes(F->getAttributes());
|
|
NewF->setAttributes(F->getAttributes());
|
|
m_newFunctions[NewF->getName()] = NewF;
|
|
m_newFunctions[NewF->getName()] = NewF;
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
|
|
- // Create DxilModule.
|
|
|
|
- const bool bSkipInit = true;
|
|
|
|
- DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
|
|
|
|
- DM.SetShaderModel(pSM);
|
|
|
|
|
|
+bool DxilLinkJob::AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap) {
|
|
|
|
+ DxilTypeSystem &typeSys = DM.GetTypeSystem();
|
|
|
|
+ Module *pM = DM.GetModule();
|
|
|
|
+ bool bSuccess = true;
|
|
|
|
+ for (auto &it : m_functionDefs) {
|
|
|
|
+ DxilFunctionLinkInfo *linkInfo = it.first;
|
|
|
|
+ DxilLib *pLib = it.second;
|
|
|
|
+ DxilModule &tmpDM = pLib->GetDxilModule();
|
|
|
|
+ DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
|
|
|
|
+ for (GlobalVariable *GV : linkInfo->usedGVs) {
|
|
|
|
+ // Skip added globals.
|
|
|
|
+ if (m_newGlobals.count(GV->getName())) {
|
|
|
|
+ if (vmap.find(GV) == vmap.end()) {
|
|
|
|
+ if (DxilResourceBase *res = pLib->GetResource(GV)) {
|
|
|
|
+ // For resource of same name, if class and type match, just map to
|
|
|
|
+ // same NewGV.
|
|
|
|
+ GlobalVariable *NewGV = m_newGlobals[GV->getName()];
|
|
|
|
+ if (AddResource(res, NewGV)) {
|
|
|
|
+ vmap[GV] = NewGV;
|
|
|
|
+ } else {
|
|
|
|
+ bSuccess = false;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
- // Set Validator version, verifying that it supports the requested profile
|
|
|
|
- unsigned minValMajor, minValMinor;
|
|
|
|
- DM.GetMinValidatorVersion(minValMajor, minValMinor);
|
|
|
|
- if (minValMajor > m_valMajor || (minValMajor == m_valMajor && minValMinor > m_valMinor)) {
|
|
|
|
- m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
|
|
|
|
- return nullptr;
|
|
|
|
|
|
+ // Redefine of global.
|
|
|
|
+ m_ctx.emitError(Twine(kRedefineGlobal) + GV->getName());
|
|
|
|
+ bSuccess = false;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Constant *Initializer = nullptr;
|
|
|
|
+ if (GV->hasInitializer())
|
|
|
|
+ Initializer = GV->getInitializer();
|
|
|
|
+
|
|
|
|
+ Type *Ty = GV->getType()->getElementType();
|
|
|
|
+ GlobalVariable *NewGV = new GlobalVariable(
|
|
|
|
+ *pM, Ty, GV->isConstant(), GV->getLinkage(), Initializer,
|
|
|
|
+ GV->getName(),
|
|
|
|
+ /*InsertBefore*/ nullptr, GV->getThreadLocalMode(),
|
|
|
|
+ GV->getType()->getAddressSpace(), GV->isExternallyInitialized());
|
|
|
|
+
|
|
|
|
+ m_newGlobals[GV->getName()] = NewGV;
|
|
|
|
+
|
|
|
|
+ vmap[GV] = NewGV;
|
|
|
|
+
|
|
|
|
+ typeSys.CopyTypeAnnotation(Ty, tmpTypeSys);
|
|
|
|
+
|
|
|
|
+ if (DxilResourceBase *res = pLib->GetResource(GV)) {
|
|
|
|
+ bSuccess &= AddResource(res, NewGV);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- DM.SetValidatorVersion(m_valMajor, m_valMinor);
|
|
|
|
|
|
+ return bSuccess;
|
|
|
|
+}
|
|
|
|
|
|
- // Add type sys
|
|
|
|
- DxilTypeSystem &typeSys = DM.GetTypeSystem();
|
|
|
|
|
|
+void DxilLinkJob::CloneFunctions(ValueToValueMapTy &vmap) {
|
|
|
|
+ for (auto &it : m_functionDefs) {
|
|
|
|
+ DxilFunctionLinkInfo *linkInfo = it.first;
|
|
|
|
|
|
- ValueToValueMapTy vmap;
|
|
|
|
|
|
+ Function *F = linkInfo->func;
|
|
|
|
+ Function *NewF = m_newFunctions[F->getName()];
|
|
|
|
|
|
- std::unordered_set<Function *> initFuncSet;
|
|
|
|
- // Add function
|
|
|
|
|
|
+ // Add dxil functions to vmap.
|
|
|
|
+ for (Function *UsedF : linkInfo->usedFunctions) {
|
|
|
|
+ if (!vmap.count(UsedF)) {
|
|
|
|
+ // Extern function need match by name
|
|
|
|
+ DXASSERT(m_newFunctions.count(UsedF->getName()),
|
|
|
|
+ "Must have new function.");
|
|
|
|
+ vmap[UsedF] = m_newFunctions[UsedF->getName()];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ CloneFunction(F, NewF, vmap);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void DxilLinkJob::AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap,
|
|
|
|
+ std::unordered_set<Function *> &initFuncSet) {
|
|
|
|
+ DxilTypeSystem &typeSys = DM.GetTypeSystem();
|
|
|
|
+ Module *pM = DM.GetModule();
|
|
for (auto &it : m_functionDefs) {
|
|
for (auto &it : m_functionDefs) {
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilLib *pLib = it.second;
|
|
DxilLib *pLib = it.second;
|
|
@@ -564,7 +596,7 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
|
|
|
|
Function *F = linkInfo->func;
|
|
Function *F = linkInfo->func;
|
|
Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
|
|
Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
|
|
- F->getName(), pM.get());
|
|
|
|
|
|
+ F->getName(), pM);
|
|
NewF->setAttributes(F->getAttributes());
|
|
NewF->setAttributes(F->getAttributes());
|
|
|
|
|
|
if (!NewF->hasFnAttribute(llvm::Attribute::NoInline))
|
|
if (!NewF->hasFnAttribute(llvm::Attribute::NoInline))
|
|
@@ -583,6 +615,50 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
|
|
|
|
vmap[F] = NewF;
|
|
vmap[F] = NewF;
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+std::unique_ptr<Module>
|
|
|
|
+DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
|
|
+ const ShaderModel *pSM) {
|
|
|
|
+ Function *entryFunc = entryLinkPair.first->func;
|
|
|
|
+ DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
|
|
|
|
+ if (!entryDM.HasDxilFunctionProps(entryFunc)) {
|
|
|
|
+ // Cannot get function props.
|
|
|
|
+ m_ctx.emitError(Twine(kNoEntryProps) + entryFunc->getName());
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DxilFunctionProps props = entryDM.GetDxilFunctionProps(entryFunc);
|
|
|
|
+
|
|
|
|
+ if (pSM->GetKind() != props.shaderKind) {
|
|
|
|
+ // Shader kind mismatch.
|
|
|
|
+ m_ctx.emitError(Twine(kShaderKindMismatch) +
|
|
|
|
+ ShaderModel::GetKindName(pSM->GetKind()) + " and " +
|
|
|
|
+ ShaderModel::GetKindName(props.shaderKind));
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Create new module.
|
|
|
|
+ std::unique_ptr<Module> pM =
|
|
|
|
+ llvm::make_unique<Module>(entryFunc->getName(), entryDM.GetCtx());
|
|
|
|
+ // Set target.
|
|
|
|
+ pM->setTargetTriple(entryDM.GetModule()->getTargetTriple());
|
|
|
|
+ // Add dxil operation functions before create DxilModule.
|
|
|
|
+ AddDxilOperations(pM.get());
|
|
|
|
+
|
|
|
|
+ // Create DxilModule.
|
|
|
|
+ const bool bSkipInit = true;
|
|
|
|
+ DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
|
|
|
|
+ DM.SetShaderModel(pSM);
|
|
|
|
+
|
|
|
|
+ // Set Validator version.
|
|
|
|
+ DM.SetValidatorVersion(m_valMajor, m_valMinor);
|
|
|
|
+
|
|
|
|
+ ValueToValueMapTy vmap;
|
|
|
|
+
|
|
|
|
+ std::unordered_set<Function *> initFuncSet;
|
|
|
|
+ // Add function
|
|
|
|
+ AddFunctions(DM, vmap, initFuncSet);
|
|
|
|
|
|
// Set Entry
|
|
// Set Entry
|
|
Function *NewEntryFunc = m_newFunctions[entryFunc->getName()];
|
|
Function *NewEntryFunc = m_newFunctions[entryFunc->getName()];
|
|
@@ -613,93 +689,101 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
|
// Debug info.
|
|
// Debug info.
|
|
|
|
|
|
// Add global
|
|
// Add global
|
|
- bool bSuccess = true;
|
|
|
|
|
|
+ bool bSuccess = AddGlobals(DM, vmap);
|
|
|
|
+ if (!bSuccess)
|
|
|
|
+ return nullptr;
|
|
|
|
+
|
|
|
|
+ // Clone functions.
|
|
|
|
+ CloneFunctions(vmap);
|
|
|
|
+
|
|
|
|
+ // Call global constrctor.
|
|
|
|
+ IRBuilder<> Builder(
|
|
|
|
+ DM.GetEntryFunction()->getEntryBlock().getFirstInsertionPt());
|
|
for (auto &it : m_functionDefs) {
|
|
for (auto &it : m_functionDefs) {
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilLib *pLib = it.second;
|
|
DxilLib *pLib = it.second;
|
|
- DxilModule &tmpDM = pLib->GetDxilModule();
|
|
|
|
- DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
|
|
|
|
- for (GlobalVariable *GV : linkInfo->usedGVs) {
|
|
|
|
- // Skip added globals.
|
|
|
|
- if (m_newGlobals.count(GV->getName())) {
|
|
|
|
- if (vmap.find(GV) == vmap.end()) {
|
|
|
|
- if (DxilResourceBase *res = pLib->GetResource(GV)) {
|
|
|
|
- // For resource of same name, if class and type match, just map to
|
|
|
|
- // same NewGV.
|
|
|
|
- GlobalVariable *NewGV = m_newGlobals[GV->getName()];
|
|
|
|
- if (AddResource(res, NewGV)) {
|
|
|
|
- vmap[GV] = NewGV;
|
|
|
|
- } else {
|
|
|
|
- bSuccess = false;
|
|
|
|
- }
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Redefine of global.
|
|
|
|
- m_ctx.emitError(Twine(kRedefineGlobal) + GV->getName());
|
|
|
|
- bSuccess = false;
|
|
|
|
- }
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- Constant *Initializer = nullptr;
|
|
|
|
- if (GV->hasInitializer())
|
|
|
|
- Initializer = GV->getInitializer();
|
|
|
|
|
|
|
|
- Type *Ty = GV->getType()->getElementType();
|
|
|
|
- GlobalVariable *NewGV = new GlobalVariable(
|
|
|
|
- *pM, Ty, GV->isConstant(),
|
|
|
|
- GV->getLinkage(), Initializer, GV->getName(),
|
|
|
|
- /*InsertBefore*/ nullptr, GV->getThreadLocalMode(),
|
|
|
|
- GV->getType()->getAddressSpace(), GV->isExternallyInitialized());
|
|
|
|
|
|
+ Function *F = linkInfo->func;
|
|
|
|
+ if (pLib->IsInitFunc(F)) {
|
|
|
|
+ Function *NewF = m_newFunctions[F->getName()];
|
|
|
|
+ Builder.CreateCall(NewF);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- m_newGlobals[GV->getName()] = NewGV;
|
|
|
|
|
|
+ // Refresh intrinsic cache.
|
|
|
|
+ DM.GetOP()->RefreshCache();
|
|
|
|
|
|
- vmap[GV] = NewGV;
|
|
|
|
|
|
+ // Add resource to DM.
|
|
|
|
+ // This should be after functions cloned.
|
|
|
|
+ AddResourceToDM(DM);
|
|
|
|
|
|
- typeSys.CopyTypeAnnotation(Ty, tmpTypeSys);
|
|
|
|
|
|
+ RunPreparePass(*pM);
|
|
|
|
|
|
- if (DxilResourceBase *res = pLib->GetResource(GV)) {
|
|
|
|
- bSuccess &= AddResource(res, NewGV);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ return pM;
|
|
|
|
+}
|
|
|
|
|
|
- if (!bSuccess)
|
|
|
|
- return nullptr;
|
|
|
|
|
|
+std::unique_ptr<Module>
|
|
|
|
+DxilLinkJob::LinkToLib(const ShaderModel *pSM) {
|
|
|
|
+ DxilLib *pLib = m_functionDefs.begin()->second;
|
|
|
|
+ DxilModule &tmpDM = pLib->GetDxilModule();
|
|
|
|
+ // Create new module.
|
|
|
|
+ std::unique_ptr<Module> pM =
|
|
|
|
+ llvm::make_unique<Module>("merged_lib", tmpDM.GetCtx());
|
|
|
|
+ // Set target.
|
|
|
|
+ pM->setTargetTriple(tmpDM.GetModule()->getTargetTriple());
|
|
|
|
+ // Add dxil operation functions before create DxilModule.
|
|
|
|
+ AddDxilOperations(pM.get());
|
|
|
|
|
|
- // Clone functions.
|
|
|
|
- for (auto &it : m_functionDefs) {
|
|
|
|
- DxilFunctionLinkInfo *linkInfo = it.first;
|
|
|
|
|
|
+ // Create DxilModule.
|
|
|
|
+ const bool bSkipInit = true;
|
|
|
|
+ DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
|
|
|
|
+ DM.SetShaderModel(pSM);
|
|
|
|
|
|
- Function *F = linkInfo->func;
|
|
|
|
- Function *NewF = m_newFunctions[F->getName()];
|
|
|
|
|
|
+ // Set Validator version.
|
|
|
|
+ DM.SetValidatorVersion(m_valMajor, m_valMinor);
|
|
|
|
|
|
- // Add dxil functions to vmap.
|
|
|
|
- for (Function *UsedF : linkInfo->usedFunctions) {
|
|
|
|
- if (!vmap.count(UsedF)) {
|
|
|
|
- // Extern function need match by name
|
|
|
|
- DXASSERT(m_newFunctions.count(UsedF->getName()),
|
|
|
|
- "Must have new function.");
|
|
|
|
- vmap[UsedF] = m_newFunctions[UsedF->getName()];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ ValueToValueMapTy vmap;
|
|
|
|
|
|
- CloneFunction(F, NewF, vmap);
|
|
|
|
- }
|
|
|
|
|
|
+ std::unordered_set<Function *> initFuncSet;
|
|
|
|
+ // Add function
|
|
|
|
+ AddFunctions(DM, vmap, initFuncSet);
|
|
|
|
|
|
- // Call global constrctor.
|
|
|
|
- IRBuilder<> Builder(
|
|
|
|
- DM.GetEntryFunction()->getEntryBlock().getFirstInsertionPt());
|
|
|
|
|
|
+ // Set DxilFunctionProps.
|
|
|
|
+ std::unordered_map<Function *, std::unique_ptr<DxilEntrySignature>>
|
|
|
|
+ DxilEntrySignatureMap;
|
|
for (auto &it : m_functionDefs) {
|
|
for (auto &it : m_functionDefs) {
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilFunctionLinkInfo *linkInfo = it.first;
|
|
DxilLib *pLib = it.second;
|
|
DxilLib *pLib = it.second;
|
|
|
|
+ DxilModule &tmpDM = pLib->GetDxilModule();
|
|
|
|
|
|
Function *F = linkInfo->func;
|
|
Function *F = linkInfo->func;
|
|
- if (pLib->IsInitFunc(F)) {
|
|
|
|
|
|
+ if (tmpDM.HasDxilFunctionProps(F)) {
|
|
Function *NewF = m_newFunctions[F->getName()];
|
|
Function *NewF = m_newFunctions[F->getName()];
|
|
- Builder.CreateCall(NewF);
|
|
|
|
|
|
+ DxilFunctionProps props = tmpDM.GetDxilFunctionProps(F);
|
|
|
|
+ std::unique_ptr<DxilFunctionProps> pProps =
|
|
|
|
+ std::make_unique<DxilFunctionProps>();
|
|
|
|
+ *pProps = props;
|
|
|
|
+ DM.AddDxilFunctionProps(NewF, pProps);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (tmpDM.HasDxilEntrySignature(F)) {
|
|
|
|
+ Function *NewF = m_newFunctions[F->getName()];
|
|
|
|
+ std::unique_ptr<DxilEntrySignature> pSig =
|
|
|
|
+ llvm::make_unique<DxilEntrySignature>(tmpDM.GetDxilEntrySignature(F));
|
|
|
|
+ DxilEntrySignatureMap[NewF] = std::move(pSig);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ DM.ResetEntrySignatureMap(std::move(DxilEntrySignatureMap));
|
|
|
|
+
|
|
|
|
+ // Debug info.
|
|
|
|
+
|
|
|
|
+ // Add global
|
|
|
|
+ bool bSuccess = AddGlobals(DM, vmap);
|
|
|
|
+ if (!bSuccess)
|
|
|
|
+ return nullptr;
|
|
|
|
+
|
|
|
|
+ // Clone functions.
|
|
|
|
+ CloneFunctions(vmap);
|
|
|
|
|
|
// Refresh intrinsic cache.
|
|
// Refresh intrinsic cache.
|
|
DM.GetOP()->RefreshCache();
|
|
DM.GetOP()->RefreshCache();
|
|
@@ -910,22 +994,74 @@ bool DxilLinkerImpl::AddFunctions(SmallVector<StringRef, 4> &workList,
|
|
|
|
|
|
std::unique_ptr<llvm::Module> DxilLinkerImpl::Link(StringRef entry,
|
|
std::unique_ptr<llvm::Module> DxilLinkerImpl::Link(StringRef entry,
|
|
StringRef profile) {
|
|
StringRef profile) {
|
|
- StringSet<> addedFunctionSet;
|
|
|
|
- SmallVector<StringRef, 4> workList;
|
|
|
|
- workList.emplace_back(entry);
|
|
|
|
|
|
+ const ShaderModel *pSM = ShaderModel::GetByName(profile.data());
|
|
|
|
+ DXIL::ShaderKind kind = pSM->GetKind();
|
|
|
|
+ if (kind == DXIL::ShaderKind::Invalid ||
|
|
|
|
+ (kind >= DXIL::ShaderKind::RayGeneration &&
|
|
|
|
+ kind <= DXIL::ShaderKind::Callable)) {
|
|
|
|
+ m_ctx.emitError(profile + Twine(kInvalidProfile));
|
|
|
|
+ // Invalid profile.
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+ // Verifying validator version supports the requested profile
|
|
|
|
+ unsigned minValMajor, minValMinor;
|
|
|
|
+ pSM->GetMinValidatorVersion(minValMajor, minValMinor);
|
|
|
|
+ if (minValMajor > m_valMajor ||
|
|
|
|
+ (minValMajor == m_valMajor && minValMinor > m_valMinor)) {
|
|
|
|
+ m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
|
|
DxilLinkJob linkJob(m_ctx, m_valMajor, m_valMinor);
|
|
DxilLinkJob linkJob(m_ctx, m_valMajor, m_valMinor);
|
|
|
|
|
|
DenseSet<DxilLib *> libSet;
|
|
DenseSet<DxilLib *> libSet;
|
|
- if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
|
|
|
|
- /*bLazyLoadDone*/ false))
|
|
|
|
- return nullptr;
|
|
|
|
|
|
+ StringSet<> addedFunctionSet;
|
|
|
|
+
|
|
|
|
+ bool bIsLib = pSM->IsLib();
|
|
|
|
+ if (!bIsLib) {
|
|
|
|
+ SmallVector<StringRef, 4> workList;
|
|
|
|
+ workList.emplace_back(entry);
|
|
|
|
+
|
|
|
|
+ if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
|
|
|
|
+ /*bLazyLoadDone*/ false))
|
|
|
|
+ return nullptr;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ // Add every function for lib profile.
|
|
|
|
+ for (auto &it : m_functionNameMap) {
|
|
|
|
+ StringRef name = it.getKey();
|
|
|
|
+ std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair = it.second;
|
|
|
|
+ DxilFunctionLinkInfo *linkInfo = linkPair.first;
|
|
|
|
+ DxilLib *pLib = linkPair.second;
|
|
|
|
+
|
|
|
|
+ Function *F = linkInfo->func;
|
|
|
|
+ pLib->LazyLoadFunction(F);
|
|
|
|
+
|
|
|
|
+ linkJob.AddFunction(linkPair);
|
|
|
|
+
|
|
|
|
+ libSet.insert(pLib);
|
|
|
|
+
|
|
|
|
+ addedFunctionSet.insert(name);
|
|
|
|
+ }
|
|
|
|
+ // Add every dxil functions.
|
|
|
|
+ for (auto *pLib : libSet) {
|
|
|
|
+ auto &DM = pLib->GetDxilModule();
|
|
|
|
+ DM.GetOP();
|
|
|
|
+ auto *pM = DM.GetModule();
|
|
|
|
+ for (Function &F : pM->functions()) {
|
|
|
|
+ if (hlsl::OP::IsDxilOpFunc(&F)) {
|
|
|
|
+ linkJob.AddFunction(&F);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
// Save global users.
|
|
// Save global users.
|
|
for (auto &pLib : libSet) {
|
|
for (auto &pLib : libSet) {
|
|
pLib->BuildGlobalUsage();
|
|
pLib->BuildGlobalUsage();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ SmallVector<StringRef, 4> workList;
|
|
// Save global ctor users.
|
|
// Save global ctor users.
|
|
for (auto &pLib : libSet) {
|
|
for (auto &pLib : libSet) {
|
|
pLib->CollectUsedInitFunctions(addedFunctionSet, workList);
|
|
pLib->CollectUsedInitFunctions(addedFunctionSet, workList);
|
|
@@ -937,10 +1073,14 @@ std::unique_ptr<llvm::Module> DxilLinkerImpl::Link(StringRef entry,
|
|
/*bLazyLoadDone*/ true))
|
|
/*bLazyLoadDone*/ true))
|
|
return nullptr;
|
|
return nullptr;
|
|
|
|
|
|
- std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair =
|
|
|
|
- m_functionNameMap[entry];
|
|
|
|
|
|
+ if (!bIsLib) {
|
|
|
|
+ std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair =
|
|
|
|
+ m_functionNameMap[entry];
|
|
|
|
|
|
- return linkJob.Link(entryLinkPair, profile);
|
|
|
|
|
|
+ return linkJob.Link(entryLinkPair, pSM);
|
|
|
|
+ } else {
|
|
|
|
+ return linkJob.LinkToLib(pSM);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
namespace hlsl {
|
|
namespace hlsl {
|