DirectXShaderCompiler/lib/DXIL/DxilTypeSystem.cpp

817 строки
28 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// //
// DxilTypeSystem.cpp //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "dxc/DXIL/DxilTypeSystem.h"
#include "dxc/DXIL/DxilModule.h"
#include "dxc/DXIL/DxilUtil.h"
#include "dxc/Support/Global.h"
#include "dxc/Support/WinFunctions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using std::unique_ptr;
using std::string;
using std::vector;
using std::map;
namespace hlsl {
//------------------------------------------------------------------------------
//
// DxilMatrixAnnotation class methods.
//
DxilMatrixAnnotation::DxilMatrixAnnotation()
: Rows(0)
, Cols(0)
, Orientation(MatrixOrientation::Undefined) {
}
//------------------------------------------------------------------------------
//
// DxilFieldAnnotation class methods.
//
DxilFieldAnnotation::DxilFieldAnnotation()
: m_bPrecise(false)
, m_ResourceAttribute(nullptr)
, m_CBufferOffset(UINT_MAX)
, m_bCBufferVarUsed(false)
{}
bool DxilFieldAnnotation::IsPrecise() const { return m_bPrecise; }
void DxilFieldAnnotation::SetPrecise(bool b) { m_bPrecise = b; }
bool DxilFieldAnnotation::HasMatrixAnnotation() const { return m_Matrix.Cols != 0; }
const DxilMatrixAnnotation &DxilFieldAnnotation::GetMatrixAnnotation() const { return m_Matrix; }
void DxilFieldAnnotation::SetMatrixAnnotation(const DxilMatrixAnnotation &MA) { m_Matrix = MA; }
bool DxilFieldAnnotation::HasResourceAttribute() const {
return m_ResourceAttribute;
}
llvm::MDNode *DxilFieldAnnotation::GetResourceAttribute() const {
return m_ResourceAttribute;
}
void DxilFieldAnnotation::SetResourceAttribute(llvm::MDNode *MD) {
m_ResourceAttribute = MD;
}
bool DxilFieldAnnotation::HasCBufferOffset() const { return m_CBufferOffset != UINT_MAX; }
unsigned DxilFieldAnnotation::GetCBufferOffset() const { return m_CBufferOffset; }
void DxilFieldAnnotation::SetCBufferOffset(unsigned Offset) { m_CBufferOffset = Offset; }
bool DxilFieldAnnotation::HasCompType() const { return m_CompType.GetKind() != CompType::Kind::Invalid; }
const CompType &DxilFieldAnnotation::GetCompType() const { return m_CompType; }
void DxilFieldAnnotation::SetCompType(CompType::Kind kind) { m_CompType = CompType(kind); }
bool DxilFieldAnnotation::HasSemanticString() const { return !m_Semantic.empty(); }
const std::string &DxilFieldAnnotation::GetSemanticString() const { return m_Semantic; }
llvm::StringRef DxilFieldAnnotation::GetSemanticStringRef() const { return llvm::StringRef(m_Semantic); }
void DxilFieldAnnotation::SetSemanticString(const std::string &SemString) { m_Semantic = SemString; }
bool DxilFieldAnnotation::HasInterpolationMode() const { return !m_InterpMode.IsUndefined(); }
const InterpolationMode &DxilFieldAnnotation::GetInterpolationMode() const { return m_InterpMode; }
void DxilFieldAnnotation::SetInterpolationMode(const InterpolationMode &IM) { m_InterpMode = IM; }
bool DxilFieldAnnotation::HasFieldName() const { return !m_FieldName.empty(); }
const std::string &DxilFieldAnnotation::GetFieldName() const { return m_FieldName; }
void DxilFieldAnnotation::SetFieldName(const std::string &FieldName) { m_FieldName = FieldName; }
bool DxilFieldAnnotation::IsCBVarUsed() const { return m_bCBufferVarUsed; }
void DxilFieldAnnotation::SetCBVarUsed(bool used) { m_bCBufferVarUsed = used; }
//------------------------------------------------------------------------------
//
// DxilPayloadFieldAnnotation class methods.
//
bool DxilPayloadFieldAnnotation::HasCompType() const { return m_CompType.GetKind() != CompType::Kind::Invalid; }
const CompType &DxilPayloadFieldAnnotation::GetCompType() const { return m_CompType; }
void DxilPayloadFieldAnnotation::SetCompType(CompType::Kind kind) { m_CompType = CompType(kind); }
uint32_t DxilPayloadFieldAnnotation::GetPayloadFieldQualifierMask() const {
return m_bitmask;
}
unsigned DxilPayloadFieldAnnotation::GetBitOffsetForShaderStage(DXIL::PayloadAccessShaderStage shaderStage ) {
unsigned bitOffset = static_cast<unsigned>(shaderStage) *
DXIL::PayloadAccessQualifierBitsPerStage;
return bitOffset;
}
void DxilPayloadFieldAnnotation::SetPayloadFieldQualifierMask(uint32_t fieldBitmask) {
DXASSERT((fieldBitmask & ~DXIL::PayloadAccessQualifierValidMask) == 0,
"Unknown payload access qualifier bits set");
m_bitmask = fieldBitmask & DXIL::PayloadAccessQualifierValidMask;
}
void DxilPayloadFieldAnnotation::AddPayloadFieldQualifier(
DXIL::PayloadAccessShaderStage shaderStage, DXIL::PayloadAccessQualifier qualifier) {
unsigned accessBits = static_cast<unsigned>(qualifier);
DXASSERT((accessBits & ~DXIL::PayloadAccessQualifierValidMaskPerStage) == 0,
"Unknown payload access qualifier bits set");
accessBits &= DXIL::PayloadAccessQualifierValidMaskPerStage;
accessBits <<= GetBitOffsetForShaderStage(shaderStage);
m_bitmask |= accessBits;
}
DXIL::PayloadAccessQualifier DxilPayloadFieldAnnotation::GetPayloadFieldQualifier(
DXIL::PayloadAccessShaderStage shaderStage) const {
int bitOffset = GetBitOffsetForShaderStage(shaderStage);
// default type is always ReadWrite
DXIL::PayloadAccessQualifier accessType = DXIL::PayloadAccessQualifier::ReadWrite;
const unsigned readBit = static_cast<unsigned>(DXIL::PayloadAccessQualifier::Read);
const unsigned writeBit = static_cast<unsigned>(DXIL::PayloadAccessQualifier::Write);
unsigned accessBits = m_bitmask >> bitOffset;
if (accessBits & readBit) {
// set Read if the first bit is set
accessType = DXIL::PayloadAccessQualifier::Read;
}
if (accessBits & writeBit) {
// set Write only if the second bit set, if both are set set to ReadWrite
accessType = accessType == DXIL::PayloadAccessQualifier::ReadWrite
? DXIL::PayloadAccessQualifier::Write
: DXIL::PayloadAccessQualifier::ReadWrite;
}
return accessType;
}
bool DxilPayloadFieldAnnotation::HasAnnotations() const {
return m_bitmask != 0;
}
//------------------------------------------------------------------------------
//
// DxilStructAnnotation class methods.
//
DxilTemplateArgAnnotation::DxilTemplateArgAnnotation()
: m_Type(nullptr), m_Integral(0)
{}
bool DxilTemplateArgAnnotation::IsType() const { return m_Type != nullptr; }
const llvm::Type *DxilTemplateArgAnnotation::GetType() const { return m_Type; }
void DxilTemplateArgAnnotation::SetType(const llvm::Type *pType) { m_Type = pType; }
bool DxilTemplateArgAnnotation::IsIntegral() const { return m_Type == nullptr; }
int64_t DxilTemplateArgAnnotation::GetIntegral() const { return m_Integral; }
void DxilTemplateArgAnnotation::SetIntegral(int64_t i64) { m_Type = nullptr; m_Integral = i64; }
unsigned DxilStructAnnotation::GetNumFields() const {
return (unsigned)m_FieldAnnotations.size();
}
DxilFieldAnnotation &DxilStructAnnotation::GetFieldAnnotation(unsigned FieldIdx) {
return m_FieldAnnotations[FieldIdx];
}
const DxilFieldAnnotation &DxilStructAnnotation::GetFieldAnnotation(unsigned FieldIdx) const {
return m_FieldAnnotations[FieldIdx];
}
const StructType *DxilStructAnnotation::GetStructType() const {
return m_pStructType;
}
void DxilStructAnnotation::SetStructType(const llvm::StructType *Ty) {
m_pStructType = Ty;
}
unsigned DxilStructAnnotation::GetCBufferSize() const { return m_CBufferSize; }
void DxilStructAnnotation::SetCBufferSize(unsigned size) { m_CBufferSize = size; }
void DxilStructAnnotation::MarkEmptyStruct() {
if (m_ResourcesContained == HasResources::True)
m_ResourcesContained = HasResources::Only;
else
m_FieldAnnotations.clear();
}
bool DxilStructAnnotation::IsEmptyStruct() {
return m_FieldAnnotations.empty();
}
bool DxilStructAnnotation::IsEmptyBesidesResources() {
return m_ResourcesContained == HasResources::Only ||
m_FieldAnnotations.empty();
}
// ContainsResources is for codegen only, not meant for metadata
void DxilStructAnnotation::SetContainsResources() {
if (m_ResourcesContained == HasResources::False)
m_ResourcesContained = HasResources::True;
}
bool DxilStructAnnotation::ContainsResources() const { return m_ResourcesContained != HasResources::False; }
// For template args, GetNumTemplateArgs() will return 0 if not a template
unsigned DxilStructAnnotation::GetNumTemplateArgs() const {
return (unsigned)m_TemplateAnnotations.size();
}
void DxilStructAnnotation::SetNumTemplateArgs(unsigned count) {
DXASSERT(m_TemplateAnnotations.empty(), "template args already initialized");
m_TemplateAnnotations.resize(count);
}
DxilTemplateArgAnnotation &DxilStructAnnotation::GetTemplateArgAnnotation(unsigned argIdx) {
return m_TemplateAnnotations[argIdx];
}
const DxilTemplateArgAnnotation &DxilStructAnnotation::GetTemplateArgAnnotation(unsigned argIdx) const {
return m_TemplateAnnotations[argIdx];
}
//------------------------------------------------------------------------------
//
// DxilParameterAnnotation class methods.
//
DxilParameterAnnotation::DxilParameterAnnotation()
: DxilFieldAnnotation(), m_inputQual(DxilParamInputQual::In) {
}
DxilParamInputQual DxilParameterAnnotation::GetParamInputQual() const {
return m_inputQual;
}
void DxilParameterAnnotation::SetParamInputQual(DxilParamInputQual qual) {
m_inputQual = qual;
}
const std::vector<unsigned> &DxilParameterAnnotation::GetSemanticIndexVec() const {
return m_semanticIndex;
}
void DxilParameterAnnotation::SetSemanticIndexVec(const std::vector<unsigned> &Vec) {
m_semanticIndex = Vec;
}
void DxilParameterAnnotation::AppendSemanticIndex(unsigned SemIdx) {
m_semanticIndex.emplace_back(SemIdx);
}
//------------------------------------------------------------------------------
//
// DxilFunctionAnnotation class methods.
//
unsigned DxilFunctionAnnotation::GetNumParameters() const {
return (unsigned)m_parameterAnnotations.size();
}
DxilParameterAnnotation &DxilFunctionAnnotation::GetParameterAnnotation(unsigned ParamIdx) {
return m_parameterAnnotations[ParamIdx];
}
const DxilParameterAnnotation &DxilFunctionAnnotation::GetParameterAnnotation(unsigned ParamIdx) const {
return m_parameterAnnotations[ParamIdx];
}
DxilParameterAnnotation &DxilFunctionAnnotation::GetRetTypeAnnotation() {
return m_retTypeAnnotation;
}
const DxilParameterAnnotation &DxilFunctionAnnotation::GetRetTypeAnnotation() const {
return m_retTypeAnnotation;
}
const Function *DxilFunctionAnnotation::GetFunction() const {
return m_pFunction;
}
//------------------------------------------------------------------------------
//
// DxilPayloadAnnotation class methods.
//
unsigned DxilPayloadAnnotation::GetNumFields() const {
return (unsigned)m_FieldAnnotations.size();
}
DxilPayloadFieldAnnotation &DxilPayloadAnnotation::GetFieldAnnotation(unsigned FieldIdx) {
return m_FieldAnnotations[FieldIdx];
}
const DxilPayloadFieldAnnotation &DxilPayloadAnnotation::GetFieldAnnotation(unsigned FieldIdx) const {
return m_FieldAnnotations[FieldIdx];
}
const StructType *DxilPayloadAnnotation::GetStructType() const {
return m_pStructType;
}
void DxilPayloadAnnotation::SetStructType(const llvm::StructType *Ty) {
m_pStructType = Ty;
}
//------------------------------------------------------------------------------
//
// DxilTypeSystem class methods.
//
DxilTypeSystem::DxilTypeSystem(Module *pModule)
: m_pModule(pModule),
m_LowPrecisionMode(DXIL::LowPrecisionMode::Undefined) {}
DxilStructAnnotation *DxilTypeSystem::AddStructAnnotation(const StructType *pStructType, unsigned numTemplateArgs) {
DXASSERT_NOMSG(m_StructAnnotations.find(pStructType) == m_StructAnnotations.end());
DxilStructAnnotation *pA = new DxilStructAnnotation();
m_StructAnnotations[pStructType] = unique_ptr<DxilStructAnnotation>(pA);
pA->m_pStructType = pStructType;
pA->m_FieldAnnotations.resize(pStructType->getNumElements());
pA->SetNumTemplateArgs(numTemplateArgs);
return pA;
}
void DxilTypeSystem::FinishStructAnnotation(DxilStructAnnotation &SA) {
const llvm::StructType *ST = SA.GetStructType();
DXASSERT(SA.GetNumFields() == ST->getNumElements(), "otherwise, mismatched field count.");
// Update resource containment
for (unsigned i = 0; i < SA.GetNumFields() && !SA.ContainsResources(); i++) {
if (IsResourceContained(ST->getElementType(i)))
SA.SetContainsResources();
}
// Mark if empty
if (SA.GetCBufferSize() == 0)
SA.MarkEmptyStruct();
}
DxilStructAnnotation *DxilTypeSystem::GetStructAnnotation(const StructType *pStructType) {
auto it = m_StructAnnotations.find(pStructType);
if (it != m_StructAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
const DxilStructAnnotation *
DxilTypeSystem::GetStructAnnotation(const StructType *pStructType) const {
auto it = m_StructAnnotations.find(pStructType);
if (it != m_StructAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
void DxilTypeSystem::EraseStructAnnotation(const StructType *pStructType) {
DXASSERT_NOMSG(m_StructAnnotations.count(pStructType));
m_StructAnnotations.remove_if([pStructType](
const std::pair<const StructType *, std::unique_ptr<DxilStructAnnotation>>
&I) { return pStructType == I.first; });
}
// Recurse type, removing any found StructType from the set
static void RemoveUsedStructsFromSet(Type *Ty, std::unordered_set<const llvm::StructType*> &unused_structs) {
if (Ty->isPointerTy())
RemoveUsedStructsFromSet(Ty->getPointerElementType(), unused_structs);
else if (Ty->isArrayTy())
RemoveUsedStructsFromSet(Ty->getArrayElementType(), unused_structs);
else if (Ty->isStructTy()) {
StructType *ST = cast<StructType>(Ty);
// Only recurse first time into this struct
if (unused_structs.erase(ST)) {
for (auto &ET : ST->elements()) {
RemoveUsedStructsFromSet(ET, unused_structs);
}
}
}
}
void DxilTypeSystem::EraseUnusedStructAnnotations() {
// Add all structures with annotations to a set
// Iterate globals, resource types, and functions, recursing used structures to
// remove matching struct annotations from set
std::unordered_set<const llvm::StructType*> unused_structs;
for (auto &it : m_StructAnnotations) {
unused_structs.insert(it.first);
}
for (auto &GV : m_pModule->globals()) {
RemoveUsedStructsFromSet(GV.getType(), unused_structs);
}
DxilModule &DM = m_pModule->GetDxilModule();
for (auto &&C : DM.GetCBuffers()) {
RemoveUsedStructsFromSet(C->GetHLSLType(), unused_structs);
}
for (auto &&Srv : DM.GetSRVs()) {
RemoveUsedStructsFromSet(Srv->GetHLSLType(), unused_structs);
}
for (auto &&Uav : DM.GetUAVs()) {
RemoveUsedStructsFromSet(Uav->GetHLSLType(), unused_structs);
}
for (auto &F : m_pModule->functions()) {
FunctionType *FT = F.getFunctionType();
RemoveUsedStructsFromSet(FT->getReturnType(), unused_structs);
for (auto &argTy : FT->params()) {
RemoveUsedStructsFromSet(argTy, unused_structs);
}
}
// erase remaining structures in set
for (auto *ST : unused_structs) {
EraseStructAnnotation(ST);
}
}
DxilTypeSystem::StructAnnotationMap &DxilTypeSystem::GetStructAnnotationMap() {
return m_StructAnnotations;
}
const DxilTypeSystem::StructAnnotationMap &DxilTypeSystem::GetStructAnnotationMap() const{
return m_StructAnnotations;
}
DxilPayloadAnnotation *DxilTypeSystem::AddPayloadAnnotation(const StructType *pStructType) {
DXASSERT_NOMSG(m_PayloadAnnotations.find(pStructType) == m_PayloadAnnotations.end());
DxilPayloadAnnotation *pA = new DxilPayloadAnnotation();
m_PayloadAnnotations[pStructType] = unique_ptr<DxilPayloadAnnotation>(pA);
pA->m_pStructType = pStructType;
pA->m_FieldAnnotations.resize(pStructType->getNumElements());
return pA;
}
DxilPayloadAnnotation *DxilTypeSystem::GetPayloadAnnotation(const StructType *pStructType) {
auto it = m_PayloadAnnotations.find(pStructType);
if (it != m_PayloadAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
const DxilPayloadAnnotation *
DxilTypeSystem::GetPayloadAnnotation(const StructType *pStructType) const {
auto it = m_PayloadAnnotations.find(pStructType);
if (it != m_PayloadAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
void DxilTypeSystem::ErasePayloadAnnotation(const StructType *pStructType) {
DXASSERT_NOMSG(m_StructAnnotations.count(pStructType));
m_PayloadAnnotations.remove_if([pStructType](
const std::pair<const StructType *, std::unique_ptr<DxilPayloadAnnotation>>
&I) { return pStructType == I.first; });
}
DxilTypeSystem::PayloadAnnotationMap &DxilTypeSystem::GetPayloadAnnotationMap() {
return m_PayloadAnnotations;
}
const DxilTypeSystem::PayloadAnnotationMap &DxilTypeSystem::GetPayloadAnnotationMap() const{
return m_PayloadAnnotations;
}
DxilFunctionAnnotation *DxilTypeSystem::AddFunctionAnnotation(const Function *pFunction) {
DXASSERT_NOMSG(m_FunctionAnnotations.find(pFunction) == m_FunctionAnnotations.end());
DxilFunctionAnnotation *pA = new DxilFunctionAnnotation();
m_FunctionAnnotations[pFunction] = unique_ptr<DxilFunctionAnnotation>(pA);
pA->m_pFunction = pFunction;
pA->m_parameterAnnotations.resize(pFunction->getFunctionType()->getNumParams());
return pA;
}
void DxilTypeSystem::FinishFunctionAnnotation(DxilFunctionAnnotation &FA) {
auto FT = FA.GetFunction()->getFunctionType();
// Update resource containment
if (IsResourceContained(FT->getReturnType()))
FA.SetContainsResourceArgs();
for (unsigned i = 0; i < FT->getNumParams() && !FA.ContainsResourceArgs(); i++) {
if (IsResourceContained(FT->getParamType(i)))
FA.SetContainsResourceArgs();
}
}
DxilFunctionAnnotation *DxilTypeSystem::GetFunctionAnnotation(const Function *pFunction) {
auto it = m_FunctionAnnotations.find(pFunction);
if (it != m_FunctionAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
const DxilFunctionAnnotation *
DxilTypeSystem::GetFunctionAnnotation(const Function *pFunction) const {
auto it = m_FunctionAnnotations.find(pFunction);
if (it != m_FunctionAnnotations.end()) {
return it->second.get();
} else {
return nullptr;
}
}
void DxilTypeSystem::EraseFunctionAnnotation(const Function *pFunction) {
DXASSERT_NOMSG(m_FunctionAnnotations.count(pFunction));
m_FunctionAnnotations.remove_if([pFunction](
const std::pair<const Function *, std::unique_ptr<DxilFunctionAnnotation>>
&I) { return pFunction == I.first; });
}
DxilTypeSystem::FunctionAnnotationMap &DxilTypeSystem::GetFunctionAnnotationMap() {
return m_FunctionAnnotations;
}
StructType *DxilTypeSystem::GetSNormF32Type(unsigned NumComps) {
return GetNormFloatType(CompType::getSNormF32(), NumComps);
}
StructType *DxilTypeSystem::GetUNormF32Type(unsigned NumComps) {
return GetNormFloatType(CompType::getUNormF32(), NumComps);
}
StructType *DxilTypeSystem::GetNormFloatType(CompType CT, unsigned NumComps) {
Type *pCompType = CT.GetLLVMType(m_pModule->getContext());
DXASSERT_NOMSG(pCompType->isFloatTy());
Type *pFieldType = pCompType;
string TypeName;
raw_string_ostream NameStream(TypeName);
if (NumComps > 1) {
(NameStream << "dx.types." << NumComps << "x" << CT.GetName()).flush();
pFieldType = VectorType::get(pFieldType, NumComps);
} else {
(NameStream << "dx.types." << CT.GetName()).flush();
}
StructType *pStructType = m_pModule->getTypeByName(TypeName);
if (pStructType == nullptr) {
pStructType = StructType::create(m_pModule->getContext(), pFieldType, TypeName);
DxilStructAnnotation &TA = *AddStructAnnotation(pStructType);
DxilFieldAnnotation &FA = TA.GetFieldAnnotation(0);
FA.SetCompType(CT.GetKind());
DXASSERT_NOMSG(CT.IsSNorm() || CT.IsUNorm());
}
return pStructType;
}
void DxilTypeSystem::CopyTypeAnnotation(const llvm::Type *Ty,
const DxilTypeSystem &src) {
if (isa<PointerType>(Ty))
Ty = Ty->getPointerElementType();
while (isa<ArrayType>(Ty))
Ty = Ty->getArrayElementType();
// Only struct type has annotation.
if (!isa<StructType>(Ty))
return;
const StructType *ST = cast<StructType>(Ty);
// Already exist.
if (GetStructAnnotation(ST))
return;
if (const DxilStructAnnotation *annot = src.GetStructAnnotation(ST)) {
DxilStructAnnotation *dstAnnot = AddStructAnnotation(ST);
// Copy the annotation.
*dstAnnot = *annot;
// Copy field type annotations.
for (Type *Ty : ST->elements()) {
CopyTypeAnnotation(Ty, src);
}
}
}
void DxilTypeSystem::CopyFunctionAnnotation(const llvm::Function *pDstFunction,
const llvm::Function *pSrcFunction,
const DxilTypeSystem &src) {
const DxilFunctionAnnotation *annot = src.GetFunctionAnnotation(pSrcFunction);
// Don't have annotation.
if (!annot)
return;
// Already exist.
if (GetFunctionAnnotation(pDstFunction))
return;
DxilFunctionAnnotation *dstAnnot = AddFunctionAnnotation(pDstFunction);
// Copy the annotation.
*dstAnnot = *annot;
dstAnnot->m_pFunction = pDstFunction;
// Clone ret type annotation.
CopyTypeAnnotation(pDstFunction->getReturnType(), src);
// Clone param type annotations.
for (const Argument &arg : pDstFunction->args()) {
CopyTypeAnnotation(arg.getType(), src);
}
}
DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q, DXIL::ShaderKind SK, bool isPC) {
DXASSERT(Q != DxilParamInputQual::Inout, "Inout not expected for SigPointFromInputQual");
switch (SK) {
case DXIL::ShaderKind::Vertex:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::VSIn;
case DxilParamInputQual::Out:
return DXIL::SigPointKind::VSOut;
default:
break;
}
break;
case DXIL::ShaderKind::Hull:
switch (Q) {
case DxilParamInputQual::In:
if (isPC)
return DXIL::SigPointKind::PCIn;
else
return DXIL::SigPointKind::HSIn;
case DxilParamInputQual::Out:
if (isPC)
return DXIL::SigPointKind::PCOut;
else
return DXIL::SigPointKind::HSCPOut;
case DxilParamInputQual::InputPatch:
return DXIL::SigPointKind::HSCPIn;
case DxilParamInputQual::OutputPatch:
return DXIL::SigPointKind::HSCPOut;
default:
break;
}
break;
case DXIL::ShaderKind::Domain:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::DSIn;
case DxilParamInputQual::Out:
return DXIL::SigPointKind::DSOut;
case DxilParamInputQual::InputPatch:
case DxilParamInputQual::OutputPatch:
return DXIL::SigPointKind::DSCPIn;
default:
break;
}
break;
case DXIL::ShaderKind::Geometry:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::GSIn;
case DxilParamInputQual::InputPrimitive:
return DXIL::SigPointKind::GSVIn;
case DxilParamInputQual::OutStream0:
case DxilParamInputQual::OutStream1:
case DxilParamInputQual::OutStream2:
case DxilParamInputQual::OutStream3:
return DXIL::SigPointKind::GSOut;
default:
break;
}
break;
case DXIL::ShaderKind::Pixel:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::PSIn;
case DxilParamInputQual::Out:
return DXIL::SigPointKind::PSOut;
default:
break;
}
break;
case DXIL::ShaderKind::Compute:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::CSIn;
default:
break;
}
break;
case DXIL::ShaderKind::Mesh:
switch (Q) {
case DxilParamInputQual::In:
case DxilParamInputQual::InPayload:
return DXIL::SigPointKind::MSIn;
case DxilParamInputQual::OutIndices:
case DxilParamInputQual::OutVertices:
return DXIL::SigPointKind::MSOut;
case DxilParamInputQual::OutPrimitives:
return DXIL::SigPointKind::MSPOut;
default:
break;
}
break;
case DXIL::ShaderKind::Amplification:
switch (Q) {
case DxilParamInputQual::In:
return DXIL::SigPointKind::ASIn;
default:
break;
}
break;
default:
break;
}
return DXIL::SigPointKind::Invalid;
}
void RemapSemantic(llvm::StringRef &oldSemName, llvm::StringRef &oldSemFullName, const char *newSemName,
DxilParameterAnnotation &paramInfo, llvm::LLVMContext &Context) {
// format deprecation warning
Context.emitWarning(Twine("DX9-style semantic \"") + oldSemName + Twine("\" mapped to DX10 system semantic \"") + newSemName +
Twine("\" due to -Gec flag. This functionality is deprecated in newer language versions."));
// create new semantic name with the same index
std::string newSemNameStr(newSemName);
unsigned indexLen = oldSemFullName.size() - oldSemName.size();
if (indexLen > 0) {
newSemNameStr = newSemNameStr.append(oldSemFullName.data() + oldSemName.size(), indexLen);
}
paramInfo.SetSemanticString(newSemNameStr);
}
void RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo, DXIL::SigPointKind sigPoint, llvm::LLVMContext &Context) {
DXASSERT(paramInfo.HasSemanticString(), "expected paramInfo with semantic");
//*ppWarningMsg = nullptr;
llvm::StringRef semFullName = paramInfo.GetSemanticStringRef();
llvm::StringRef semName;
unsigned semIndex;
Semantic::DecomposeNameAndIndex(semFullName, &semName, &semIndex);
if (sigPoint == DXIL::SigPointKind::PSOut) {
if (semName.size() == 5) {
if (_strnicmp(semName.data(), "COLOR", 5) == 0) {
RemapSemantic(semName, semFullName, "SV_Target", paramInfo, Context);
}
else if (_strnicmp(semName.data(), "DEPTH", 5) == 0) {
RemapSemantic(semName, semFullName, "SV_Depth", paramInfo, Context);
}
}
}
else if ((sigPoint == DXIL::SigPointKind::VSOut && semName.size() == 8 && _strnicmp(semName.data(), "POSITION", 8) == 0) ||
(sigPoint == DXIL::SigPointKind::PSIn && semName.size() == 4 && _strnicmp(semName.data(), "VPOS", 4) == 0)) {
RemapSemantic(semName, semFullName, "SV_Position", paramInfo, Context);
}
}
bool DxilTypeSystem::UseMinPrecision() {
return m_LowPrecisionMode == DXIL::LowPrecisionMode::UseMinPrecision;
}
void DxilTypeSystem::SetMinPrecision(bool bMinPrecision) {
DXIL::LowPrecisionMode mode =
bMinPrecision ? DXIL::LowPrecisionMode::UseMinPrecision
: DXIL::LowPrecisionMode::UseNativeLowPrecision;
DXASSERT((mode == m_LowPrecisionMode ||
m_LowPrecisionMode == DXIL::LowPrecisionMode::Undefined),
"LowPrecisionMode should only be set once.");
m_LowPrecisionMode = mode;
}
bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) {
// strip pointer/array
if (Ty->isPointerTy())
Ty = Ty->getPointerElementType();
if (Ty->isArrayTy())
Ty = Ty->getArrayElementType();
if (auto ST = dyn_cast<StructType>(Ty)) {
if (dxilutil::IsHLSLResourceType(Ty)) {
return true;
} else if (auto SA = GetStructAnnotation(ST)) {
if (SA->ContainsResources())
return true;
}
}
return false;
}
DxilStructTypeIterator::DxilStructTypeIterator(llvm::StructType *sTy, DxilStructAnnotation *sAnnotation,
unsigned idx)
: STy(sTy), SAnnotation(sAnnotation), index(idx) {
DXASSERT(
sTy->getNumElements() == sAnnotation->GetNumFields(),
"Otherwise the pairing of annotation and struct type does not match.");
}
// prefix
DxilStructTypeIterator &DxilStructTypeIterator::operator++() {
index++;
return *this;
}
// postfix
DxilStructTypeIterator DxilStructTypeIterator::operator++(int) {
DxilStructTypeIterator iter(STy, SAnnotation, index);
index++;
return iter;
}
bool DxilStructTypeIterator::operator==(DxilStructTypeIterator iter) {
return iter.STy == STy && iter.SAnnotation == SAnnotation &&
iter.index == index;
}
bool DxilStructTypeIterator::operator!=(DxilStructTypeIterator iter) { return !(operator==(iter)); }
std::pair<llvm::Type *, DxilFieldAnnotation *> DxilStructTypeIterator::operator*() {
return std::pair<llvm::Type *, DxilFieldAnnotation *>(
STy->getElementType(index), &SAnnotation->GetFieldAnnotation(index));
}
DxilStructTypeIterator begin(llvm::StructType *STy, DxilStructAnnotation *SAnno) {
return { STy, SAnno, 0 };
}
DxilStructTypeIterator end(llvm::StructType *STy, DxilStructAnnotation *SAnno) {
return { STy, SAnno, STy->getNumElements() };
}
} // namespace hlsl