Skip to content

Commit c21f48e

Browse files
authored
[HLSL][SPIR-V] Add Vulkan to target triple (llvm#76749)
Add support for specifying the logical SPIR-V target environment in the triple as Vulkan. When compiling HLSL, this replaces the DirectX Shader Model with a Vulkan environment instead. Currently, the only supported combinations of SPIR-V version and Vulkan environment are: - Vulkan 1.2 and SPIR-V 1.5 - Vulkan 1.3 and SPIR-V 1.6 Fixes llvm#70051
1 parent b689e16 commit c21f48e

File tree

8 files changed

+132
-83
lines changed

8 files changed

+132
-83
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,10 +735,10 @@ def err_drv_dxc_missing_target_profile : Error<
735735
def err_drv_hlsl_unsupported_target : Error<
736736
"HLSL code generation is unsupported for target '%0'">;
737737
def err_drv_hlsl_bad_shader_required_in_target : Error<
738-
"shader %select{model|stage}0 is required in target '%1' for HLSL code generation">;
738+
"%select{shader model|Vulkan environment|shader stage}0 is required as %select{OS|environment}1 in target '%2' for HLSL code generation">;
739739

740740
def err_drv_hlsl_bad_shader_unsupported : Error<
741-
"shader %select{model|stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
741+
"%select{shader model|Vulkan environment|shader stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
742742
def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
743743
"Resulting DXIL will not be validated or signed for use in release environments.">,
744744
InGroup<DXILValidation>;

clang/lib/Basic/Targets/SPIR.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "clang/Basic/TargetInfo.h"
1818
#include "clang/Basic/TargetOptions.h"
1919
#include "llvm/Support/Compiler.h"
20+
#include "llvm/Support/VersionTuple.h"
2021
#include "llvm/TargetParser/Triple.h"
2122
#include <optional>
2223

@@ -301,8 +302,9 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {
301302
: BaseSPIRVTargetInfo(Triple, Opts) {
302303
assert(Triple.getArch() == llvm::Triple::spirv &&
303304
"Invalid architecture for Logical SPIR-V.");
304-
assert(Triple.getOS() == llvm::Triple::ShaderModel &&
305-
"Logical SPIR-V requires a valid ShaderModel.");
305+
assert(Triple.getOS() == llvm::Triple::Vulkan &&
306+
Triple.getVulkanVersion() != llvm::VersionTuple(0) &&
307+
"Logical SPIR-V requires a valid Vulkan environment.");
306308
assert(Triple.getEnvironment() >= llvm::Triple::Pixel &&
307309
Triple.getEnvironment() <= llvm::Triple::Amplification &&
308310
"Logical SPIR-V environment must be a valid shader stage.");

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4236,20 +4236,35 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
42364236
// TODO: Revisit restricting SPIR-V to logical once we've figured out how to
42374237
// handle PhysicalStorageBuffer64 memory model
42384238
if (T.isDXIL() || T.isSPIRVLogical()) {
4239-
enum { ShaderModel, ShaderStage };
4239+
enum { ShaderModel, VulkanEnv, ShaderStage };
4240+
enum { OS, Environment };
4241+
4242+
int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;
4243+
42404244
if (T.getOSName().empty()) {
42414245
Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4242-
<< ShaderModel << T.str();
4243-
} else if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
4244-
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4245-
<< ShaderModel << T.getOSName() << T.str();
4246+
<< ExpectedOS << OS << T.str();
42464247
} else if (T.getEnvironmentName().empty()) {
42474248
Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4248-
<< ShaderStage << T.str();
4249+
<< ShaderStage << Environment << T.str();
42494250
} else if (!T.isShaderStageEnvironment()) {
42504251
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
42514252
<< ShaderStage << T.getEnvironmentName() << T.str();
42524253
}
4254+
4255+
if (T.isDXIL()) {
4256+
if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
4257+
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4258+
<< ShaderModel << T.getOSName() << T.str();
4259+
}
4260+
} else if (T.isSPIRVLogical()) {
4261+
if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {
4262+
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4263+
<< VulkanEnv << T.getOSName() << T.str();
4264+
}
4265+
} else {
4266+
llvm_unreachable("expected DXIL or SPIR-V target");
4267+
}
42534268
} else
42544269
Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
42554270
}

clang/test/Driver/hlsl-lang-targets-spirv.hlsl

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,39 @@
33
// Supported targets
44
//
55
// RUN: %clang -target dxil-unknown-shadermodel6.2-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
6-
// RUN: %clang -target spirv-unknown-shadermodel6.2-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
6+
// RUN: %clang -target spirv-unknown-vulkan-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
7+
// RUN: %clang -target spirv-unknown-vulkan1.2-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
8+
// RUN: %clang -target spirv-unknown-vulkan1.3-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
9+
// RUN: %clang -target spirv1.5-unknown-vulkan1.2-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
10+
// RUN: %clang -target spirv1.6-unknown-vulkan1.3-compute %s -S -o /dev/null 2>&1 | FileCheck --allow-empty --check-prefix=CHECK-VALID %s
711

8-
// Empty shader model
12+
// Empty Vulkan environment
913
//
1014
// RUN: not %clang -target spirv %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s
1115

12-
// Invalid shader models
16+
// Invalid Vulkan environment
1317
//
14-
// RUN: not %clang -target spirv--unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
18+
// RUN: not %clang -target spirv--shadermodel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
19+
// RUN: not %clang -target spirv-unknown-vulkan1.0-compute %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
20+
// RUN: not %clang -target spirv1.5-unknown-vulkan1.3-compute %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
21+
22+
// Invalid SPIR-V version
23+
// RUN: not %clang -target spirv1.0-unknown-vulkan-compute %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
1524

1625
// Empty shader stage
1726
//
18-
// RUN: not %clang -target spirv--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
27+
// RUN: not %clang -target spirv--vulkan %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
1928

2029
// Invalid shader stages
2130
//
22-
// RUN: not %clang -target spirv--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
31+
// RUN: not %clang -target spirv--vulkan-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
2332

2433
// CHECK-VALID-NOT: error:
25-
// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
26-
// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
27-
// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
34+
// CHECK-NO-OS: error: Vulkan environment is required as OS in target '{{.*}}' for HLSL code generation
35+
// CHECK-BAD-OS: error: Vulkan environment '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
36+
// CHECK-NO-ENV: error: shader stage is required as environment in target '{{.*}}' for HLSL code generation
2837
// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
38+
// CHECK-BAD-TARGET: error: HLSL code generation is unsupported for target '{{.*}}'
2939

3040
[shader("compute"), numthreads(1,1,1)]
3141
void main() {}

clang/test/Driver/hlsl-lang-targets.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// REQUIRES: dxil-registered-target
1+
// REQUIRES: directx-registered-target
22

33
// Supported targets
44
//
@@ -43,9 +43,9 @@
4343
// RUN: not %clang -target amdgcn %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
4444

4545
// CHECK-VALID-NOT: error:
46-
// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
46+
// CHECK-NO-OS: error: shader model is required as OS in target '{{.*}}' for HLSL code generation
4747
// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
48-
// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
48+
// CHECK-NO-ENV: error: shader stage is required as environment in target '{{.*}}' for HLSL code generation
4949
// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
5050
// CHECK-BAD-TARGET: error: HLSL code generation is unsupported for target '{{.*}}'
5151

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ class Triple {
164164
SPIRVSubArch_v13,
165165
SPIRVSubArch_v14,
166166
SPIRVSubArch_v15,
167+
SPIRVSubArch_v16,
167168
};
168169
enum VendorType {
169170
UnknownVendor,
@@ -224,7 +225,8 @@ class Triple {
224225
ShaderModel, // DirectX ShaderModel
225226
LiteOS,
226227
Serenity,
227-
LastOSType = Serenity
228+
Vulkan, // Vulkan SPIR-V
229+
LastOSType = Vulkan
228230
};
229231
enum EnvironmentType {
230232
UnknownEnvironment,
@@ -410,6 +412,10 @@ class Triple {
410412
/// Parse the version number as with getOSVersion.
411413
VersionTuple getDriverKitVersion() const;
412414

415+
/// Parse the Vulkan version number from the OSVersion and SPIR-V version
416+
/// (SubArch). This should only be called with Vulkan SPIR-V triples.
417+
VersionTuple getVulkanVersion() const;
418+
413419
/// @}
414420
/// @name Direct Component Access
415421
/// @{
@@ -775,6 +781,8 @@ class Triple {
775781
return getOS() == Triple::ShaderModel;
776782
}
777783

784+
bool isVulkanOS() const { return getOS() == Triple::Vulkan; }
785+
778786
bool isShaderStageEnvironment() const {
779787
EnvironmentType Env = getEnvironment();
780788
return Env == Triple::Pixel || Env == Triple::Vertex ||

llvm/lib/TargetParser/Triple.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/TargetParser/Triple.h"
10+
#include "llvm/ADT/DenseMap.h"
1011
#include "llvm/ADT/SmallString.h"
1112
#include "llvm/ADT/StringExtras.h"
1213
#include "llvm/ADT/StringSwitch.h"
@@ -274,6 +275,7 @@ StringRef Triple::getOSTypeName(OSType Kind) {
274275
case ShaderModel: return "shadermodel";
275276
case LiteOS: return "liteos";
276277
case XROS: return "xros";
278+
case Vulkan: return "vulkan";
277279
}
278280

279281
llvm_unreachable("Invalid OSType");
@@ -551,8 +553,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
551553
.Case("hsail64", Triple::hsail64)
552554
.Case("spir", Triple::spir)
553555
.Case("spir64", Triple::spir64)
554-
.Cases("spirv", "spirv1.0", "spirv1.1", "spirv1.2",
555-
"spirv1.3", "spirv1.4", "spirv1.5", Triple::spirv)
556+
.Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv)
556557
.Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2",
557558
"spirv32v1.3", "spirv32v1.4", "spirv32v1.5", Triple::spirv32)
558559
.Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2",
@@ -646,6 +647,7 @@ static Triple::OSType parseOS(StringRef OSName) {
646647
.StartsWith("shadermodel", Triple::ShaderModel)
647648
.StartsWith("liteos", Triple::LiteOS)
648649
.StartsWith("serenity", Triple::Serenity)
650+
.StartsWith("vulkan", Triple::Vulkan)
649651
.Default(Triple::UnknownOS);
650652
}
651653

@@ -730,6 +732,7 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
730732
.EndsWith("v1.3", Triple::SPIRVSubArch_v13)
731733
.EndsWith("v1.4", Triple::SPIRVSubArch_v14)
732734
.EndsWith("v1.5", Triple::SPIRVSubArch_v15)
735+
.EndsWith("v1.6", Triple::SPIRVSubArch_v16)
733736
.Default(Triple::NoSubArch);
734737

735738
StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
@@ -1345,6 +1348,31 @@ VersionTuple Triple::getDriverKitVersion() const {
13451348
}
13461349
}
13471350

1351+
VersionTuple Triple::getVulkanVersion() const {
1352+
if (getArch() != spirv || getOS() != Vulkan)
1353+
llvm_unreachable("invalid Vulkan SPIR-V triple");
1354+
1355+
VersionTuple VulkanVersion = getOSVersion();
1356+
SubArchType SpirvVersion = getSubArch();
1357+
1358+
llvm::DenseMap<VersionTuple, SubArchType> ValidVersionMap = {
1359+
// Vulkan 1.2 -> SPIR-V 1.5.
1360+
{VersionTuple(1, 2), SPIRVSubArch_v15},
1361+
// Vulkan 1.3 -> SPIR-V 1.6.
1362+
{VersionTuple(1, 3), SPIRVSubArch_v16}};
1363+
1364+
// If Vulkan version is unset, default to 1.2.
1365+
if (VulkanVersion == VersionTuple(0))
1366+
VulkanVersion = VersionTuple(1, 2);
1367+
1368+
if (ValidVersionMap.contains(VulkanVersion) &&
1369+
(ValidVersionMap.lookup(VulkanVersion) == SpirvVersion ||
1370+
SpirvVersion == NoSubArch))
1371+
return VulkanVersion;
1372+
1373+
return VersionTuple(0);
1374+
}
1375+
13481376
void Triple::setTriple(const Twine &Str) {
13491377
*this = Triple(Str);
13501378
}

0 commit comments

Comments
 (0)