1. Support flatten function decl.

2. Clone shader entry to be called by other functions.
3. Skip ComputeViewIdState for library profile.
4. Change HLFunctionProps to DxilFunctionProps for DxilModule to use.
5. Don't add .flat to flattened function name.
This commit is contained in:
Xiang Li 2017-05-19 13:21:09 -07:00 коммит произвёл Xiang Li
Родитель c1bc9d945a
Коммит 0a3981b54b
12 изменённых файлов: 287 добавлений и 135 удалений

Просмотреть файл

@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxilFunctionProps.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// Function properties for a dxil shader function. //
// //
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include "dxc/HLSL/DxilConstants.h"
namespace hlsl {
struct DxilFunctionProps {
union {
// Compute shader.
struct {
unsigned numThreads[3];
} CS;
// Geometry shader.
struct {
DXIL::InputPrimitive inputPrimitive;
unsigned maxVertexCount;
unsigned instanceCount;
DXIL::PrimitiveTopology
streamPrimitiveTopologies[DXIL::kNumOutputStreams];
} GS;
// Hull shader.
struct {
llvm::Function *patchConstantFunc;
DXIL::TessellatorDomain domain;
DXIL::TessellatorPartitioning partition;
DXIL::TessellatorOutputPrimitive outputPrimitive;
unsigned inputControlPoints;
unsigned outputControlPoints;
float maxTessFactor;
} HS;
// Domain shader.
struct {
DXIL::TessellatorDomain domain;
unsigned inputControlPoints;
} DS;
// Vertex shader.
struct {
llvm::Constant *clipPlanes[DXIL::kNumClipPlanes];
} VS;
// Pixel shader.
struct {
bool EarlyDepthStencil;
} PS;
} ShaderProps;
DXIL::ShaderKind shaderKind;
};
} // namespace hlsl

Просмотреть файл

@ -19,6 +19,7 @@
#include "dxc/HLSL/DxilSampler.h"
#include "dxc/HLSL/DxilShaderModel.h"
#include "dxc/HLSL/DxilSignature.h"
#include "dxc/HLSL/DxilFunctionProps.h"
#include <memory>
#include <string>
#include <vector>
@ -44,47 +45,6 @@ class ShaderModel;
class OP;
class RootSignatureHandle;
struct HLFunctionProps {
union {
// TODO: not every function need this union.
// Compute shader.
struct {
unsigned numThreads[3];
} CS;
// Geometry shader.
struct {
DXIL::InputPrimitive inputPrimitive;
unsigned maxVertexCount;
unsigned instanceCount;
DXIL::PrimitiveTopology streamPrimitiveTopologies[DXIL::kNumOutputStreams];
} GS;
// Hull shader.
struct {
llvm::Function *patchConstantFunc;
DXIL::TessellatorDomain domain;
DXIL::TessellatorPartitioning partition;
DXIL::TessellatorOutputPrimitive outputPrimitive;
unsigned inputControlPoints;
unsigned outputControlPoints;
float maxTessFactor;
} HS;
// Domain shader.
struct {
DXIL::TessellatorDomain domain;
unsigned inputControlPoints;
} DS;
// Vertex shader.
struct {
llvm::Constant *clipPlanes[DXIL::kNumClipPlanes];
} VS;
// Pixel shader.
struct {
bool EarlyDepthStencil;
} PS;
} ShaderProps;
DXIL::ShaderKind shaderKind;
};
struct HLOptions {
HLOptions()
: bDefaultRowMajor(false), bIEEEStrict(false), bDisableOptimizations(false),
@ -164,10 +124,10 @@ public:
DxilSignature &GetPatchConstantSignature();
RootSignatureHandle &GetRootSignature();
// HLFunctionProps.
bool HasHLFunctionProps(llvm::Function *F);
HLFunctionProps &GetHLFunctionProps(llvm::Function *F);
void AddHLFunctionProps(llvm::Function *F, std::unique_ptr<HLFunctionProps> &info);
// DxilFunctionProps.
bool HasDxilFunctionProps(llvm::Function *F);
DxilFunctionProps &GetDxilFunctionProps(llvm::Function *F);
void AddDxilFunctionProps(llvm::Function *F, std::unique_ptr<DxilFunctionProps> &info);
DxilFunctionAnnotation *GetFunctionAnnotation(llvm::Function *F);
DxilFunctionAnnotation *AddFunctionAnnotation(llvm::Function *F);
@ -286,7 +246,7 @@ private:
std::vector<llvm::GlobalVariable*> m_TGSMVariables;
// High level function info.
std::unordered_map<llvm::Function *, std::unique_ptr<HLFunctionProps>> m_HLFunctionPropsMap;
std::unordered_map<llvm::Function *, std::unique_ptr<DxilFunctionProps>> m_DxilFunctionPropsMap;
// Resource type annotation.
std::unordered_map<llvm::Type *, std::pair<DXIL::ResourceClass, DXIL::ResourceKind>> m_ResTypeAnnotation;

Просмотреть файл

@ -1000,7 +1000,7 @@ ComputeViewIdState::ComputeViewIdState() : ModulePass(ID) {
bool ComputeViewIdState::runOnModule(Module &M) {
DxilModule &DxilModule = M.GetOrCreateDxilModule();
const ShaderModel *pSM = DxilModule.GetShaderModel();
if (!pSM->IsCS()) {
if (!pSM->IsCS() && !pSM->IsLib()) {
DxilViewIdState &ViewIdState = DxilModule.GetViewIdState();
ViewIdState.Compute();
return true;

Просмотреть файл

@ -112,7 +112,7 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
// Entry function.
Function *EntryFn = H.GetEntryFunction();
HLFunctionProps *FnProps = H.HasHLFunctionProps(EntryFn) ? &H.GetHLFunctionProps(EntryFn) : nullptr;
DxilFunctionProps *FnProps = H.HasDxilFunctionProps(EntryFn) ? &H.GetDxilFunctionProps(EntryFn) : nullptr;
M.SetEntryFunction(EntryFn);
M.SetEntryFunctionName(H.GetEntryFunctionName());
@ -706,7 +706,7 @@ void DxilGenerationPass::CreateDxilSignatures() {
m_OtherSemanticsUsed.clear();
if (SM->IsHS()) {
HLFunctionProps &EntryProps = m_pHLModule->GetHLFunctionProps(EntryFunc);
DxilFunctionProps &EntryProps = m_pHLModule->GetDxilFunctionProps(EntryFunc);
Function *patchConstantFunc = EntryProps.ShaderProps.HS.patchConstantFunc;
if (patchConstantFunc == nullptr) {
EntryFunc->getContext().emitError("Patch constant function is not specified.");
@ -1506,7 +1506,7 @@ void DxilGenerationPass::GenerateDxilPatchConstantLdSt() {
const bool bIsInout = false;
const bool bNeedVertexID = false;
if (bIsHs) {
HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
DxilFunctionProps &EntryQual = m_pHLModule->GetDxilFunctionProps(EntryFunc);
Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
InsertPt = patchConstantFunc->getEntryBlock().getFirstInsertionPt();
}
@ -1584,7 +1584,7 @@ void DxilGenerationPass::GenerateDxilPatchConstantFunctionInputs() {
OP *hlslOP = m_pHLModule->GetOP();
Constant *constZero = hlslOP->GetU32Const(0);
Function *EntryFunc = m_pHLModule->GetEntryFunction();
HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
DxilFunctionProps &EntryQual = m_pHLModule->GetDxilFunctionProps(EntryFunc);
Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
DxilFunctionAnnotation *patchFuncAnnotation = m_pHLModule->GetFunctionAnnotation(patchConstantFunc);
@ -1631,11 +1631,11 @@ void DxilGenerationPass::GenerateDxilPatchConstantFunctionInputs() {
bool DxilGenerationPass::HasClipPlanes() {
Function *EntryFunc = m_pHLModule->GetEntryFunction();
if (!m_pHLModule->HasHLFunctionProps(EntryFunc))
if (!m_pHLModule->HasDxilFunctionProps(EntryFunc))
return false;
HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
DxilFunctionProps &EntryQual = m_pHLModule->GetDxilFunctionProps(EntryFunc);
auto &VS = EntryQual.ShaderProps.VS;
unsigned numClipPlanes = 0;
@ -1651,7 +1651,7 @@ bool DxilGenerationPass::HasClipPlanes() {
void DxilGenerationPass::GenerateClipPlanesForVS(Value *outPosition) {
Function *EntryFunc = m_pHLModule->GetEntryFunction();
HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
DxilFunctionProps &EntryQual = m_pHLModule->GetDxilFunctionProps(EntryFunc);
auto &VS = EntryQual.ShaderProps.VS;
unsigned numClipPlanes = 0;
@ -2444,7 +2444,7 @@ void DxilGenerationPass::GenerateDxilOperations(
const ShaderModel *pSM = m_pHLModule->GetShaderModel();
Function *patchConstantFunc = nullptr;
if (pSM->IsHS()) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(entry);
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(entry);
patchConstantFunc = funcProps.ShaderProps.HS.patchConstantFunc;
}
@ -2532,7 +2532,7 @@ void DxilGenerationPass::TranslatePreciseAttribute() {
}
if (m_pHLModule->GetShaderModel()->IsHS()) {
HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFn);
DxilFunctionProps &EntryQual = m_pHLModule->GetDxilFunctionProps(EntryFn);
Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
TranslatePreciseAttributeOnFunction(*patchConstantFunc, M);
}

Просмотреть файл

@ -222,7 +222,7 @@ const vector<unique_ptr<HLResource> > &HLModule::GetUAVs() const {
void HLModule::RemoveFunction(llvm::Function *F) {
DXASSERT_NOMSG(F != nullptr);
m_HLFunctionPropsMap.erase(F);
m_DxilFunctionPropsMap.erase(F);
if (m_pTypeSystem.get()->GetFunctionAnnotation(F))
m_pTypeSystem.get()->EraseFunctionAnnotation(F);
m_pOP->RemoveFunction(F);
@ -361,15 +361,15 @@ vector<GlobalVariable* > &HLModule::GetLLVMUsed() {
return m_LLVMUsed;
}
bool HLModule::HasHLFunctionProps(llvm::Function *F) {
return m_HLFunctionPropsMap.find(F) != m_HLFunctionPropsMap.end();
bool HLModule::HasDxilFunctionProps(llvm::Function *F) {
return m_DxilFunctionPropsMap.find(F) != m_DxilFunctionPropsMap.end();
}
HLFunctionProps &HLModule::GetHLFunctionProps(llvm::Function *F) {
return *m_HLFunctionPropsMap[F];
DxilFunctionProps &HLModule::GetDxilFunctionProps(llvm::Function *F) {
return *m_DxilFunctionPropsMap[F];
}
void HLModule::AddHLFunctionProps(llvm::Function *F, std::unique_ptr<HLFunctionProps> &info) {
DXASSERT(m_HLFunctionPropsMap.count(F) == 0, "F already in map, info will be overwritten");
m_HLFunctionPropsMap[F] = std::move(info);
void HLModule::AddDxilFunctionProps(llvm::Function *F, std::unique_ptr<DxilFunctionProps> &info) {
DXASSERT(m_DxilFunctionPropsMap.count(F) == 0, "F already in map, info will be overwritten");
m_DxilFunctionPropsMap[F] = std::move(info);
}
DxilFunctionAnnotation *HLModule::GetFunctionAnnotation(llvm::Function *F) {
@ -440,8 +440,8 @@ void HLModule::EmitHLMetadata() {
{
NamedMDNode * fnProps = m_pModule->getOrInsertNamedMetadata(kHLDxilFunctionPropertiesMDName);
for (auto && pair : m_HLFunctionPropsMap) {
const hlsl::HLFunctionProps * props = pair.second.get();
for (auto && pair : m_DxilFunctionPropsMap) {
const hlsl::DxilFunctionProps * props = pair.second.get();
Metadata *MDVals[30];
std::fill(MDVals, MDVals + _countof(MDVals), nullptr);
unsigned valIdx = 0;
@ -521,7 +521,7 @@ void HLModule::LoadHLMetadata() {
while (propIdx < fnProps->getNumOperands()) {
MDTuple *pProps = dyn_cast<MDTuple>(fnProps->getOperand(propIdx++));
std::unique_ptr<hlsl::HLFunctionProps> props = llvm::make_unique<hlsl::HLFunctionProps>();
std::unique_ptr<hlsl::DxilFunctionProps> props = llvm::make_unique<hlsl::DxilFunctionProps>();
unsigned idx = 0;
Function *F = dyn_cast<Function>(dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
switch (m_pSM->GetKind()) {
@ -554,7 +554,7 @@ void HLModule::LoadHLMetadata() {
break;
}
m_HLFunctionPropsMap[F] = std::move(props);
m_DxilFunctionPropsMap[F] = std::move(props);
}
const NamedMDNode * options = m_pModule->getOrInsertNamedMetadata(kHLDxilOptionsMDName);

Просмотреть файл

@ -35,7 +35,7 @@ struct HLOperationLowerHelper {
llvm::Type *i1Ty;
Type *i8Ty;
DxilTypeSystem &dxilTypeSys;
HLFunctionProps *functionProps;
DxilFunctionProps *functionProps;
bool bLegacyCBufferLoad;
DataLayout legacyDataLayout;
HLOperationLowerHelper(HLModule &HLM);
@ -51,7 +51,7 @@ HLOperationLowerHelper::HLOperationLowerHelper(HLModule &HLM)
i1Ty = Type::getInt1Ty(Ctx);
i8Ty = Type::getInt8Ty(Ctx);
Function *EntryFunc = HLM.GetEntryFunction();
functionProps = &HLM.GetHLFunctionProps(EntryFunc);
functionProps = &HLM.GetDxilFunctionProps(EntryFunc);
bLegacyCBufferLoad = HLM.GetHLOptions().bLegacyCBufferLoad;
}

Просмотреть файл

@ -3886,6 +3886,8 @@ public:
// Remove flattened functions.
for (auto Iter : funcMap) {
Function *F = Iter.first;
Function *flatF = Iter.second;
flatF->takeName(F);
F->eraseFromParent();
}
@ -4978,9 +4980,11 @@ void SROA_Parameter_HLSL::flattenArgument(
Function *Entry = m_pHLModule->GetEntryFunction();
bool hasShaderInputOutput = F == Entry;
if (m_pHLModule->HasHLFunctionProps(Entry)) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(Entry);
if (m_pHLModule->HasDxilFunctionProps(F)) {
hasShaderInputOutput = true;
}
if (m_pHLModule->HasDxilFunctionProps(Entry)) {
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(Entry);
if (funcProps.shaderKind == DXIL::ShaderKind::Hull) {
Function *patchConstantFunc = funcProps.ShaderProps.HS.patchConstantFunc;
hasShaderInputOutput |= F == patchConstantFunc;
@ -5536,7 +5540,13 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
DXASSERT(funcAnnotation, "must find annotation for function");
std::deque<Value *> WorkList;
LLVMContext &Ctx = m_pHLModule->GetCtx();
std::unique_ptr<BasicBlock> TmpBlockForFuncDecl;
if (F->isDeclaration()) {
TmpBlockForFuncDecl.reset(BasicBlock::Create(Ctx));
}
std::vector<Value *> FlatParamList;
std::vector<DxilParameterAnnotation> FlatParamAnnotationList;
const bool bForParamTrue = true;
@ -5545,7 +5555,13 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
// merge GEP use for arg.
HLModule::MergeGepUse(&Arg);
// Insert point may be removed. So recreate builder every time.
IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
IRBuilder<> Builder(Ctx);
if (!F->isDeclaration()) {
Builder.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
} else {
Builder.SetInsertPoint(TmpBlockForFuncDecl.get());
}
DxilParameterAnnotation &paramAnnotation =
funcAnnotation->GetParameterAnnotation(Arg.getArgNo());
DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(&Arg);
@ -5558,8 +5574,12 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
std::vector<DxilParameterAnnotation> FlatRetAnnotationList;
// Split and change to out parameter.
if (!retType->isVoidTy()) {
Instruction *InsertPt = F->getEntryBlock().getFirstInsertionPt();
IRBuilder<> Builder(InsertPt);
IRBuilder<> Builder(Ctx);
if (!F->isDeclaration()) {
Builder.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
} else {
Builder.SetInsertPoint(TmpBlockForFuncDecl.get());
}
Value *retValAddr = Builder.CreateAlloca(retType);
DxilParameterAnnotation &retAnnotation =
funcAnnotation->GetRetTypeAnnotation();
@ -5640,8 +5660,8 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
}
unsigned extraParamSize = 0;
if (m_pHLModule->HasHLFunctionProps(F)) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(F);
if (m_pHLModule->HasDxilFunctionProps(F)) {
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(F);
if (funcProps.shaderKind == ShaderModel::Kind::Vertex) {
auto &VS = funcProps.ShaderProps.VS;
Type *outFloatTy = Type::getFloatPtrTy(F->getContext());
@ -5698,12 +5718,12 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
}
DXASSERT(flatF->arg_size() == (extraParamSize + FlatParamAnnotationList.size()), "parameter count mismatch");
// ShaderProps.
if (m_pHLModule->HasHLFunctionProps(F)) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(F);
std::unique_ptr<HLFunctionProps> flatFuncProps = std::make_unique<HLFunctionProps>();
if (m_pHLModule->HasDxilFunctionProps(F)) {
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(F);
std::unique_ptr<DxilFunctionProps> flatFuncProps = std::make_unique<DxilFunctionProps>();
flatFuncProps->shaderKind = funcProps.shaderKind;
flatFuncProps->ShaderProps = funcProps.ShaderProps;
m_pHLModule->AddHLFunctionProps(flatF, flatFuncProps);
m_pHLModule->AddDxilFunctionProps(flatF, flatFuncProps);
if (funcProps.shaderKind == ShaderModel::Kind::Vertex) {
auto &VS = funcProps.ShaderProps.VS;
unsigned clipArgIndex = FlatParamAnnotationList.size();
@ -5722,50 +5742,52 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
}
}
// Move function body into flatF.
moveFunctionBody(F, flatF);
if (!F->isDeclaration()) {
// Move function body into flatF.
moveFunctionBody(F, flatF);
// Replace old parameters with flatF Arguments.
auto argIter = flatF->arg_begin();
auto flatArgIter = FlatParamList.begin();
LLVMContext &Context = F->getContext();
// Replace old parameters with flatF Arguments.
auto argIter = flatF->arg_begin();
auto flatArgIter = FlatParamList.begin();
LLVMContext &Context = F->getContext();
// Parameter cast come from begining of entry block.
IRBuilder<> Builder(flatF->getEntryBlock().getFirstInsertionPt());
// Parameter cast come from begining of entry block.
IRBuilder<> Builder(flatF->getEntryBlock().getFirstInsertionPt());
while (argIter != flatF->arg_end()) {
Argument *Arg = argIter++;
if (flatArgIter == FlatParamList.end()) {
DXASSERT(extraParamSize>0, "parameter count mismatch");
break;
}
Value *flatArg = *(flatArgIter++);
if (castParamMap.count(flatArg)) {
replaceCastParameter(flatArg, castParamMap[flatArg].first, *flatF, Arg,
castParamMap[flatArg].second, Builder);
}
flatArg->replaceAllUsesWith(Arg);
// Update arg debug info.
DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(flatArg);
if (DDI) {
Value *VMD = MetadataAsValue::get(Context, ValueAsMetadata::get(Arg));
DDI->setArgOperand(0, VMD);
}
HLModule::MergeGepUse(Arg);
// Flatten store of array parameter.
if (Arg->getType()->isPointerTy()) {
Type *Ty = Arg->getType()->getPointerElementType();
if (Ty->isArrayTy())
SplitArrayCopy(
Arg, typeSys,
&flatFuncAnnotation->GetParameterAnnotation(Arg->getArgNo()));
while (argIter != flatF->arg_end()) {
Argument *Arg = argIter++;
if (flatArgIter == FlatParamList.end()) {
DXASSERT(extraParamSize > 0, "parameter count mismatch");
break;
}
Value *flatArg = *(flatArgIter++);
if (castParamMap.count(flatArg)) {
replaceCastParameter(flatArg, castParamMap[flatArg].first, *flatF, Arg,
castParamMap[flatArg].second, Builder);
}
flatArg->replaceAllUsesWith(Arg);
// Update arg debug info.
DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(flatArg);
if (DDI) {
Value *VMD = MetadataAsValue::get(Context, ValueAsMetadata::get(Arg));
DDI->setArgOperand(0, VMD);
}
HLModule::MergeGepUse(Arg);
// Flatten store of array parameter.
if (Arg->getType()->isPointerTy()) {
Type *Ty = Arg->getType()->getPointerElementType();
if (Ty->isArrayTy())
SplitArrayCopy(
Arg, typeSys,
&flatFuncAnnotation->GetParameterAnnotation(Arg->getArgNo()));
}
}
// Support store to input and load from output.
LegalizeDxilInputOutputs(flatF, flatFuncAnnotation, typeSys);
}
// Support store to input and load from output.
LegalizeDxilInputOutputs(flatF, flatFuncAnnotation, typeSys);
}
void SROA_Parameter_HLSL::createFlattenedFunctionCall(Function *F, Function *flatF, CallInst *CI) {
@ -5972,8 +5994,8 @@ void SROA_Parameter_HLSL::replaceCall(Function *F, Function *flatF) {
m_pHLModule->SetEntryFunction(flatF);
}
// Update patch constant function.
if (m_pHLModule->HasHLFunctionProps(flatF)) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(flatF);
if (m_pHLModule->HasDxilFunctionProps(flatF)) {
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(flatF);
if (funcProps.shaderKind == DXIL::ShaderKind::Hull) {
Function *oldPatchConstantFunc =
funcProps.ShaderProps.HS.patchConstantFunc;

Просмотреть файл

@ -28,6 +28,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <memory>
#include <unordered_map>
#include <unordered_set>
@ -115,6 +116,9 @@ private:
StringMap<Function *> patchConstantFunctionMap;
bool IsPatchConstantFunction(const Function *F);
// Map to save entry functions.
StringMap<Function *> entryFunctionMap;
// List for functions with clip plane.
std::vector<Function *> clipPlaneFuncList;
std::unordered_map<Value *, DebugLoc> debugInfoMap;
@ -1053,8 +1057,8 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
if (isEntry)
EntryFunc = F;
std::unique_ptr<HLFunctionProps> funcProps =
llvm::make_unique<HLFunctionProps>();
std::unique_ptr<DxilFunctionProps> funcProps =
llvm::make_unique<DxilFunctionProps>();
// Save patch constant function to patchConstantFunctionMap.
bool isPatchConstantFunction = false;
@ -1165,7 +1169,7 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
if (patchConstantFunctionMap.count(funcName) == 1) {
Function *patchConstFunc = patchConstantFunctionMap[funcName];
funcProps->ShaderProps.HS.patchConstantFunc = patchConstFunc;
DXASSERT_NOMSG(m_pHLModule->HasHLFunctionProps(patchConstFunc));
DXASSERT_NOMSG(m_pHLModule->HasDxilFunctionProps(patchConstFunc));
// Check no inout parameter for patch constant function.
DxilFunctionAnnotation *patchConstFuncAnnotation =
m_pHLModule->GetFunctionAnnotation(patchConstFunc);
@ -1597,9 +1601,9 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
if (isHS) {
// Check
Function *patchConstFunc = funcProps->ShaderProps.HS.patchConstantFunc;
if (m_pHLModule->HasHLFunctionProps(patchConstFunc)) {
HLFunctionProps &patchProps =
m_pHLModule->GetHLFunctionProps(patchConstFunc);
if (m_pHLModule->HasDxilFunctionProps(patchConstFunc)) {
DxilFunctionProps &patchProps =
m_pHLModule->GetDxilFunctionProps(patchConstFunc);
if (patchProps.ShaderProps.HS.outputControlPoints != 0 &&
patchProps.ShaderProps.HS.outputControlPoints !=
funcProps->ShaderProps.HS.outputControlPoints) {
@ -1627,13 +1631,24 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
// Only add functionProps when exist.
if (profileAttributes || isPatchConstantFunction)
m_pHLModule->AddHLFunctionProps(F, funcProps);
m_pHLModule->AddDxilFunctionProps(F, funcProps);
// Save F to entry map.
if (profileAttributes) {
if (entryFunctionMap.count(FD->getName())) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"redefinition of %0");
Diags.Report(FD->getLocStart(), DiagID) << FD->getName();
}
entryFunctionMap[FD->getNameAsString()] = F;
}
}
void CGMSHLSLRuntime::EmitHLSLFunctionProlog(Function *F, const FunctionDecl *FD) {
// Support clip plane need debug info which not available when create function attribute.
if (const HLSLClipPlanesAttr *Attr = FD->getAttr<HLSLClipPlanesAttr>()) {
HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(F);
DxilFunctionProps &funcProps = m_pHLModule->GetDxilFunctionProps(F);
// Initialize to null.
memset(funcProps.ShaderProps.VS.clipPlanes, 0, sizeof(funcProps.ShaderProps.VS.clipPlanes));
// Create global for each clip plane, and use the clip plane val as init val.
@ -3769,6 +3784,50 @@ static void SimpleTransformForHLDXIR(llvm::Module *pM) {
I->eraseFromParent();
}
// Clone shader entry function to be called by other functions.
// The original function will be used as shader entry.
static void CloneShaderEntry(Function *ShaderF, StringRef EntryName,
HLModule &HLM) {
// Use mangled name for cloned one.
Function *F = Function::Create(ShaderF->getFunctionType(),
GlobalValue::LinkageTypes::ExternalLinkage,
"", HLM.GetModule());
F->takeName(ShaderF);
// Set to name before mangled.
ShaderF->setName(EntryName);
SmallVector<ReturnInst *, 2> Returns;
ValueToValueMapTy vmap;
// Map params.
auto entryParamIt = F->arg_begin();
for (Argument &param : ShaderF->args()) {
vmap[&param] = (entryParamIt++);
}
llvm::CloneFunctionInto(F, ShaderF, vmap, /*ModuleLevelChagnes*/ false,
Returns);
// Copy function annotation.
DxilFunctionAnnotation *shaderAnnot = HLM.GetFunctionAnnotation(ShaderF);
DxilFunctionAnnotation *annot = HLM.AddFunctionAnnotation(F);
DxilParameterAnnotation &retAnnot = shaderAnnot->GetRetTypeAnnotation();
DxilParameterAnnotation &cloneRetAnnot = annot->GetRetTypeAnnotation();
cloneRetAnnot = retAnnot;
// Clear semantic for cloned one.
retAnnot.SetSemanticString("");
retAnnot.SetSemanticIndexVec({});
for (unsigned i = 0; i < shaderAnnot->GetNumParameters(); i++) {
DxilParameterAnnotation &cloneParamAnnot = annot->GetParameterAnnotation(i);
DxilParameterAnnotation &paramAnnot =
shaderAnnot->GetParameterAnnotation(i);
cloneParamAnnot = paramAnnot;
// Clear semantic for cloned one.
cloneParamAnnot.SetSemanticString("");
cloneParamAnnot.SetSemanticIndexVec({});
}
}
void CGMSHLSLRuntime::FinishCodeGen() {
// Library don't have entry.
if (!m_bIsLib) {
@ -3780,11 +3839,15 @@ void CGMSHLSLRuntime::FinishCodeGen() {
"else SetEntryFunction should have reported this condition");
return;
}
} else {
for (auto &it : entryFunctionMap) {
CloneShaderEntry(it.second, it.getKey(), *m_pHLModule);
}
}
// Create copy for clip plane.
for (Function *F : clipPlaneFuncList) {
HLFunctionProps &props = m_pHLModule->GetHLFunctionProps(F);
DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(F);
IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
for (unsigned i = 0; i < DXIL::kNumClipPlanes; i++) {

Просмотреть файл

@ -0,0 +1,26 @@
// RUN: %dxc -T lib_6_1 %s | FileCheck %s
// Make sure entry function exist.
// CHECK: @entry(
// Make sure function decl exist.
// CHECK: LoadInputMat
// CHECK: RotateMat
// CHECK: StoreOutputMat
// Make sure cloned function exist.
// CHECK: @"\01?entry
void StoreOutputMat(float2x2 m, uint gidx);
float2x2 LoadInputMat(uint x, uint y);
float2x2 RotateMat(float2x2 m, uint x, uint y);
[numthreads(8,8,1)]
void entry( uint2 tid : SV_DispatchThreadID, uint2 gid : SV_GroupID, uint2 gtid : SV_GroupThreadID, uint gidx : SV_GroupIndex )
{
float2x2 f2x2 = LoadInputMat(gid.x, gid.y);
f2x2 = RotateMat(f2x2, tid.x, tid.y);
StoreOutputMat(f2x2, gidx);
}

Просмотреть файл

@ -0,0 +1,13 @@
// RUN: %dxc -T lib_6_1 %s | FileCheck %s
// CHECK: redefinition of entry
[numthreads(8,8,1)]
void entry( uint2 tid : SV_DispatchThreadID, uint2 gid : SV_GroupID, uint2 gtid : SV_GroupThreadID, uint gidx : SV_GroupIndex )
{
}
[numthreads(8,8,1)]
void entry( uint2 gid : SV_GroupID, uint2 gtid : SV_GroupThreadID, uint gidx : SV_GroupIndex )
{
}

Просмотреть файл

@ -501,6 +501,8 @@ public:
TEST_METHOD(CodeGenIntrinsic5)
TEST_METHOD(CodeGenInvalidInputOutputTypes)
TEST_METHOD(CodeGenLegacyStruct)
TEST_METHOD(CodeGenLibCsEntry)
TEST_METHOD(CodeGenLibCsEntry2)
TEST_METHOD(CodeGenLibResource)
TEST_METHOD(CodeGenLibUnusedFunc)
TEST_METHOD(CodeGenLitInParen)
@ -2773,6 +2775,14 @@ TEST_F(CompilerTest, CodeGenLegacyStruct) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\legacy_struct.hlsl");
}
TEST_F(CompilerTest, CodeGenLibCsEntry) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl");
}
TEST_F(CompilerTest, CodeGenLibCsEntry2) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\lib_cs_entry2.hlsl");
}
TEST_F(CompilerTest, CodeGenLibResource) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\lib_resource.hlsl");
}

Просмотреть файл

@ -617,8 +617,8 @@ TEST_F(ValidationTest, WhenUnknownBlocksThenFail) {
TEST_F(ValidationTest, WhenZeroInputPatchCountWithInputThenFail) {
RewriteAssemblyCheckMsg(
L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_6_0",
"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z.flat\", i32 3, i32 3",
"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z.flat\", i32 0, i32 3",
"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z\", i32 3, i32 3",
"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z\", i32 0, i32 3",
"When HS input control point count is 0, no input signature should exist");
}