Skip to content

Commit 3488da4

Browse files
committed
[HLSL][SPIR-V] Implement vk::push_constant
Implements initial support for vk::push_constant. As is, this allows handling simple push constants, but has one main issue: layout can be incorrect (See #168401). The layout issue being not only push-constant related, it's ignored for this PR. The frontend part of the implementation is straightforward: - adding a new attribute - when targeting vulkan/spirv, we process it - global variables with this attribute gets a new AS: hlsl_push_constant The IR has nothing specific, only some RO globals in this new AS. On the SPIR-V side, we not convert this AS into a PushConstant storage class. But this creates some issues: the variables in this storage class must have a specific set of decoration to define their layout. Current infra to create the SPIR-V types lacks the context required to make this decision: no indication on the AS or context around the type being created. Refactoring this would be a heavy task as it would require getting this information in every place using the GR for type creation. Instead, we do something similar to CBuffers: - find all globals with this address space, and change their type to a target-specific type. - insert a new intrinsic in place of every reference to this global variable. This allow the backend to handle both layout variables loads and type lowering independently. Type lowering has nothing specific: when we encounter a target extension type with spirv.PushConstant, we lower this to the correct SPIR-V type with the proper offset & block decorations. As for the intrinsic, it's mostly a no-op, but required since we have this target-specific type.
1 parent 7e29448 commit 3488da4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+547
-24
lines changed

clang/include/clang/Basic/AddressSpaces.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum class LangAS : unsigned {
6262
hlsl_private,
6363
hlsl_device,
6464
hlsl_input,
65+
hlsl_push_constant,
6566

6667
// Wasm specific address spaces.
6768
wasm_funcref,

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,6 +5164,14 @@ def HLSLVkExtBuiltinInput : InheritableAttr {
51645164
let Documentation = [HLSLVkExtBuiltinInputDocs];
51655165
}
51665166

5167+
def HLSLVkPushConstant : InheritableAttr {
5168+
let Spellings = [CXX11<"vk", "push_constant">];
5169+
let Args = [];
5170+
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
5171+
let LangOpts = [HLSL];
5172+
let Documentation = [HLSLVkPushConstantDocs];
5173+
}
5174+
51675175
def HLSLVkConstantId : InheritableAttr {
51685176
let Spellings = [CXX11<"vk", "constant_id">];
51695177
let Args = [IntArgument<"Id">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8794,6 +8794,11 @@ https://github.com/microsoft/hlsl-specs/blob/main/proposals/0011-inline-spirv.md
87948794
}];
87958795
}
87968796

8797+
def HLSLVkPushConstantDocs : Documentation {
8798+
let Category = DocCatVariable;
8799+
let Content = [{ FIXME }];
8800+
}
8801+
87978802
def AnnotateTypeDocs : Documentation {
87988803
let Category = DocCatType;
87998804
let Heading = "annotate_type";

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13216,6 +13216,9 @@ def err_hlsl_attr_invalid_type : Error<
1321613216
"attribute %0 only applies to a field or parameter of type '%1'">;
1321713217
def err_hlsl_attr_invalid_ast_node : Error<
1321813218
"attribute %0 only applies to %1">;
13219+
def err_hlsl_attr_incompatible
13220+
: Error<"%0 attribute is not compatible with %1 attribute">;
13221+
1321913222
def err_hlsl_entry_shader_attr_mismatch : Error<
1322013223
"%0 attribute on entry function does not match the target profile">;
1322113224
def err_hlsl_numthreads_argument_oor : Error<"argument '%select{X|Y|Z}0' to numthreads attribute cannot exceed %1">;
@@ -13333,6 +13336,9 @@ def err_hlsl_incomplete_resource_array_in_function_param: Error<
1333313336
def err_hlsl_assign_to_global_resource: Error<
1333413337
"assignment to global resource variable %0 is not allowed">;
1333513338

13339+
def err_hlsl_push_constant_unique
13340+
: Error<"cannot have more than one push constant block">;
13341+
1333613342
// Layout randomization diagnostics.
1333713343
def err_non_designated_init_used : Error<
1333813344
"a randomized struct can only be initialized with a designated initializer">;

clang/include/clang/Basic/HLSLRuntime.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef CLANG_BASIC_HLSLRUNTIME_H
1515
#define CLANG_BASIC_HLSLRUNTIME_H
1616

17+
#include "clang/Basic/AddressSpaces.h"
1718
#include "clang/Basic/LangOptions.h"
1819
#include <cstdint>
1920

@@ -30,6 +31,10 @@ getStageFromEnvironment(const llvm::Triple::EnvironmentType &E) {
3031
return static_cast<ShaderStage>(Pipeline);
3132
}
3233

34+
constexpr bool isInitializedByPipeline(LangAS AS) {
35+
return AS == LangAS::hlsl_input || AS == LangAS::hlsl_push_constant;
36+
}
37+
3338
#define ENUM_COMPARE_ASSERT(Value) \
3439
static_assert( \
3540
getStageFromEnvironment(llvm::Triple::Value) == ShaderStage::Value, \

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class SemaHLSL : public SemaBase {
188188
void handleSemanticAttr(Decl *D, const ParsedAttr &AL);
189189

190190
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL);
191+
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL);
191192

192193
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
193194
QualType ProcessResourceTypeAttributes(QualType Wrapped);
@@ -237,6 +238,8 @@ class SemaHLSL : public SemaBase {
237238

238239
IdentifierInfo *RootSigOverrideIdent = nullptr;
239240

241+
bool HasDeclaredAPushConstant = false;
242+
240243
// Information about the current subtree being flattened.
241244
struct SemanticInfo {
242245
HLSLParsedSemanticAttr *Semantic;

clang/lib/AST/Type.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ bool Qualifiers::isTargetAddressSpaceSupersetOf(LangAS A, LangAS B,
101101
(A == LangAS::Default && B == LangAS::hlsl_private) ||
102102
(A == LangAS::Default && B == LangAS::hlsl_device) ||
103103
(A == LangAS::Default && B == LangAS::hlsl_input) ||
104+
(A == LangAS::Default && B == LangAS::hlsl_push_constant) ||
104105
// Conversions from target specific address spaces may be legal
105106
// depending on the target information.
106107
Ctx.getTargetInfo().isAddressSpaceSupersetOf(A, B);

clang/lib/AST/TypePrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,6 +2694,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
26942694
return "hlsl_device";
26952695
case LangAS::hlsl_input:
26962696
return "hlsl_input";
2697+
case LangAS::hlsl_push_constant:
2698+
return "hlsl_push_constant";
26972699
case LangAS::wasm_funcref:
26982700
return "__funcref";
26992701
default:

clang/lib/Basic/TargetInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static const LangASMap FakeAddrSpaceMap = {
5252
15, // hlsl_private
5353
16, // hlsl_device
5454
17, // hlsl_input
55+
18, // hlsl_push_constant
5556
20, // wasm_funcref
5657
};
5758

clang/lib/Basic/Targets/AArch64.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ static const unsigned ARM64AddrSpaceMap[] = {
4848
0, // hlsl_private
4949
0, // hlsl_device
5050
0, // hlsl_input
51+
0, // hlsl_push_constant
5152
// Wasm address space values for this target are dummy values,
5253
// as it is only enabled for Wasm targets.
5354
20, // wasm_funcref

0 commit comments

Comments
 (0)