Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H

#include "llvm/Support/DXILABI.h"
#include "llvm/Support/raw_ostream.h"
#include <variant>

namespace llvm {
Expand Down Expand Up @@ -52,12 +53,16 @@ enum class RegisterType { BReg, TReg, UReg, SReg };
struct Register {
RegisterType ViewType;
uint32_t Number;

void dump(raw_ostream &OS) const;
};

// Models the end of a descriptor table and stores its visibility
struct DescriptorTable {
ShaderVisibility Visibility = ShaderVisibility::All;
uint32_t NumClauses = 0; // The number of clauses in the table

void dump(raw_ostream &OS) const;
};

static const uint32_t NumDescriptorsUnbounded = 0xffffffff;
Expand Down Expand Up @@ -86,6 +91,8 @@ struct DescriptorTableClause {
break;
}
}

void dump(raw_ostream &OS) const;
};

// Models RootElement : DescriptorTable | DescriptorTableClause
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Frontend/HLSL/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_llvm_component_library(LLVMFrontendHLSL
CBuffer.cpp
HLSLResource.cpp
HLSLRootSignature.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
Expand Down
154 changes: 154 additions & 0 deletions llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file This file contains helpers for working with HLSL Root Signatures.
///
//===----------------------------------------------------------------------===//

#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
#include "llvm/ADT/bit.h"

namespace llvm {
namespace hlsl {
namespace rootsig {

static void dumpRegType(raw_ostream &OS, RegisterType Type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole file becomes a bit simpler and cleaner if we define a bunch of operator<<s instead of dump functions. So here we could have

static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {
  switch (Reg.Type) {
  case RegisterType::BReg:
    OS << "b";
    break;
  // ...
  }
  OS << Number;
  return OS;

and similarly for the rest of these static dump functions. Then the publicly visible dump() methods can be implemented as OS << "Foo(" << thing1 << "bar = " << thing2 << ")" etc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

switch (Type) {
case RegisterType::BReg:
OS << "b";
break;
case RegisterType::TReg:
OS << "t";
break;
case RegisterType::UReg:
OS << "u";
break;
case RegisterType::SReg:
OS << "s";
break;
}
}

void Register::dump(raw_ostream &OS) const {
dumpRegType(OS, ViewType);
OS << Number;
}

static void dumpVisibility(raw_ostream &OS, ShaderVisibility Visibility) {
switch (Visibility) {
case ShaderVisibility::All:
OS << "All";
break;
case ShaderVisibility::Vertex:
OS << "Vertex";
break;
case ShaderVisibility::Hull:
OS << "Hull";
break;
case ShaderVisibility::Domain:
OS << "Domain";
break;
case ShaderVisibility::Geometry:
OS << "Geometry";
break;
case ShaderVisibility::Pixel:
OS << "Pixel";
break;
case ShaderVisibility::Amplification:
OS << "Amplification";
break;
case ShaderVisibility::Mesh:
OS << "Mesh";
break;
}
}

void DescriptorTable::dump(raw_ostream &OS) const {
OS << "DescriptorTable(numClauses = " << NumClauses;
OS << ", visibility = ";
dumpVisibility(OS, Visibility);
OS << ")";
}

static void dumpClauseType(raw_ostream &OS, ClauseType Type) {
switch (Type) {
case ClauseType::CBuffer:
OS << "CBV";
break;
case ClauseType::SRV:
OS << "SRV";
break;
case ClauseType::UAV:
OS << "UAV";
break;
case ClauseType::Sampler:
OS << "Sampler";
break;
}
}

static void dumpDescriptorRangeFlag(raw_ostream &OS, unsigned Bit) {
switch (static_cast<DescriptorRangeFlags>(Bit)) {
case DescriptorRangeFlags::DescriptorsVolatile:
OS << "DescriptorsVolatile";
break;
case DescriptorRangeFlags::DataVolatile:
OS << "DataVolatile";
break;
case DescriptorRangeFlags::DataStaticWhileSetAtExecute:
OS << "DataStaticWhileSetAtExecute";
break;
case DescriptorRangeFlags::DataStatic:
OS << "DataStatic";
break;
case DescriptorRangeFlags::DescriptorsStaticKeepingBufferBoundsChecks:
OS << "DescriptorsStaticKeepingBufferBoundsChecks";
break;
default:
OS << "invalid: " << Bit;
break;
}
}

static void dumpDescriptorRangeFlags(raw_ostream &OS,
DescriptorRangeFlags Flags) {
bool FlagSet = false;
unsigned Remaining = llvm::to_underlying(Flags);
while (Remaining) {
unsigned Bit = 1u << llvm::countr_zero(Remaining);
if (Remaining & Bit) {
if (FlagSet)
OS << " | ";
dumpDescriptorRangeFlag(OS, Bit);
FlagSet = true;
}
Remaining &= ~Bit;
}
if (!FlagSet)
OS << "None";
}

void DescriptorTableClause::dump(raw_ostream &OS) const {
dumpClauseType(OS, Type);
OS << "(";
Reg.dump(OS);
OS << ", numDescriptors = " << NumDescriptors;
OS << ", space = " << Space;
OS << ", offset = ";
if (Offset == DescriptorTableOffsetAppend)
OS << "DescriptorTableOffsetAppend";
else
OS << Offset;
OS << ", flags = ";
dumpDescriptorRangeFlags(OS, Flags);
OS << ")";
}

} // namespace rootsig
} // namespace hlsl
} // namespace llvm
2 changes: 2 additions & 0 deletions llvm/unittests/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
Analysis
Core
FrontendHLSL
FrontendOpenACC
FrontendOpenMP
Passes
Expand All @@ -10,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
)

add_llvm_unittest(LLVMFrontendTests
HLSLRootSignatureDumpTest.cpp
OpenACCTest.cpp
OpenMPContextTest.cpp
OpenMPIRBuilderTest.cpp
Expand Down
111 changes: 111 additions & 0 deletions llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//===-------- HLSLRootSignatureDumpTest.cpp - RootSignature dump tests ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
#include "gtest/gtest.h"

using namespace llvm::hlsl::rootsig;

namespace {

TEST(HLSLRootSignatureTest, DescriptorCBVClauseDump) {
DescriptorTableClause Clause;
Clause.Type = ClauseType::CBuffer;
Clause.Reg = {RegisterType::BReg, 0};
Clause.setDefaultFlags();

std::string Out;
llvm::raw_string_ostream OS(Out);
Clause.dump(OS);
OS.flush();

std::string Expected = "CBV(b0, numDescriptors = 1, space = 0, "
"offset = DescriptorTableOffsetAppend, "
"flags = DataStaticWhileSetAtExecute)";
EXPECT_EQ(Out, Expected);
}

TEST(HLSLRootSignatureTest, DescriptorSRVClauseDump) {
DescriptorTableClause Clause;
Clause.Type = ClauseType::SRV;
Clause.Reg = {RegisterType::TReg, 0};
Clause.NumDescriptors = 2;
Clause.Space = 42;
Clause.Offset = 3;
Clause.Flags = DescriptorRangeFlags::None;

std::string Out;
llvm::raw_string_ostream OS(Out);
Clause.dump(OS);
OS.flush();

std::string Expected =
"SRV(t0, numDescriptors = 2, space = 42, offset = 3, flags = None)";
EXPECT_EQ(Out, Expected);
}

TEST(HLSLRootSignatureTest, DescriptorUAVClauseDump) {
DescriptorTableClause Clause;
Clause.Type = ClauseType::UAV;
Clause.Reg = {RegisterType::UReg, 92374};
Clause.NumDescriptors = 3298;
Clause.Space = 932847;
Clause.Offset = 1;
Clause.Flags = DescriptorRangeFlags::ValidFlags;

std::string Out;
llvm::raw_string_ostream OS(Out);
Clause.dump(OS);
OS.flush();

std::string Expected =
"UAV(u92374, numDescriptors = 3298, space = 932847, offset = 1, flags = "
"DescriptorsVolatile | "
"DataVolatile | "
"DataStaticWhileSetAtExecute | "
"DataStatic | "
"DescriptorsStaticKeepingBufferBoundsChecks)";
EXPECT_EQ(Out, Expected);
}

TEST(HLSLRootSignatureTest, DescriptorSamplerClauseDump) {
DescriptorTableClause Clause;
Clause.Type = ClauseType::Sampler;
Clause.Reg = {RegisterType::SReg, 0};
Clause.NumDescriptors = 2;
Clause.Space = 42;
Clause.Offset = DescriptorTableOffsetAppend;
Clause.Flags = DescriptorRangeFlags::ValidSamplerFlags;

std::string Out;
llvm::raw_string_ostream OS(Out);
Clause.dump(OS);
OS.flush();

std::string Expected = "Sampler(s0, numDescriptors = 2, space = 42, offset = "
"DescriptorTableOffsetAppend, "
"flags = DescriptorsVolatile)";
EXPECT_EQ(Out, Expected);
}

TEST(HLSLRootSignatureTest, DescriptorTableDump) {
DescriptorTable Table;
Table.NumClauses = 4;
Table.Visibility = ShaderVisibility::Geometry;

std::string Out;
llvm::raw_string_ostream OS(Out);
Table.dump(OS);
OS.flush();

std::string Expected =
"DescriptorTable(numClauses = 4, visibility = Geometry)";
EXPECT_EQ(Out, Expected);
}

} // namespace