Skip to content

[HLSL][RootSignature] Add hlsl-rootsig-ver option to specify root signature version #144813

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions clang/include/clang/AST/Decl.h
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going through the commits 1 by 1 should be easier to read then from top to bottom of this diff.

Original file line number Diff line number Diff line change
Expand Up @@ -5179,6 +5179,8 @@ class HLSLRootSignatureDecl final
llvm::hlsl::rootsig::RootElement> {
friend TrailingObjects;

llvm::dxil::RootSignatureVersion RootSigVer;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a member of a HLSLRootSignatureDecl - it can probably just be called Version.


unsigned NumElems;

llvm::hlsl::rootsig::RootElement *getElems() { return getTrailingObjects(); }
Expand All @@ -5188,16 +5190,20 @@ class HLSLRootSignatureDecl final
}

HLSLRootSignatureDecl(DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
llvm::dxil::RootSignatureVersion RootSigVer,
unsigned NumElems);

public:
static HLSLRootSignatureDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
llvm::dxil::RootSignatureVersion RootSigVer,
ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements);

static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);

llvm::dxil::RootSignatureVersion getVersion() const { return RootSigVer; }

ArrayRef<llvm::hlsl::rootsig::RootElement> getRootElements() const {
return {getElems(), NumElems};
}
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DXILABI.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>
#include <string>
Expand Down Expand Up @@ -623,6 +624,10 @@ class LangOptions : public LangOptionsBase {
// implementation on real-world examples.
std::string OpenACCMacroOverride;

/// The HLSL root signature version for dxil.
llvm::dxil::RootSignatureVersion HLSLRootSigVer =
llvm::dxil::RootSignatureVersion::rootsig_1_1;

// Indicates if the wasm-opt binary must be ignored in the case of a
// WebAssembly target.
bool NoWasmOpt = false;
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -9288,6 +9288,15 @@ def fcgl : DXCFlag<"fcgl">, Alias<emit_pristine_llvm>;
def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias<fnative_half_type>,
HelpText<"Enable 16-bit types and disable min precision types."
"Available in HLSL 2018 and shader model 6.2.">;
def hlsl_rootsig_ver :
Option<["-"], "hlsl-rootsig-ver", KIND_SEPARATE>,
Group<dxc_Group>,
Visibility<[ClangOption, CC1Option, DXCOption]>,
HelpText<"Root Signature Version">,
Values<"rootsig_1_0,rootsig_1_1">,
NormalizedValuesScope<"llvm::dxil::RootSignatureVersion">,
NormalizedValues<["rootsig_1_0", "rootsig_1_1"]>,
MarshallingInfoEnum<LangOpts<"HLSLRootSigVer">, "rootsig_1_1">;
def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>,
Group<dxc_Group>,
Visibility<[ClangOption, CC1Option]>,
Expand Down
18 changes: 10 additions & 8 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5853,21 +5853,21 @@ bool HLSLBufferDecl::buffer_decls_empty() {
// HLSLRootSignatureDecl Implementation
//===----------------------------------------------------------------------===//

HLSLRootSignatureDecl::HLSLRootSignatureDecl(DeclContext *DC,
SourceLocation Loc,
IdentifierInfo *ID,
unsigned NumElems)
HLSLRootSignatureDecl::HLSLRootSignatureDecl(
DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
llvm::dxil::RootSignatureVersion RootSigVer, unsigned NumElems)
: NamedDecl(Decl::Kind::HLSLRootSignature, DC, Loc, DeclarationName(ID)),
NumElems(NumElems) {}
RootSigVer(RootSigVer), NumElems(NumElems) {}

HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create(
ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
llvm::dxil::RootSignatureVersion RootSigVer,
ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements) {
HLSLRootSignatureDecl *RSDecl =
new (C, DC,
additionalSizeToAlloc<llvm::hlsl::rootsig::RootElement>(
RootElements.size()))
HLSLRootSignatureDecl(DC, Loc, ID, RootElements.size());
HLSLRootSignatureDecl(DC, Loc, ID, RootSigVer, RootElements.size());
auto *StoredElems = RSDecl->getElems();
std::uninitialized_copy(RootElements.begin(), RootElements.end(),
StoredElems);
Expand All @@ -5876,8 +5876,10 @@ HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create(

HLSLRootSignatureDecl *
HLSLRootSignatureDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
HLSLRootSignatureDecl *Result = new (C, ID)
HLSLRootSignatureDecl(nullptr, SourceLocation(), nullptr, /*NumElems=*/0);
HLSLRootSignatureDecl *Result = new (C, ID) HLSLRootSignatureDecl(
nullptr, SourceLocation(), nullptr,
/*RootSigVer*/ llvm::dxil::RootSignatureVersion::rootsig_1_0,
/*NumElems=*/0);
return Result;
}

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3041,6 +3041,16 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
void TextNodeDumper::VisitHLSLRootSignatureDecl(
const HLSLRootSignatureDecl *D) {
dumpName(D);
OS << " version: ";
switch (D->getVersion()) {
case llvm::dxil::RootSignatureVersion::rootsig_1_0:
OS << "1.0";
break;
case llvm::dxil::RootSignatureVersion::rootsig_1_1:
OS << "1.1";
break;
}
OS << ", ";
llvm::hlsl::rootsig::dumpRootElements(OS, D->getRootElements());
}

Expand Down
24 changes: 17 additions & 7 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,22 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
DXILValMD->addOperand(Val);
}

void addRootSignature(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements,
void addRootSignature(llvm::dxil::RootSignatureVersion RootSigVer,
ArrayRef<llvm::hlsl::rootsig::RootElement> Elements,
llvm::Function *Fn, llvm::Module &M) {
auto &Ctx = M.getContext();
IRBuilder<> Builder(Ctx);

llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements);
MDNode *RootSignature = Builder.BuildRootSignature();
MDNode *FnPairing =
MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature});
llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
MDNode *RootSignature = RSBuilder.BuildRootSignature();

Metadata *Operands[] = {
ValueAsMetadata::get(Fn),
RootSignature,
ConstantAsMetadata::get(
Builder.getInt32(llvm::to_underlying(RootSigVer))),
};
MDNode *FnPairing = MDNode::get(Ctx, Operands);

StringRef RootSignatureValKey = "dx.rootsignatures";
auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
Expand Down Expand Up @@ -465,9 +473,11 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,

// Add and identify root signature to function, if applicable
for (const Attr *Attr : FD->getAttrs()) {
if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr))
addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn,
if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
auto *RSDecl = RSAttr->getSignatureDecl();
addRootSignature(RSDecl->getVersion(), RSDecl->getRootElements(), EntryFn,
M);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3834,7 +3834,8 @@ static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
options::OPT_emit_obj,
options::OPT_disable_llvm_passes,
options::OPT_fnative_half_type,
options::OPT_hlsl_entrypoint};
options::OPT_hlsl_entrypoint,
options::OPT_hlsl_rootsig_ver};
if (!types::isHLSL(InputType))
return;
for (const auto &Arg : ForwardedArguments)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,10 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< "-hlsl-entry" << GetInputKindName(IK);

if (Args.hasArg(OPT_hlsl_rootsig_ver) && !LangOpts.HLSL)
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< "-hlsl-rootsig-ver" << GetInputKindName(IK);

if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
Diags.Report(diag::warn_ignored_hip_only_option)
<< Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ void SemaHLSL::ActOnFinishRootSignatureDecl(

auto *SignatureDecl = HLSLRootSignatureDecl::Create(
SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc,
DeclIdent, Elements);
DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);

SignatureDecl->setImplicit();
SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());
Expand Down
8 changes: 8 additions & 0 deletions clang/test/AST/HLSL/RootSignatures-AST.hlsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
// RUN: -disable-llvm-passes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
// RUN: -hlsl-rootsig-ver rootsig_1_0 \
// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-V1_0
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
// RUN: -hlsl-rootsig-ver rootsig_1_1 \
// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-V1_1

// This test ensures that the sample root signature is parsed without error and
// the Attr AST Node is created succesfully. If an invalid root signature was
Expand All @@ -16,6 +22,8 @@
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"

// CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]]
// CHECK-V1_0: version: 1.0,
// CHECK-V1_1: version: 1.1,
// CHECK-SAME: RootElements{
// CHECK-SAME: CBV(b1, numDescriptors = 1, space = 0,
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DataStaticWhileSetAtExecute),
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenHLSL/RootSignature.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]],
// CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]], ![[#SS_ENTRY:]]}

// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]]}
// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], i32 2}
// CHECK: ![[#EMPTY]] = !{}

[shader("compute"), RootSignature("")]
[numthreads(1,1,1)]
void EmptyEntry() {}

// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]]}
// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 2}
// CHECK: ![[#DT_RS]] = !{![[#TABLE:]]}
// CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]}
// CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4}
Expand All @@ -25,7 +25,7 @@ void EmptyEntry() {}
[numthreads(1,1,1)]
void DescriptorTableEntry() {}

// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]]}
// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]], i32 2}
// CHECK: ![[#RF_RS]] = !{![[#ROOT_FLAGS:]]}
// CHECK: ![[#ROOT_FLAGS]] = !{!"RootFlags", i32 2114}

Expand All @@ -38,7 +38,7 @@ void DescriptorTableEntry() {}
[numthreads(1,1,1)]
void RootFlagsEntry() {}

// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]]}
// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]], i32 2}
// CHECK: ![[#RC_RS]] = !{![[#ROOT_CONSTANTS:]]}
// CHECK: ![[#ROOT_CONSTANTS]] = !{!"RootConstants", i32 5, i32 1, i32 2, i32 1}

Expand All @@ -52,7 +52,7 @@ void RootFlagsEntry() {}
[numthreads(1,1,1)]
void RootConstantsEntry() {}

// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]]}
// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]], i32 2}
// CHECK: ![[#RD_RS]] = !{![[#ROOT_CBV:]], ![[#ROOT_UAV:]], ![[#ROOT_SRV:]]}
// CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4}
// CHECK: ![[#ROOT_UAV]] = !{!"RootUAV", i32 0, i32 42, i32 3, i32 2}
Expand All @@ -66,7 +66,7 @@ void RootConstantsEntry() {}
[numthreads(1,1,1)]
void RootDescriptorsEntry() {}

// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]]}
// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]], i32 2}
// CHECK: ![[#SS_RS]] = !{![[#STATIC_SAMPLER:]]}

// checking filter = 0x4
Expand Down
15 changes: 15 additions & 0 deletions clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: %clang_dxc -T cs_6_0 -fcgl %s | FileCheck %s --check-prefix=CHECK-V1_1
// RUN: %clang_dxc -T cs_6_0 -fcgl -hlsl-rootsig-ver rootsig_1_0 %s | FileCheck %s --check-prefix=CHECK-V1_0
// RUN: %clang_dxc -T cs_6_0 -fcgl -hlsl-rootsig-ver rootsig_1_1 %s | FileCheck %s --check-prefix=CHECK-V1_1

// Test to demonstrate that we can specify the root-signature versions

// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]]}
// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]],
// CHECK-V1_0: i32 1}
// CHECK-V1_1: i32 2}
// CHECK: ![[#EMPTY]] = !{}

[shader("compute"), RootSignature("")]
[numthreads(1,1,1)]
void EmptyEntry() {}
6 changes: 6 additions & 0 deletions llvm/include/llvm/Support/DXILABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ enum class SamplerFeedbackType : uint32_t {
const unsigned MinWaveSize = 4;
const unsigned MaxWaveSize = 128;

// D3D_ROOT_SIGNATURE_VERSION
enum class RootSignatureVersion {
rootsig_1_0 = 0x1,
rootsig_1_1 = 0x2,
};
Comment on lines +102 to +106
Copy link
Contributor

Choose a reason for hiding this comment

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

Should these be defined in BinaryFormat/DXContainer.h with the other d3d12 constants? They don't seem like they belong in DXILABI to me.

Also the naming here feels a bit awkward - we're kind of repeating ourselves with RootSignatureVersion::rootsig_1_0 - Should it just be RootSignatureVersion::V1_0 or something like that?


} // namespace dxil
} // namespace llvm

Expand Down
Loading