Skip to content

Commit

Permalink
[DX] Add support for PSV resource bindings
Browse files Browse the repository at this point in the history
This patch continues implementing DirectX pipeline state validation
information by adding support for resource binding metadata.

Reviewed By: python3kgae

Differential Revision: https://reviews.llvm.org/D143130
  • Loading branch information
llvm-beanz committed Feb 2, 2023
1 parent 954cf9a commit dd3f7b0
Show file tree
Hide file tree
Showing 34 changed files with 826 additions and 0 deletions.
24 changes: 24 additions & 0 deletions llvm/include/llvm/BinaryFormat/DXContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,20 @@ struct RuntimeInfo {
void swapBytes(Triple::EnvironmentType Stage) { StageInfo.swapBytes(Stage); }
};

struct ResourceBindInfo {
uint32_t Type;
uint32_t Space;
uint32_t LowerBound;
uint32_t UpperBound;

void swapBytes() {
sys::swapByteOrder(Type);
sys::swapByteOrder(Space);
sys::swapByteOrder(LowerBound);
sys::swapByteOrder(UpperBound);
}
};

} // namespace v0

namespace v1 {
Expand Down Expand Up @@ -348,6 +362,16 @@ struct RuntimeInfo : public v1::RuntimeInfo {
}
};

struct ResourceBindInfo : public v0::ResourceBindInfo {
uint32_t Kind;
uint32_t Flags;

void swapBytes() {
sys::swapByteOrder(Kind);
sys::swapByteOrder(Flags);
}
};

} // namespace v2
} // namespace PSV

Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/DXContainerPSVInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace mcdxbc {
// RuntimeInfo.
struct PSVRuntimeInfo {
dxbc::PSV::v2::RuntimeInfo BaseData;
std::vector<dxbc::PSV::v2::ResourceBindInfo> Resources;

// Serialize PSVInfo into the provided raw_ostream. The version field
// specifies the data version to encode, the default value specifies encoding
Expand All @@ -39,6 +40,8 @@ struct PSVRuntimeInfo {
void swapBytes(Triple::EnvironmentType Stage) {
BaseData.swapBytes();
BaseData.swapBytes(Stage);
for (auto Res : Resources)
Res.swapBytes();
}
};

Expand Down
75 changes: 75 additions & 0 deletions llvm/include/llvm/Object/DXContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,84 @@ namespace object {

namespace DirectX {
class PSVRuntimeInfo {

// This class provides a view into the underlying resource array. The Resource
// data is little-endian encoded and may not be properly aligned to read
// directly from. The dereference operator creates a copy of the data and byte
// swaps it as appropriate.
struct ResourceArray {
StringRef Data;
size_t Stride; // size of each element in the list.

ResourceArray() = default;
ResourceArray(StringRef D, size_t S) : Data(D), Stride(S) {}

using value_type = dxbc::PSV::v2::ResourceBindInfo;

struct iterator {
StringRef Data;
size_t Stride; // size of each element in the list.
const char *Current;

iterator(const ResourceArray &A, const char *C)
: Data(A.Data), Stride(A.Stride), Current(C) {}
iterator(const iterator &) = default;

value_type operator*() {
// Explicitly zero the structure so that unused fields are zeroed. It is
// up to the user to know if the fields are used by verifying the PSV
// version.
value_type Val = {{0, 0, 0, 0}, 0, 0};
if (Current >= Data.end())
return Val;
memcpy(static_cast<void *>(&Val), Current, Stride);
if (sys::IsBigEndianHost)
Val.swapBytes();
return Val;
}

iterator operator++() {
if (Current < Data.end())
Current += Stride;
return *this;
}

iterator operator++(int) {
iterator Tmp = *this;
++*this;
return Tmp;
}

iterator operator--() {
if (Current > Data.begin())
Current -= Stride;
return *this;
}

iterator operator--(int) {
iterator Tmp = *this;
--*this;
return Tmp;
}

bool operator==(const iterator I) { return I.Current == Current; }
bool operator!=(const iterator I) { return !(*this == I); }
};

iterator begin() const { return iterator(*this, Data.begin()); }

iterator end() const { return iterator(*this, Data.end()); }

size_t size() const { return Data.size() / Stride; }
};

StringRef Data;
uint32_t Size;
using InfoStruct =
std::variant<std::monostate, dxbc::PSV::v0::RuntimeInfo,
dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo>;
InfoStruct BasicInfo;
ResourceArray Resources;

public:
PSVRuntimeInfo(StringRef D) : Data(D), Size(0) {}
Expand All @@ -41,6 +113,9 @@ class PSVRuntimeInfo {
Error parse(uint16_t ShaderKind);

uint32_t getSize() const { return Size; }
uint32_t getResourceCount() const { return Resources.size(); }
ResourceArray getResources() const { return Resources; }

uint32_t getVersion() const {
return Size >= sizeof(dxbc::PSV::v2::RuntimeInfo)
? 2
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/ObjectYAML/DXContainerYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,16 @@ struct ShaderHash {
std::vector<llvm::yaml::Hex8> Digest;
};

using ResourceBindInfo = dxbc::PSV::v2::ResourceBindInfo;

struct PSVInfo {
// The version field isn't actually encoded in the file, but it is inferred by
// the size of data regions. We include it in the yaml because it simplifies
// the format.
uint32_t Version;

dxbc::PSV::v2::RuntimeInfo Info;
std::vector<ResourceBindInfo> Resources;

void mapInfoForVersion(yaml::IO &IO);

Expand Down Expand Up @@ -107,6 +110,7 @@ struct Object {
} // namespace llvm

LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::Part)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::ResourceBindInfo)
namespace llvm {

class raw_ostream;
Expand Down Expand Up @@ -145,6 +149,10 @@ template <> struct MappingTraits<DXContainerYAML::Object> {
static void mapping(IO &IO, DXContainerYAML::Object &Obj);
};

template <> struct MappingTraits<DXContainerYAML::ResourceBindInfo> {
static void mapping(IO &IO, DXContainerYAML::ResourceBindInfo &Res);
};

} // namespace yaml

} // namespace llvm
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/MC/DXContainerPSVInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

using namespace llvm;
using namespace llvm::mcdxbc;
using namespace llvm::dxbc::PSV;

void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
uint32_t InfoSize;
Expand All @@ -33,4 +34,14 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
OS.write(reinterpret_cast<const char *>(&InfoSizeSwapped), sizeof(uint32_t));
// Write the info itself.
OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);

uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());
if (sys::IsBigEndianHost)
sys::swapByteOrder(ResourceCount);
OS.write(reinterpret_cast<const char *>(&ResourceCount), sizeof(uint32_t));

size_t BindingSize = (Version < 2) ? sizeof(v0::ResourceBindInfo)
: sizeof(v2::ResourceBindInfo);
for (const auto &Res : Resources)
OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
}
12 changes: 12 additions & 0 deletions llvm/lib/Object/DXContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,17 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
}
Current += Size;

uint32_t ResourceCount = 0;
if (Error Err = readInteger(Data, Current, ResourceCount))
return Err;
Current += sizeof(uint32_t);

Resources.Stride = (PSVVersion < 2) ? sizeof(v0::ResourceBindInfo)
: sizeof(v2::ResourceBindInfo);
size_t BindingDataSize = Resources.Stride * ResourceCount;
Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);

Current += BindingDataSize;

return Error::success();
}
1 change: 1 addition & 0 deletions llvm/lib/ObjectYAML/DXContainerEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
continue;
mcdxbc::PSVRuntimeInfo PSV;
memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v2::RuntimeInfo));
PSV.Resources = P.Info->Resources;

if (sys::IsBigEndianHost)
PSV.swapBytes(static_cast<Triple::EnvironmentType>(
Expand Down
25 changes: 25 additions & 0 deletions llvm/lib/ObjectYAML/DXContainerYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,20 @@ void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
IO &IO, DXContainerYAML::PSVInfo &PSV) {
IO.mapRequired("Version", PSV.Version);

// Store the PSV version in the YAML context.
void *OldContext = IO.getContext();
uint32_t Version = PSV.Version;
IO.setContext(&Version);

// Shader stage is only included in binaries for v1 and later, but we always
// include it since it simplifies parsing and file construction.
IO.mapRequired("ShaderStage", PSV.Info.ShaderStage);
PSV.mapInfoForVersion(IO);

IO.mapRequired("Resources", PSV.Resources);

// Restore the YAML context.
IO.setContext(OldContext);
}

void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
Expand All @@ -140,6 +150,21 @@ void MappingTraits<DXContainerYAML::Object>::mapping(
IO.mapRequired("Parts", Obj.Parts);
}

void MappingTraits<DXContainerYAML::ResourceBindInfo>::mapping(
IO &IO, DXContainerYAML::ResourceBindInfo &Res) {
IO.mapRequired("Type", Res.Type);
IO.mapRequired("Space", Res.Space);
IO.mapRequired("LowerBound", Res.LowerBound);
IO.mapRequired("UpperBound", Res.UpperBound);

const uint32_t *PSVVersion = static_cast<uint32_t *>(IO.getContext());
if (*PSVVersion < 2)
return;

IO.mapRequired("Kind", Res.Kind);
IO.mapRequired("Flags", Res.Flags);
}

} // namespace yaml

void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ Parts:
PayloadSizeInBytes: 4092
MinimumWaveLaneCount: 0
MaximumWaveLaneCount: 4294967295
Resources:
- Type: 1
Space: 2
LowerBound: 3
UpperBound: 4
- Type: 128
Space: 32768
LowerBound: 8388608
UpperBound: 2147483648
- Name: DXIL
Size: 24
Program:
Expand All @@ -36,4 +45,13 @@ Parts:
# CHECK-NEXT: PayloadSizeInBytes: 4092
# CHECK-NEXT: MinimumWaveLaneCount: 0
# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
# CHECK-NEXT: Resources:
# CHECK-NEXT: - Type: 1
# CHECK-NEXT: Space: 2
# CHECK-NEXT: LowerBound: 3
# CHECK-NEXT: UpperBound: 4
# CHECK-NEXT: - Type: 128
# CHECK-NEXT: Space: 32768
# CHECK-NEXT: LowerBound: 8388608
# CHECK-NEXT: UpperBound: 2147483648
# CHECK-NEXT: Name
18 changes: 18 additions & 0 deletions llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ Parts:
ShaderStage: 5
MinimumWaveLaneCount: 0
MaximumWaveLaneCount: 4294967295
Resources:
- Type: 1
Space: 2
LowerBound: 3
UpperBound: 4
- Type: 128
Space: 32768
LowerBound: 8388608
UpperBound: 2147483648
- Name: DXIL
Size: 24
Program:
Expand All @@ -34,4 +43,13 @@ Parts:
# CHECK-NEXT: ShaderStage: 5
# CHECK-NEXT: MinimumWaveLaneCount: 0
# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
# CHECK-NEXT: Resources:
# CHECK-NEXT: - Type: 1
# CHECK-NEXT: Space: 2
# CHECK-NEXT: LowerBound: 3
# CHECK-NEXT: UpperBound: 4
# CHECK-NEXT: - Type: 128
# CHECK-NEXT: Space: 32768
# CHECK-NEXT: LowerBound: 8388608
# CHECK-NEXT: UpperBound: 2147483648
# CHECK-NEXT: Name
18 changes: 18 additions & 0 deletions llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ Parts:
TessellatorDomain: 2056
MinimumWaveLaneCount: 0
MaximumWaveLaneCount: 4294967295
Resources:
- Type: 1
Space: 2
LowerBound: 3
UpperBound: 4
- Type: 128
Space: 32768
LowerBound: 8388608
UpperBound: 2147483648
- Name: DXIL
Size: 24
Program:
Expand All @@ -40,4 +49,13 @@ Parts:
# CHECK-NEXT: TessellatorDomain: 2056
# CHECK-NEXT: MinimumWaveLaneCount: 0
# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
# CHECK-NEXT: Resources:
# CHECK-NEXT: - Type: 1
# CHECK-NEXT: Space: 2
# CHECK-NEXT: LowerBound: 3
# CHECK-NEXT: UpperBound: 4
# CHECK-NEXT: - Type: 128
# CHECK-NEXT: Space: 32768
# CHECK-NEXT: LowerBound: 8388608
# CHECK-NEXT: UpperBound: 2147483648
# CHECK-NEXT: Name
18 changes: 18 additions & 0 deletions llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ Parts:
OutputPositionPresent: 1
MinimumWaveLaneCount: 0
MaximumWaveLaneCount: 4294967295
Resources:
- Type: 1
Space: 2
LowerBound: 3
UpperBound: 4
- Type: 128
Space: 32768
LowerBound: 8388608
UpperBound: 2147483648
- Name: DXIL
Size: 24
Program:
Expand All @@ -42,4 +51,13 @@ Parts:
# CHECK-NEXT: OutputPositionPresent: 1
# CHECK-NEXT: MinimumWaveLaneCount: 0
# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
# CHECK-NEXT: Resources:
# CHECK-NEXT: - Type: 1
# CHECK-NEXT: Space: 2
# CHECK-NEXT: LowerBound: 3
# CHECK-NEXT: UpperBound: 4
# CHECK-NEXT: - Type: 128
# CHECK-NEXT: Space: 32768
# CHECK-NEXT: LowerBound: 8388608
# CHECK-NEXT: UpperBound: 2147483648
# CHECK-NEXT: Name
Loading

0 comments on commit dd3f7b0

Please sign in to comment.