DirectXShaderCompiler/lib/DXIL/DxilSubobject.cpp

417 строки
15 KiB
C++
Исходник Обычный вид История

///////////////////////////////////////////////////////////////////////////////
// //
// DxilSubobject.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/Support/Global.h"
#include "dxc/Support/Unicode.h"
#include "dxc/Support/WinIncludes.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "dxc/DxilContainer/DxilRuntimeReflection.h"
#include "llvm/ADT/STLExtras.h"
namespace hlsl {
//------------------------------------------------------------------------------
//
// Subobject methods.
//
DxilSubobject::DxilSubobject(DxilSubobject &&other)
: m_Owner(other.m_Owner),
m_Kind(other.m_Kind),
m_Name(m_Owner.InternString(other.m_Name)),
m_Exports(std::move(other.m_Exports))
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
CopyUnionedContents(other);
}
DxilSubobject::DxilSubobject(DxilSubobjects &owner, Kind kind, llvm::StringRef name)
: m_Owner(owner),
m_Kind(kind),
m_Name(m_Owner.InternString(name)),
m_Exports()
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
}
DxilSubobject::DxilSubobject(DxilSubobjects &owner, const DxilSubobject &other, llvm::StringRef name)
: m_Owner(owner),
m_Kind(other.m_Kind),
m_Name(name),
m_Exports(other.m_Exports.begin(), other.m_Exports.end())
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
CopyUnionedContents(other);
if (&m_Owner != &other.m_Owner)
InternStrings();
}
void DxilSubobject::CopyUnionedContents(const DxilSubobject &other) {
switch (m_Kind) {
case Kind::StateObjectConfig:
StateObjectConfig.Flags = other.StateObjectConfig.Flags;
break;
case Kind::GlobalRootSignature:
case Kind::LocalRootSignature:
RootSignature.Size = other.RootSignature.Size;
RootSignature.Data = other.RootSignature.Data;
break;
case Kind::SubobjectToExportsAssociation:
SubobjectToExportsAssociation.Subobject = other.SubobjectToExportsAssociation.Subobject;
break;
case Kind::RaytracingShaderConfig:
RaytracingShaderConfig.MaxPayloadSizeInBytes = other.RaytracingShaderConfig.MaxPayloadSizeInBytes;
RaytracingShaderConfig.MaxAttributeSizeInBytes = other.RaytracingShaderConfig.MaxAttributeSizeInBytes;
break;
case Kind::RaytracingPipelineConfig:
RaytracingPipelineConfig.MaxTraceRecursionDepth = other.RaytracingPipelineConfig.MaxTraceRecursionDepth;
break;
case Kind::HitGroup:
HitGroup.Type = other.HitGroup.Type;
HitGroup.AnyHit = other.HitGroup.AnyHit;
HitGroup.ClosestHit = other.HitGroup.ClosestHit;
HitGroup.Intersection = other.HitGroup.Intersection;
break;
case Kind::RaytracingPipelineConfig1:
RaytracingPipelineConfig1.MaxTraceRecursionDepth = other.RaytracingPipelineConfig1.MaxTraceRecursionDepth;
RaytracingPipelineConfig1.Flags = other.RaytracingPipelineConfig1.Flags;
break;
2019-01-05 02:36:56 +03:00
default:
DXASSERT(0, "invalid kind");
break;
}
}
void DxilSubobject::InternStrings() {
// Transfer strings if necessary
m_Name = m_Owner.InternString(m_Name).data();
switch (m_Kind) {
case Kind::SubobjectToExportsAssociation:
SubobjectToExportsAssociation.Subobject = m_Owner.InternString(SubobjectToExportsAssociation.Subobject).data();
for (auto &ptr : m_Exports)
ptr = m_Owner.InternString(ptr).data();
break;
case Kind::HitGroup:
HitGroup.AnyHit = m_Owner.InternString(HitGroup.AnyHit).data();
HitGroup.ClosestHit = m_Owner.InternString(HitGroup.ClosestHit).data();
HitGroup.Intersection = m_Owner.InternString(HitGroup.Intersection).data();
break;
default:
break;
}
}
DxilSubobject::~DxilSubobject() {
}
// StateObjectConfig
bool DxilSubobject::GetStateObjectConfig(uint32_t &Flags) const {
if (m_Kind == Kind::StateObjectConfig) {
Flags = StateObjectConfig.Flags;
return true;
}
return false;
}
// Local/Global RootSignature
bool DxilSubobject::GetRootSignature(
bool local, const void * &Data, uint32_t &Size, const char **pText) const {
Kind expected = local ? Kind::LocalRootSignature : Kind::GlobalRootSignature;
if (m_Kind == expected) {
Data = RootSignature.Data;
Size = RootSignature.Size;
if (pText)
*pText = RootSignature.Text;
return true;
}
return false;
}
// SubobjectToExportsAssociation
bool DxilSubobject::GetSubobjectToExportsAssociation(
llvm::StringRef &Subobject,
const char * const * &Exports,
uint32_t &NumExports) const {
if (m_Kind == Kind::SubobjectToExportsAssociation) {
Subobject = SubobjectToExportsAssociation.Subobject;
Exports = m_Exports.data();
NumExports = (uint32_t)m_Exports.size();
return true;
}
return false;
}
// RaytracingShaderConfig
bool DxilSubobject::GetRaytracingShaderConfig(uint32_t &MaxPayloadSizeInBytes,
uint32_t &MaxAttributeSizeInBytes) const {
if (m_Kind == Kind::RaytracingShaderConfig) {
MaxPayloadSizeInBytes = RaytracingShaderConfig.MaxPayloadSizeInBytes;
MaxAttributeSizeInBytes = RaytracingShaderConfig.MaxAttributeSizeInBytes;
return true;
}
return false;
}
// RaytracingPipelineConfig
bool DxilSubobject::GetRaytracingPipelineConfig(
uint32_t &MaxTraceRecursionDepth) const {
if (m_Kind == Kind::RaytracingPipelineConfig) {
MaxTraceRecursionDepth = RaytracingPipelineConfig.MaxTraceRecursionDepth;
return true;
}
return false;
}
// HitGroup
bool DxilSubobject::GetHitGroup(DXIL::HitGroupType &hitGroupType,
llvm::StringRef &AnyHit,
llvm::StringRef &ClosestHit,
llvm::StringRef &Intersection) const {
if (m_Kind == Kind::HitGroup) {
hitGroupType = HitGroup.Type;
AnyHit = HitGroup.AnyHit;
ClosestHit = HitGroup.ClosestHit;
Intersection = HitGroup.Intersection;
return true;
}
return false;
}
// RaytracingPipelineConfig1
bool DxilSubobject::GetRaytracingPipelineConfig1(
uint32_t &MaxTraceRecursionDepth, uint32_t &Flags) const {
if (m_Kind == Kind::RaytracingPipelineConfig1) {
MaxTraceRecursionDepth = RaytracingPipelineConfig1.MaxTraceRecursionDepth;
Flags = RaytracingPipelineConfig1.Flags;
return true;
}
return false;
}
DxilSubobjects::DxilSubobjects()
: m_BytesStorage()
, m_Subobjects()
{}
DxilSubobjects::DxilSubobjects(DxilSubobjects &&other)
: m_BytesStorage(std::move(other.m_BytesStorage))
, m_Subobjects(std::move(other.m_Subobjects))
{}
DxilSubobjects::~DxilSubobjects() {}
llvm::StringRef DxilSubobjects::InternString(llvm::StringRef value) {
auto it = m_BytesStorage.find(value);
if (it != m_BytesStorage.end())
return it->first;
size_t size = value.size();
StoredBytes stored(std::make_pair(std::unique_ptr<char[]>(new char[size + 1]), size + 1));
memcpy(stored.first.get(), value.data(), size);
stored.first[size] = 0;
llvm::StringRef key(stored.first.get(), size);
m_BytesStorage[key] = std::move(stored);
return key;
}
const void *DxilSubobjects::InternRawBytes(const void *ptr, size_t size) {
auto it = m_BytesStorage.find(llvm::StringRef((const char *)ptr, size));
if (it != m_BytesStorage.end())
return it->first.data();
StoredBytes stored(std::make_pair(std::unique_ptr<char[]>(new char[size]), size));
memcpy(stored.first.get(), ptr, size);
llvm::StringRef key(stored.first.get(), size);
m_BytesStorage[key] = std::move(stored);
return key.data();
}
DxilSubobject *DxilSubobjects::FindSubobject(llvm::StringRef name) {
auto it = m_Subobjects.find(name);
if (it != m_Subobjects.end())
return it->second.get();
return nullptr;
}
void DxilSubobjects::RemoveSubobject(llvm::StringRef name) {
auto it = m_Subobjects.find(name);
if (it != m_Subobjects.end())
m_Subobjects.erase(it);
}
DxilSubobject &DxilSubobjects::CloneSubobject(
const DxilSubobject &Subobject, llvm::StringRef Name) {
Name = InternString(Name);
DXASSERT(FindSubobject(Name) == nullptr,
"otherwise, name collision between subobjects");
std::unique_ptr<DxilSubobject> ptr(new DxilSubobject(*this, Subobject, Name));
DxilSubobject &ref = *ptr;
m_Subobjects[Name] = std::move(ptr);
return ref;
}
// Create DxilSubobjects
DxilSubobject &DxilSubobjects::CreateStateObjectConfig(
llvm::StringRef Name, uint32_t Flags) {
DXASSERT_NOMSG(0 == ((~(uint32_t)DXIL::StateObjectFlags::ValidMask) & Flags));
auto &obj = CreateSubobject(Kind::StateObjectConfig, Name);
obj.StateObjectConfig.Flags = Flags;
return obj;
}
DxilSubobject &DxilSubobjects::CreateRootSignature(
llvm::StringRef Name, bool local, const void *Data, uint32_t Size, llvm::StringRef *pText /*= nullptr*/) {
auto &obj = CreateSubobject(local ? Kind::LocalRootSignature : Kind::GlobalRootSignature, Name);
obj.RootSignature.Data = InternRawBytes(Data, Size);
obj.RootSignature.Size = Size;
obj.RootSignature.Text = (pText ? InternString(*pText).data() : nullptr);
return obj;
}
DxilSubobject &DxilSubobjects::CreateSubobjectToExportsAssociation(
llvm::StringRef Name,
llvm::StringRef Subobject,
llvm::StringRef *Exports,
uint32_t NumExports) {
auto &obj = CreateSubobject(Kind::SubobjectToExportsAssociation, Name);
Subobject = InternString(Subobject);
obj.SubobjectToExportsAssociation.Subobject = Subobject.data();
for (unsigned i = 0; i < NumExports; i++) {
obj.m_Exports.emplace_back(InternString(Exports[i]).data());
}
return obj;
}
DxilSubobject &DxilSubobjects::CreateRaytracingShaderConfig(
llvm::StringRef Name,
uint32_t MaxPayloadSizeInBytes,
uint32_t MaxAttributeSizeInBytes) {
auto &obj = CreateSubobject(Kind::RaytracingShaderConfig, Name);
obj.RaytracingShaderConfig.MaxPayloadSizeInBytes = MaxPayloadSizeInBytes;
obj.RaytracingShaderConfig.MaxAttributeSizeInBytes = MaxAttributeSizeInBytes;
return obj;
}
DxilSubobject &DxilSubobjects::CreateRaytracingPipelineConfig(
llvm::StringRef Name,
uint32_t MaxTraceRecursionDepth) {
auto &obj = CreateSubobject(Kind::RaytracingPipelineConfig, Name);
obj.RaytracingPipelineConfig.MaxTraceRecursionDepth = MaxTraceRecursionDepth;
return obj;
}
DxilSubobject &DxilSubobjects::CreateHitGroup(llvm::StringRef Name,
DXIL::HitGroupType hitGroupType,
llvm::StringRef AnyHit,
llvm::StringRef ClosestHit,
llvm::StringRef Intersection) {
auto &obj = CreateSubobject(Kind::HitGroup, Name);
AnyHit = InternString(AnyHit);
ClosestHit = InternString(ClosestHit);
Intersection = InternString(Intersection);
obj.HitGroup.Type = hitGroupType;
obj.HitGroup.AnyHit = AnyHit.data();
obj.HitGroup.ClosestHit = ClosestHit.data();
obj.HitGroup.Intersection = Intersection.data();
return obj;
}
DxilSubobject &DxilSubobjects::CreateRaytracingPipelineConfig1(
llvm::StringRef Name, uint32_t MaxTraceRecursionDepth, uint32_t Flags) {
auto &obj = CreateSubobject(Kind::RaytracingPipelineConfig1, Name);
obj.RaytracingPipelineConfig1.MaxTraceRecursionDepth = MaxTraceRecursionDepth;
DXASSERT_NOMSG(
0 == ((~(uint32_t)DXIL::RaytracingPipelineFlags::ValidMask) & Flags));
obj.RaytracingPipelineConfig1.Flags = Flags;
return obj;
}
DxilSubobject &DxilSubobjects::CreateSubobject(Kind kind, llvm::StringRef Name) {
Name = InternString(Name);
IFTBOOLMSG(FindSubobject(Name) == nullptr, DXC_E_GENERAL_INTERNAL_ERROR, "Subobject name collision");
IFTBOOLMSG(!Name.empty(), DXC_E_GENERAL_INTERNAL_ERROR, "Empty Subobject name");
std::unique_ptr<DxilSubobject> ptr(new DxilSubobject(*this, kind, Name));
DxilSubobject &ref = *ptr;
m_Subobjects[Name] = std::move(ptr);
return ref;
}
bool LoadSubobjectsFromRDAT(DxilSubobjects &subobjects, RDAT::SubobjectTableReader *pSubobjectTableReader) {
if (!pSubobjectTableReader)
return false;
bool result = true;
for (unsigned i = 0; i < pSubobjectTableReader->GetCount(); ++i) {
try {
auto reader = pSubobjectTableReader->GetItem(i);
DXIL::SubobjectKind kind = reader.GetKind();
bool bLocalRS = false;
switch (kind) {
case DXIL::SubobjectKind::StateObjectConfig:
subobjects.CreateStateObjectConfig(reader.GetName(),
reader.GetStateObjectConfig_Flags());
break;
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const void *pOutBytes;
uint32_t OutSizeInBytes;
if (!reader.GetRootSignature(&pOutBytes, &OutSizeInBytes)) {
result = false;
continue;
}
subobjects.CreateRootSignature(reader.GetName(), bLocalRS, pOutBytes, OutSizeInBytes);
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
uint32_t NumExports = reader.GetSubobjectToExportsAssociation_NumExports();
std::vector<llvm::StringRef> Exports;
Exports.resize(NumExports);
for (unsigned i = 0; i < NumExports; ++i) {
Exports[i] = reader.GetSubobjectToExportsAssociation_Export(i);
}
subobjects.CreateSubobjectToExportsAssociation(reader.GetName(),
reader.GetSubobjectToExportsAssociation_Subobject(),
Exports.data(), NumExports);
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig:
subobjects.CreateRaytracingShaderConfig(reader.GetName(),
reader.GetRaytracingShaderConfig_MaxPayloadSizeInBytes(),
reader.GetRaytracingShaderConfig_MaxAttributeSizeInBytes());
break;
case DXIL::SubobjectKind::RaytracingPipelineConfig:
subobjects.CreateRaytracingPipelineConfig(reader.GetName(),
reader.GetRaytracingPipelineConfig_MaxTraceRecursionDepth());
break;
case DXIL::SubobjectKind::HitGroup:
subobjects.CreateHitGroup(reader.GetName(),
reader.GetHitGroup_Type(),
reader.GetHitGroup_AnyHit(),
reader.GetHitGroup_ClosestHit(),
reader.GetHitGroup_Intersection());
break;
case DXIL::SubobjectKind::RaytracingPipelineConfig1:
subobjects.CreateRaytracingPipelineConfig1(
reader.GetName(),
reader.GetRaytracingPipelineConfig1_MaxTraceRecursionDepth(),
reader.GetRaytracingPipelineConfig1_Flags());
break;
}
}
catch (hlsl::Exception &) {
result = false;
}
}
return result;
}
} // namespace hlsl