Skip to content

Commit 9002bee

Browse files
author
Greg Roth
committed
Allow loading DXIL shader model without module
Adds a dxilutil function to retrieve shader model from metadata. To enable this, the metadata helper implementation is split into a few utility functions which will continue to throw the exceptions as they did before, but allows passes to call them without fear of crashes as a result of that. Passes will assume the default shader model where it can't retrieve it for one reason or another. Changes scalarizer to try to retrieve the shader module when no module is found. Changes dyanmicvector to array to use the utility function and never try to recreate the hlmodule. Instead it will try the dxilmodule and if that isn't present, it will use the metadata for shader model only.
1 parent 46829dd commit 9002bee

6 files changed

Lines changed: 62 additions & 29 deletions

File tree

include/dxc/DXIL/DxilMetadataHelper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ class DxilMDHelper {
435435
// Shader model.
436436
void EmitDxilShaderModel(const ShaderModel *pSM);
437437
void LoadDxilShaderModel(const ShaderModel *&pSM);
438+
static const ShaderModel *LoadDxilShaderModel(const llvm::Module *pModule);
438439

439440
// Intermediate flags
440441
void EmitDxilIntermediateOptions(uint32_t flags);
@@ -687,6 +688,8 @@ class DxilMDHelper {
687688
static void
688689
CopyMetadata(llvm::Instruction &I, llvm::Instruction &SrcInst,
689690
llvm::ArrayRef<unsigned> WL = llvm::ArrayRef<unsigned>());
691+
static bool
692+
LoadShaderModelName(const llvm::Module *pModule, std::string &str);
690693

691694
private:
692695
llvm::LLVMContext &m_Ctx;

include/dxc/DXIL/DxilUtil.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ bool DeleteDeadAllocas(llvm::Function &F);
221221
llvm::Value *GEPIdxToOffset(llvm::GetElementPtrInst *GEP,
222222
llvm::IRBuilder<> &Builder, hlsl::OP *OP,
223223
const llvm::DataLayout &DL);
224+
225+
// Returns shader model appropriate to given module.
226+
const ShaderModel *LoadShaderModel(const llvm::Module &M);
227+
224228
} // namespace dxilutil
225229

226230
} // namespace hlsl

lib/DXIL/DxilMetadataHelper.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -261,31 +261,49 @@ void DxilMDHelper::EmitDxilShaderModel(const ShaderModel *pSM) {
261261
SetShaderModel(pSM);
262262
}
263263

264-
void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
264+
// Retrieve the name string of the shader model for the given module.
265+
// Returns true and passes shader model target string through str if valid.
266+
// Returns false if metadata is missing or invalid.
267+
bool DxilMDHelper::LoadShaderModelName(const Module *pModule, string &Name) {
265268
NamedMDNode *pShaderModelNamedMD =
266-
m_pModule->getNamedMetadata(kDxilShaderModelMDName);
267-
IFTBOOL(pShaderModelNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
268-
IFTBOOL(pShaderModelNamedMD->getNumOperands() == 1,
269-
DXC_E_INCORRECT_DXIL_METADATA);
269+
pModule->getNamedMetadata(kDxilShaderModelMDName);
270+
IFRBOOL(pShaderModelNamedMD != nullptr, false);
271+
IFRBOOL(pShaderModelNamedMD->getNumOperands() == 1, false);
270272

271273
MDNode *pShaderModelMD = pShaderModelNamedMD->getOperand(0);
272-
IFTBOOL(pShaderModelMD->getNumOperands() == kDxilShaderModelNumFields,
273-
DXC_E_INCORRECT_DXIL_METADATA);
274+
IFRBOOL(pShaderModelMD->getNumOperands() == kDxilShaderModelNumFields, false);
274275

275276
MDString *pShaderTypeMD =
276277
dyn_cast<MDString>(pShaderModelMD->getOperand(kDxilShaderModelTypeIdx));
277-
IFTBOOL(pShaderTypeMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
278+
IFRBOOL(pShaderTypeMD != nullptr, false);
278279
unsigned Major =
279280
ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMajorIdx));
280281
unsigned Minor =
281282
ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMinorIdx));
282-
string ShaderModelName = pShaderTypeMD->getString().str();
283-
ShaderModelName +=
284-
"_" + std::to_string(Major) + "_" +
285-
(Minor == ShaderModel::kOfflineMinor ? "x" : std::to_string(Minor));
286-
pSM = ShaderModel::GetByName(ShaderModelName.c_str());
283+
Name = pShaderTypeMD->getString().str();
284+
Name += "_" + std::to_string(Major) + "_" +
285+
(Minor == ShaderModel::kOfflineMinor ? "x" : std::to_string(Minor));
286+
return true;
287+
}
288+
289+
// Load shader model object from metadata contained in pModule.
290+
// Throws exceptions if any metadata is invalid or the values
291+
// of the shader model are invalid.
292+
const ShaderModel *DxilMDHelper::LoadDxilShaderModel(const Module *pModule) {
293+
string ShaderModelName;
294+
IFRBOOL(LoadShaderModelName(pModule, ShaderModelName), nullptr);
295+
return ShaderModel::GetByName(ShaderModelName.c_str());
296+
}
297+
298+
// Load shader model object from metadata MDHelper's module
299+
// and set it as current for MDHelper.
300+
void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
301+
pSM = LoadDxilShaderModel(m_pModule);
302+
IFTBOOL(pSM != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
287303
if (!pSM->IsValidForDxil()) {
288304
char ErrorMsgTxt[40];
305+
string ShaderModelName;
306+
LoadShaderModelName(m_pModule, ShaderModelName);
289307
StringCchPrintfA(ErrorMsgTxt, _countof(ErrorMsgTxt),
290308
"Unknown shader model '%s'", ShaderModelName.c_str());
291309
string ErrorMsg(ErrorMsgTxt);

lib/DXIL/DxilUtil.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,5 +1394,16 @@ bool DeleteDeadAllocas(llvm::Function &F) {
13941394
return Changed;
13951395
}
13961396

1397+
// Retrieve stored shader model in the given module.
1398+
// Where the module doesn't have HL nor Dxil modules,
1399+
// it identifies and returns the shader model from the module metatdata.
1400+
// Returns nullptr where none of that works, but that shouldn't happen much.
1401+
const ShaderModel *LoadShaderModel(const llvm::Module &M) {
1402+
if (M.HasDxilModule())
1403+
return M.GetDxilModule().GetShaderModel();
1404+
1405+
return DxilMDHelper::LoadDxilShaderModel(&M);
1406+
}
1407+
13971408
} // namespace dxilutil
13981409
} // namespace hlsl

lib/Transforms/Scalar/LowerTypePasses.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,15 @@ class DynamicIndexingVectorToArray : public LowerTypePass {
212212
};
213213

214214
void DynamicIndexingVectorToArray::initialize(Module &M) {
215-
// Can be invoked in a few places:
216-
// - From standard compile before dxilgen.
217-
// - When linking, where dxmodule is available.
218-
// - In isolated dxopt, where the module will need to be created.
219-
// When linking, we expect a dxil module and can't create an HL module,
220-
// so we try for the dxil module first.
221-
// Otherwise, either retrieve or generate the HL module.
222-
if (M.HasDxilModule()) {
223-
SupportsVectors = M.GetOrCreateDxilModule().GetShaderModel()->IsSM69Plus();
224-
} else {
225-
HLModule &HLM = M.GetOrCreateHLModule();
226-
SupportsVectors = HLM.GetShaderModel()->IsSM69Plus();
227-
}
215+
// Set vector support according to available shader model.
216+
// Use HLModule shader model if present.
217+
// Otherwise retrieve from dxil module or metadata.
218+
const ShaderModel *SM = nullptr;
219+
if (M.HasHLModule())
220+
SM = M.GetHLModule().GetShaderModel();
221+
else
222+
SM = dxilutil::LoadShaderModel(M);
223+
SupportsVectors = SM && SM->IsSM69Plus();
228224
}
229225

230226
void DynamicIndexingVectorToArray::applyOptions(PassOptions O) {

lib/Transforms/Scalar/Scalarizer.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "dxc/DXIL/DxilModule.h"
18+
#include "dxc/DXIL/DxilUtil.h"
1819

1920
#include "llvm/ADT/STLExtras.h"
2021
#include "llvm/IR/IRBuilder.h"
@@ -293,9 +294,9 @@ bool Scalarizer::doInitialization(Module &M) {
293294
}
294295

295296
bool Scalarizer::runOnFunction(Function &F) {
296-
Module *M = F.getParent();
297-
if (M->HasDxilModule() && M->GetDxilModule().GetShaderModel()->IsSM69Plus())
298-
SupportsVectors = true;
297+
const Module *M = F.getParent();
298+
const hlsl::ShaderModel *SM = hlsl::dxilutil::LoadShaderModel(*M);
299+
SupportsVectors = SM && SM->IsSM69Plus();
299300

300301
for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
301302
BasicBlock *BB = BBI;

0 commit comments

Comments
 (0)