Skip to content

Commit bc9044a

Browse files
authored
[SER] REORDER_SCOPE Barrier semantic flag (#7263)
- HLSL REORDER_SCOPE flag (available from SM6.9) - Make validator accept REORDER_SCOPE from DXIL 1.9
1 parent 90bfb66 commit bc9044a

File tree

11 files changed

+218
-14
lines changed

11 files changed

+218
-14
lines changed

include/dxc/DXIL/DxilConstants.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -1905,7 +1905,9 @@ enum class BarrierSemanticFlag : uint32_t {
19051905
GroupSync = 0x00000001, // GROUP_SYNC
19061906
GroupScope = 0x00000002, // GROUP_SCOPE
19071907
DeviceScope = 0x00000004, // DEVICE_SCOPE
1908-
ValidMask = 0x00000007,
1908+
LegacyFlags = 0x00000007,
1909+
ReorderScope = 0x00000008, // REORDER_SCOPE
1910+
ValidMask = 0x0000000F,
19091911
GroupFlags = GroupSync | GroupScope,
19101912
};
19111913

include/dxc/DXIL/DxilOperations.h

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ class OP {
151151
static bool IsDxilOpBarrier(OpCode C);
152152
static bool BarrierRequiresGroup(const llvm::CallInst *CI);
153153
static bool BarrierRequiresNode(const llvm::CallInst *CI);
154+
static bool BarrierRequiresReorder(const llvm::CallInst *CI);
154155
static DXIL::BarrierMode TranslateToBarrierMode(const llvm::CallInst *CI);
155156
static void GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
156157
unsigned &major, unsigned &minor,

lib/DXIL/DxilOperations.cpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
///////////////////////////////////////////////////////////////////////////////
1111

1212
#include "dxc/DXIL/DxilOperations.h"
13+
#include "dxc/DXIL/DxilConstants.h"
1314
#include "dxc/DXIL/DxilInstructions.h"
1415
#include "dxc/DXIL/DxilModule.h"
1516
#include "dxc/Support/Global.h"
@@ -3024,6 +3025,30 @@ bool OP::BarrierRequiresNode(const llvm::CallInst *CI) {
30243025
}
30253026
}
30263027

3028+
bool OP::BarrierRequiresReorder(const llvm::CallInst *CI) {
3029+
OpCode Opcode = OP::GetDxilOpFuncCallInst(CI);
3030+
switch (Opcode) {
3031+
case OpCode::BarrierByMemoryType: {
3032+
DxilInst_BarrierByMemoryType Barrier(const_cast<CallInst *>(CI));
3033+
if (!isa<ConstantInt>(Barrier.get_SemanticFlags()))
3034+
return false;
3035+
unsigned SemanticFlags = Barrier.get_SemanticFlags_val();
3036+
return (SemanticFlags & static_cast<unsigned>(
3037+
DXIL::BarrierSemanticFlag::ReorderScope)) != 0U;
3038+
}
3039+
case OpCode::BarrierByMemoryHandle: {
3040+
DxilInst_BarrierByMemoryHandle Barrier(const_cast<CallInst *>(CI));
3041+
if (!isa<ConstantInt>(Barrier.get_SemanticFlags()))
3042+
return false;
3043+
unsigned SemanticFlags = Barrier.get_SemanticFlags_val();
3044+
return (SemanticFlags & static_cast<unsigned>(
3045+
DXIL::BarrierSemanticFlag::ReorderScope)) != 0U;
3046+
}
3047+
default:
3048+
return false;
3049+
}
3050+
}
3051+
30273052
DXIL::BarrierMode OP::TranslateToBarrierMode(const llvm::CallInst *CI) {
30283053
OpCode opcode = OP::GetDxilOpFuncCallInst(CI);
30293054
switch (opcode) {
@@ -3046,6 +3071,12 @@ DXIL::BarrierMode OP::TranslateToBarrierMode(const llvm::CallInst *CI) {
30463071
semanticFlags = barrier.get_SemanticFlags_val();
30473072
}
30483073

3074+
// Disallow SM6.9+ semantic flags.
3075+
if (semanticFlags &
3076+
~static_cast<unsigned>(DXIL::BarrierSemanticFlag::LegacyFlags)) {
3077+
return DXIL::BarrierMode::Invalid;
3078+
}
3079+
30493080
// Mask to legacy flags, if allowed.
30503081
memoryTypeFlags = MaskMemoryTypeFlagsIfAllowed(
30513082
memoryTypeFlags, (unsigned)DXIL::MemoryTypeFlag::LegacyFlags);
@@ -3467,10 +3498,17 @@ void OP::GetMinShaderModelAndMask(const llvm::CallInst *CI,
34673498
minor = 8;
34683499
}
34693500
}
3501+
if (BarrierRequiresReorder(CI)) {
3502+
major = 6;
3503+
minor = 9;
3504+
mask &= SFLAG(Library) | SFLAG(RayGeneration);
3505+
return;
3506+
}
34703507
if (BarrierRequiresNode(CI)) {
34713508
mask &= SFLAG(Library) | SFLAG(Node);
34723509
return;
3473-
} else if (BarrierRequiresGroup(CI)) {
3510+
}
3511+
if (BarrierRequiresGroup(CI)) {
34743512
mask &= SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) |
34753513
SFLAG(Mesh) | SFLAG(Node);
34763514
return;

lib/DxilValidation/DxilValidation.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,15 @@ std::string GetLaunchTypeStr(DXIL::NodeLaunchType LT) {
16281628
}
16291629
}
16301630

1631+
static unsigned getSemanticFlagValidMask(const ShaderModel *pSM) {
1632+
unsigned DxilMajor, DxilMinor;
1633+
pSM->GetDxilVersion(DxilMajor, DxilMinor);
1634+
// DXIL version >= 1.9
1635+
if (hlsl::DXIL::CompareVersions(DxilMajor, DxilMinor, 1, 9) < 0)
1636+
return static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::LegacyFlags);
1637+
return static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::ValidMask);
1638+
}
1639+
16311640
static void ValidateDxilOperationCallInProfile(CallInst *CI,
16321641
DXIL::OpCode Opcode,
16331642
const ShaderModel *pSM,
@@ -1838,8 +1847,8 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
18381847
(unsigned)hlsl::DXIL::MemoryTypeFlag::ValidMask,
18391848
"memory type", "BarrierByMemoryType");
18401849
ValidateBarrierFlagArg(ValCtx, CI, DI.get_SemanticFlags(),
1841-
(unsigned)hlsl::DXIL::BarrierSemanticFlag::ValidMask,
1842-
"semantic", "BarrierByMemoryType");
1850+
getSemanticFlagValidMask(pSM), "semantic",
1851+
"BarrierByMemoryType");
18431852
if (!IsLibFunc && ShaderKind != DXIL::ShaderKind::Node &&
18441853
OP::BarrierRequiresNode(CI)) {
18451854
ValCtx.EmitInstrError(CI, ValidationRule::InstrBarrierRequiresNode);
@@ -1855,8 +1864,7 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
18551864
: "barrierByMemoryHandle";
18561865
DxilInst_BarrierByMemoryHandle DIMH(CI);
18571866
ValidateBarrierFlagArg(ValCtx, CI, DIMH.get_SemanticFlags(),
1858-
(unsigned)hlsl::DXIL::BarrierSemanticFlag::ValidMask,
1859-
"semantic", OpName);
1867+
getSemanticFlagValidMask(pSM), "semantic", OpName);
18601868
if (!IsLibFunc && ShaderKind != DXIL::ShaderKind::Node &&
18611869
OP::BarrierRequiresNode(CI)) {
18621870
ValCtx.EmitInstrError(CI, ValidationRule::InstrBarrierRequiresNode);

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -7986,7 +7986,7 @@ def err_hlsl_barrier_invalid_memory_flags: Error<
79867986
"UAV_MEMORY, GROUP_SHARED_MEMORY, NODE_INPUT_MEMORY, NODE_OUTPUT_MEMORY flags">;
79877987
def err_hlsl_barrier_invalid_semantic_flags: Error<
79887988
"invalid SemanticFlags for Barrier operation; expected 0 or some combination of "
7989-
"GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE flags">;
7989+
"GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE%select{|, REORDER_SCOPE}0 flags">;
79907990
def warn_hlsl_barrier_group_memory_requires_group: Warning<
79917991
"GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group">,
79927992
InGroup<HLSLBarrier>, DefaultError;

tools/clang/lib/AST/ASTContextHLSL.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,8 @@ void hlsl::AddSamplerFeedbackConstants(ASTContext &context) {
718718

719719
/// <summary> Adds all enums for Barrier intrinsic</summary>
720720
void hlsl::AddBarrierConstants(ASTContext &context) {
721+
VersionTuple VT69 = VersionTuple(6, 9);
722+
721723
AddTypedefPseudoEnum(
722724
context, "MEMORY_TYPE_FLAG",
723725
{{"UAV_MEMORY", (unsigned)DXIL::MemoryTypeFlag::UavMemory},
@@ -730,7 +732,9 @@ void hlsl::AddBarrierConstants(ASTContext &context) {
730732
context, "BARRIER_SEMANTIC_FLAG",
731733
{{"GROUP_SYNC", (unsigned)DXIL::BarrierSemanticFlag::GroupSync},
732734
{"GROUP_SCOPE", (unsigned)DXIL::BarrierSemanticFlag::GroupScope},
733-
{"DEVICE_SCOPE", (unsigned)DXIL::BarrierSemanticFlag::DeviceScope}});
735+
{"DEVICE_SCOPE", (unsigned)DXIL::BarrierSemanticFlag::DeviceScope},
736+
{"REORDER_SCOPE", (unsigned)DXIL::BarrierSemanticFlag::ReorderScope,
737+
ConstructAvailabilityAttribute(context, VT69)}});
734738
}
735739

736740
static Expr *IntConstantAsBoolExpr(clang::Sema &sema, uint64_t value) {

tools/clang/lib/Sema/SemaHLSL.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -11576,7 +11576,8 @@ static bool CheckFinishedCrossGroupSharingCall(Sema &S, CXXMethodDecl *MD,
1157611576
return false;
1157711577
}
1157811578

11579-
static bool CheckBarrierCall(Sema &S, FunctionDecl *FD, CallExpr *CE) {
11579+
static bool CheckBarrierCall(Sema &S, FunctionDecl *FD, CallExpr *CE,
11580+
const hlsl::ShaderModel *SM) {
1158011581
DXASSERT(FD->getNumParams() == 2, "otherwise, unknown Barrier overload");
1158111582

1158211583
// Emit error when MemoryTypeFlags are known to be invalid.
@@ -11606,12 +11607,18 @@ static bool CheckBarrierCall(Sema &S, FunctionDecl *FD, CallExpr *CE) {
1160611607
llvm::APSInt SemanticFlagsVal;
1160711608
if (SemanticFlagsExpr->isIntegerConstantExpr(SemanticFlagsVal, S.Context)) {
1160811609
SemanticFlags = SemanticFlagsVal.getLimitedValue();
11609-
if ((uint32_t)SemanticFlags &
11610-
~(uint32_t)DXIL::BarrierSemanticFlag::ValidMask) {
11610+
uint32_t ValidMask = 0U;
11611+
if (SM->IsSM69Plus()) {
11612+
ValidMask =
11613+
static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::ValidMask);
11614+
} else {
11615+
ValidMask =
11616+
static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::LegacyFlags);
11617+
}
11618+
if ((uint32_t)SemanticFlags & ~ValidMask) {
1161111619
S.Diags.Report(SemanticFlagsExpr->getExprLoc(),
1161211620
diag::err_hlsl_barrier_invalid_semantic_flags)
11613-
<< (uint32_t)SemanticFlags
11614-
<< (uint32_t)DXIL::BarrierSemanticFlag::ValidMask;
11621+
<< SM->IsSM69Plus();
1161511622
return true;
1161611623
}
1161711624
}
@@ -11654,14 +11661,17 @@ void Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
1165411661
if (!IsBuiltinTable(IntrinsicAttr->getGroup()))
1165511662
return;
1165611663

11664+
const auto *SM =
11665+
hlsl::ShaderModel::GetByName(getLangOpts().HLSLProfile.c_str());
11666+
1165711667
hlsl::IntrinsicOp opCode = (hlsl::IntrinsicOp)IntrinsicAttr->getOpcode();
1165811668
switch (opCode) {
1165911669
case hlsl::IntrinsicOp::MOP_FinishedCrossGroupSharing:
1166011670
CheckFinishedCrossGroupSharingCall(*this, cast<CXXMethodDecl>(FDecl),
1166111671
TheCall->getLocStart());
1166211672
break;
1166311673
case hlsl::IntrinsicOp::IOP_Barrier:
11664-
CheckBarrierCall(*this, FDecl, TheCall);
11674+
CheckBarrierCall(*this, FDecl, TheCall, SM);
1166511675
break;
1166611676
#ifdef ENABLE_SPIRV_CODEGEN
1166711677
case hlsl::IntrinsicOp::IOP_Vkreinterpret_pointer_cast:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %dxilver 1.9 | %dxc -T lib_6_9 %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
2+
3+
// Check that stage flags are set correctly still for different barrier modes in SM 6.9.
4+
5+
// RDAT: FunctionTable[{{.*}}] = {
6+
7+
RWByteAddressBuffer BAB : register(u1, space0);
8+
9+
// RDAT-LABEL: UnmangledName: "fn_barrier_reorder"
10+
// RDAT: FeatureInfo1: 0
11+
// RDAT: FeatureInfo2: 0
12+
// RDAT: ShaderStageFlag: (Library | RayGeneration)
13+
// RDAT: MinShaderTarget: 0x60069
14+
15+
[noinline] export
16+
void fn_barrier_reorder() {
17+
Barrier(UAV_MEMORY, REORDER_SCOPE);
18+
}
19+
20+
// RDAT-LABEL: UnmangledName: "fn_barrier_reorder2"
21+
// RDAT: FeatureInfo1: 0
22+
// RDAT: FeatureInfo2: 0
23+
// RDAT: ShaderStageFlag: (Library | RayGeneration)
24+
// RDAT: MinShaderTarget: 0x60069
25+
26+
[noinline] export
27+
void fn_barrier_reorder2() {
28+
Barrier(BAB, REORDER_SCOPE);
29+
}
30+
31+
// RDAT-LABEL: UnmangledName: "rg_barrier_reorder_in_call"
32+
// RDAT: FeatureInfo1: 0
33+
// RDAT: FeatureInfo2: 0
34+
// RDAT: ShaderStageFlag: (RayGeneration)
35+
// RDAT: MinShaderTarget: 0x70069
36+
37+
[shader("raygeneration")]
38+
void rg_barrier_reorder_in_call() {
39+
fn_barrier_reorder();
40+
BAB.Store(0, 0);
41+
}
42+
43+
// RDAT-LABEL: UnmangledName: "rg_barrier_reorder_in_call2"
44+
// RDAT: FeatureInfo1: 0
45+
// RDAT: FeatureInfo2: 0
46+
// RDAT: ShaderStageFlag: (RayGeneration)
47+
// RDAT: MinShaderTarget: 0x70069
48+
49+
[shader("raygeneration")]
50+
void rg_barrier_reorder_in_call2() {
51+
fn_barrier_reorder2();
52+
BAB.Store(0, 0);
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
; RUN: %dxilver 1.9 | %dxv %s
2+
3+
; Buffer Definitions:
4+
;
5+
;
6+
; Resource Bindings:
7+
;
8+
; Name Type Format Dim ID HLSL Bind Count
9+
; ------------------------------ ---------- ------- ----------- ------- -------------- ------
10+
; BAB UAV byte r/w U0 u1 1
11+
;
12+
target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
13+
target triple = "dxil-ms-dx"
14+
15+
%dx.types.Handle = type { i8* }
16+
%dx.types.ResourceProperties = type { i32, i32 }
17+
%struct.RWByteAddressBuffer = type { i32 }
18+
19+
@"\01?BAB@@3URWByteAddressBuffer@@A" = external constant %dx.types.Handle, align 4
20+
21+
; Function Attrs: nounwind
22+
define void @"\01?main@@YAXXZ"() #0 {
23+
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?BAB@@3URWByteAddressBuffer@@A", align 4
24+
call void @dx.op.barrierByMemoryType(i32 244, i32 1, i32 8) ; BarrierByMemoryType(MemoryTypeFlags,SemanticFlags)
25+
%2 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
26+
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 4107, i32 0 }) ; AnnotateHandle(res,props) resource: RWByteAddressBuffer
27+
call void @dx.op.barrierByMemoryHandle(i32 245, %dx.types.Handle %3, i32 8) ; BarrierByMemoryHandle(object,SemanticFlags)
28+
ret void
29+
}
30+
31+
; Function Attrs: noduplicate nounwind
32+
declare void @dx.op.barrierByMemoryType(i32, i32, i32) #1
33+
34+
; Function Attrs: noduplicate nounwind
35+
declare void @dx.op.barrierByMemoryHandle(i32, %dx.types.Handle, i32) #1
36+
37+
; Function Attrs: nounwind readnone
38+
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #2
39+
40+
; Function Attrs: nounwind readonly
41+
declare %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32, %dx.types.Handle) #3
42+
43+
attributes #0 = { nounwind }
44+
attributes #1 = { noduplicate nounwind }
45+
attributes #2 = { nounwind readnone }
46+
attributes #3 = { nounwind readonly }
47+
48+
!dx.version = !{!0}
49+
!dx.valver = !{!0}
50+
!dx.shaderModel = !{!1}
51+
!dx.resources = !{!2}
52+
!dx.typeAnnotations = !{!5}
53+
!dx.entryPoints = !{!9, !11}
54+
55+
!0 = !{i32 1, i32 9}
56+
!1 = !{!"lib", i32 6, i32 9}
57+
!2 = !{null, !3, null, null}
58+
!3 = !{!4}
59+
!4 = !{i32 0, %struct.RWByteAddressBuffer* bitcast (%dx.types.Handle* @"\01?BAB@@3URWByteAddressBuffer@@A" to %struct.RWByteAddressBuffer*), !"BAB", i32 0, i32 1, i32 1, i32 11, i1 false, i1 false, i1 false, null}
60+
!5 = !{i32 1, void ()* @"\01?main@@YAXXZ", !6}
61+
!6 = !{!7}
62+
!7 = !{i32 1, !8, !8}
63+
!8 = !{}
64+
!9 = !{null, !"", null, !2, !10}
65+
!10 = !{i32 0, i64 8589934608}
66+
!11 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !12}
67+
!12 = !{i32 8, i32 7, i32 5, !13}
68+
!13 = !{i32 0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %dxc -Tlib_6_8 -verify %s
2+
3+
[Shader("compute")]
4+
[numthreads(1, 1, 1)]
5+
void main() {
6+
// expected-error@+1{{invalid SemanticFlags for Barrier operation; expected 0 or some combination of GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE flags}}
7+
Barrier(0, REORDER_SCOPE);
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s
2+
3+
RWByteAddressBuffer BAB : register(u1, space0);
4+
5+
[shader("raygeneration")]
6+
void main() {
7+
// CHECK: call void @dx.op.barrierByMemoryType(i32 244, i32 1, i32 8)
8+
Barrier(UAV_MEMORY, REORDER_SCOPE);
9+
10+
// CHECK: call void @dx.op.barrierByMemoryHandle(i32 245, %dx.types.Handle %{{[^ ]+}}, i32 8)
11+
Barrier(BAB, REORDER_SCOPE);
12+
}

0 commit comments

Comments
 (0)