[llvm] [NFC] Refactoring MCDXBC to support out of order storage of root parameters (PR #137284)
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Wed May 14 12:01:37 PDT 2025
================
@@ -9,18 +9,81 @@
#include "llvm/BinaryFormat/DXContainer.h"
#include <cstdint>
#include <limits>
+#include <variant>
namespace llvm {
class raw_ostream;
namespace mcdxbc {
-struct RootParameter {
+struct RootParameterInfo {
dxbc::RootParameterHeader Header;
- union {
- dxbc::RootConstants Constants;
- dxbc::RTS0::v2::RootDescriptor Descriptor;
- };
+ size_t Location;
+
+ RootParameterInfo() = default;
+
+ RootParameterInfo(dxbc::RootParameterHeader H, size_t L)
+ : Header(H), Location(L) {}
+};
+
+using RootDescriptor = std::variant<dxbc::RTS0::v1::RootDescriptor,
+ dxbc::RTS0::v2::RootDescriptor>;
+using ParametersView = std::variant<const dxbc::RootConstants *,
+ const dxbc::RTS0::v1::RootDescriptor *,
+ const dxbc::RTS0::v2::RootDescriptor *>;
+struct RootParametersContainer {
+ SmallVector<RootParameterInfo> ParametersInfo;
+
+ SmallVector<dxbc::RootConstants> Constants;
+ SmallVector<RootDescriptor> Descriptors;
+
+ void addInfo(dxbc::RootParameterHeader H, size_t L) {
+ ParametersInfo.push_back(RootParameterInfo(H, L));
+ }
+
+ void addParameter(dxbc::RootParameterHeader H, dxbc::RootConstants C) {
+ addInfo(H, Constants.size());
+ Constants.push_back(C);
+ }
+
+ void addParameter(dxbc::RootParameterHeader H,
+ dxbc::RTS0::v1::RootDescriptor D) {
+ addInfo(H, Descriptors.size());
+ Descriptors.push_back(D);
+ }
+
+ void addParameter(dxbc::RootParameterHeader H,
+ dxbc::RTS0::v2::RootDescriptor D) {
+ addInfo(H, Descriptors.size());
+ Descriptors.push_back(D);
+ }
+
+ std::optional<ParametersView> getParameter(const RootParameterInfo *H) const {
+ switch (H->Header.ParameterType) {
+ case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+ return &Constants[H->Location];
+ case llvm::to_underlying(dxbc::RootParameterType::CBV):
+ case llvm::to_underlying(dxbc::RootParameterType::SRV):
+ case llvm::to_underlying(dxbc::RootParameterType::UAV):
+ const RootDescriptor &VersionedParam = Descriptors[H->Location];
+ if (std::holds_alternative<dxbc::RTS0::v1::RootDescriptor>(
+ VersionedParam)) {
+ return &std::get<dxbc::RTS0::v1::RootDescriptor>(VersionedParam);
+ }
+ return &std::get<dxbc::RTS0::v2::RootDescriptor>(VersionedParam);
+ }
+
+ return std::nullopt;
+ }
----------------
bogner wrote:
I'm not really convinced that the abstraction that the `std::variant` and the generic `getParameter` are providing are really helping much here. Consider this simplified API:
```c++
const std::pair<uint32_t, uint32_t>
getTypeAndLocForParameter(uint32_t Index) const {
const RootParameterInfo &Info = ParametersInfo[Index];
return {Info.Header.ParameterType, Info.Location};
}
const dxbc::RootConstants &getConstant(size_t Index) const {
return Constants[Index];
}
const dxbc::RTS0::v2::RootDescriptor &getRootDescriptor(size_t Index) const {
return Descriptors[Index];
}
```
The logic to use this is more or less the same - instead of the `holds_alternative` type checks we simply check against the type enum we already have:
```diff
- auto P = ParametersContainer.getParameter(ParametersContainer[I]);
- if (std::holds_alternative<const dxbc::RootConstants *>(P.value())) {
- auto *Constants = std::get<const dxbc::RootConstants *>(P.value());
- support::endian::write(BOS, Constants->ShaderRegister,
- llvm::endianness::little);
+ const auto &[Type, Loc] = ParametersContainer.getTypeAndLocForParameter(I);
+ switch (Type) {
+ case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
+ const dxbc::RootConstants &Constants =
+ ParametersContainer.getConstant(Loc);
+ support::endian::write(BOS, Constants.ShaderRegister,
+ llvm::endianness::little);
```
I think `std::variant` has its uses when we need something akin to a type safe union or we want to use visitor patterns to handle a large number of cases, but if we're just going to switch over the types anyway I think it just adds a layer of abstraction that needs to be looked through when reading the code to understand it.
https://github.com/llvm/llvm-project/pull/137284
More information about the llvm-commits
mailing list