Add barrier MemoryTypeFlags and SemanticFlags diagnostics (#6513)

Context-specific diagnostics are warnings with DefaultError, since in
theory they could be dead code at this stage.

There were some changes to existing Sema diagnostic hooks along the way.

SemaHLSLDiagnoseTU.cpp - HLSLMethodCallDiagnoseVisitor
- extend to non-method calls and pass CallExpr
- instead of skipping when call reached from multiple entry/export
functions, pass locallyVisited flag for skipping of redundant diags not
dependent on entry properties.
- use llvm::SmallPtrSet for DiagnosticCalls
- capture launch type for entry and pass it down

Replace DiagnoseHLSLMethodCall hook with CheckHLSLFunctionCall:

Move hook into Sema::CheckFunctionCall in SemaChecking.cpp to be general
to either a function call or a method call.
Refactor existing code in DiagnoseHLSLMethodCall into
CheckFinishedCrossGroupSharingCall called in the hook for this method.
Add CheckBarrierCall for context-free flag validity check, called by
CheckHLSLFunctionCall.

Refactor CalculateLOD checking into more generic parts, dispatched based
on IntrinsicOp from top-level DiagnoseReachableHLSLCall function.

Switch to using new note: "entry function defined here", instead of
"declared here".

Fix intrinsic checking to use IsBuiltinTable on the intrinsic
attribute's group.

**Preparation Changes**
While these could be broken out, the barrier diagnostic changes are
dependent on them, and testing for some of these is dependent on the
other parts of the barrier diagnostic changes.

Correct errors in tests, check MaxRecords for EmptyNodeOutput in AST
Note that Barrier(..., 3) means SemanticFlags: GroupSync | GroupScope.
These are only valid in a shader with a visible group, and GroupSync on
memory with at least group scope, so they have been changed to 0 in
specific cases in these tests.

Make DiagnoseSVForLaunchType a static function, add FIXME notes.

Use StringRef for IsBuiltinTable, compare strings instead of pointers.

Fix FileCheckerTest for -verify output.

New ShaderModel::HasVisibleGroup uses ShaderKind and NodeLaunchType to
determine whether shader type has a visible group.
This commit is contained in:
Tex Riddell 2024-04-10 14:44:37 -07:00 коммит произвёл GitHub
Родитель fa39b3984f
Коммит fe393e09d7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
20 изменённых файлов: 1116 добавлений и 165 удалений

Просмотреть файл

@ -90,6 +90,18 @@ public:
static const char *GetNodeLaunchTypeName(DXIL::NodeLaunchType launchTy);
static DXIL::NodeLaunchType NodeLaunchTypeFromName(llvm::StringRef name);
static bool HasVisibleGroup(
DXIL::ShaderKind SK,
DXIL::NodeLaunchType launchType = DXIL::NodeLaunchType::Invalid) {
// Note: Library case is permissive; enforced at entry point.
return SK == DXIL::ShaderKind::Compute || SK == DXIL::ShaderKind::Mesh ||
SK == DXIL::ShaderKind::Amplification ||
SK == DXIL::ShaderKind::Library ||
(SK == DXIL::ShaderKind::Node &&
(launchType == DXIL::NodeLaunchType::Broadcasting ||
launchType == DXIL::NodeLaunchType::Coalescing));
}
bool operator==(const ShaderModel &other) const;
bool operator!=(const ShaderModel &other) const { return !(*this == other); }

Просмотреть файл

@ -802,4 +802,5 @@ def HLSLSemanticIdentifierCollision : DiagGroup<"semantic-identifier-collision">
def HLSLStructurizeExitsLifetimeMarkersConflict: DiagGroup<"structurize-exits-lifetime-markers-conflict">;
def HLSLParameterUsage : DiagGroup<"parameter-usage">;
def HLSLAvailability: DiagGroup<"hlsl-availability">;
def HLSLBarrier : DiagGroup<"hlsl-barrier">;
// HLSL Change Ends

Просмотреть файл

@ -20,6 +20,9 @@ def note_callee_decl : Note<"%0 declared here">;
def note_defined_here : Note<"%0 defined here">;
def note_field_declared_here : Note<"%0 field declared here">;
// HLSL Change: Note for HLSL entry function location
def note_hlsl_entry_defined_here : Note<"entry function defined here">;
// For loop analysis
def warn_variables_not_in_loop_body : Warning<
"variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 "
@ -7922,6 +7925,27 @@ def err_hlsl_outputpatch_size: Error<
def note_hlsl_node_array : Note<"'%0' cannot be used as an array; did you mean '%0Array'?">;
def err_hlsl_controlpoints_size: Error<
"number of control points %0 is outside the valid range of [1..32]">;
def err_hlsl_barrier_invalid_memory_flags: Error<
"invalid MemoryTypeFlags for Barrier operation; expected 0, ALL_MEMORY, or some combination of "
"UAV_MEMORY, GROUP_SHARED_MEMORY, NODE_INPUT_MEMORY, NODE_OUTPUT_MEMORY flags">;
def err_hlsl_barrier_invalid_semantic_flags: Error<
"invalid SemanticFlags for Barrier operation; expected 0 or some combination of "
"GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE flags">;
def warn_hlsl_barrier_group_memory_requires_group: Warning<
"GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group">,
InGroup<HLSLBarrier>, DefaultError;
def warn_hlsl_barrier_node_memory_requires_node: Warning<
"NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader">,
InGroup<HLSLBarrier>, DefaultError;
def warn_hlsl_barrier_group_semantic_requires_group: Warning<
"GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group">,
InGroup<HLSLBarrier>, DefaultError;
def warn_hlsl_barrier_no_mem_with_required_group_scope: Warning<
"GROUP_SCOPE specified for Barrier operation without applicable memory">,
InGroup<HLSLBarrier>, DefaultError;
def warn_hlsl_barrier_no_mem_with_required_device_scope: Warning<
"DEVICE_SCOPE specified for Barrier operation without applicable memory">,
InGroup<HLSLBarrier>, DefaultError;
// HLSL Change Ends
// SPIRV Change Starts

Просмотреть файл

@ -3807,14 +3807,13 @@ public:
void DiagnoseGloballyCoherentMismatch(const Expr *SrcExpr,
QualType TargetType,
SourceLocation Loc);
bool DiagnoseHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc);
void DiagnoseSVForLaunchType(const FunctionDecl *FD,
hlsl::DXIL::NodeLaunchType LaunchTy);
void DiagnoseReachableHLSLMethodCall(const CXXMethodDecl *MD,
SourceLocation Loc,
const hlsl::ShaderModel *SM,
hlsl::DXIL::ShaderKind EntrySK,
const FunctionDecl *EntryDecl);
void CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
const FunctionProtoType *Proto);
void DiagnoseReachableHLSLCall(CallExpr *CE, const hlsl::ShaderModel *SM,
hlsl::DXIL::ShaderKind EntrySK,
hlsl::DXIL::NodeLaunchType NodeLaunchTy,
const FunctionDecl *EntryDecl,
bool locallyVisited);
// HLSL Change Ends
bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);

Просмотреть файл

@ -1426,6 +1426,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
CheckMemaccessArguments(TheCall, CMId, FnInfo);
#endif // HLSL Change Ends
CheckHLSLFunctionCall(FDecl, TheCall, Proto); // HLSL Change
return false;
}

Просмотреть файл

@ -1853,8 +1853,8 @@ static void InitParamMods(const HLSL_INTRINSIC *pIntrinsic,
}
}
static bool IsBuiltinTable(LPCSTR tableName) {
return tableName == kBuiltinIntrinsicTableName;
static bool IsBuiltinTable(StringRef tableName) {
return tableName.compare(kBuiltinIntrinsicTableName) == 0;
}
static bool HasUnsignedOpcode(LPCSTR tableName, IntrinsicOp opcode) {
@ -11117,37 +11117,18 @@ void hlsl::DiagnoseRegisterType(clang::Sema *self, clang::SourceLocation loc,
}
}
// Check HLSL member call constraints
bool Sema::DiagnoseHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc) {
if (MD->hasAttr<HLSLIntrinsicAttr>()) {
hlsl::IntrinsicOp opCode =
(IntrinsicOp)MD->getAttr<HLSLIntrinsicAttr>()->getOpcode();
// If this is a call to FinishedCrossGroupSharing then the Input record
// must have the NodeTrackRWInputSharing attribute
if (opCode == hlsl::IntrinsicOp::MOP_FinishedCrossGroupSharing) {
const CXXRecordDecl *NodeRecDecl = MD->getParent();
// Node I/O records are templateTypes
const ClassTemplateSpecializationDecl *templateDecl =
cast<ClassTemplateSpecializationDecl>(NodeRecDecl);
auto &TemplateArgs = templateDecl->getTemplateArgs();
DXASSERT(TemplateArgs.size() == 1,
"Input record types need to have one template argument");
auto &Rec = TemplateArgs.get(0);
clang::QualType RecType = Rec.getAsType();
RecordDecl *RD = RecType->getAs<RecordType>()->getDecl();
if (!RD->hasAttr<HLSLNodeTrackRWInputSharingAttr>()) {
Diags.Report(Loc, diag::err_hlsl_wg_nodetrackrwinputsharing_missing);
return true;
}
}
}
return false;
}
// FIXME: DiagnoseSVForLaunchType is wrong in multiple ways:
// - It doesn't handle system values inside structs
// - It doesn't account for the fact that semantics are case-insensitive
// - It doesn't account for optional index at the end of semantic name
// - It permits any `SV_*` for Broadcasting launch, not just the legal ones
// - It doesn't prevent multiple system values with the same semantic
// - It doesn't check that the type is valid for the system value
// Produce diagnostics for any system values attached to `FD` function
// that are invalid for the `LaunchTy` launch type
void Sema::DiagnoseSVForLaunchType(const FunctionDecl *FD,
DXIL::NodeLaunchType LaunchTy) {
static void DiagnoseSVForLaunchType(const FunctionDecl *FD,
DXIL::NodeLaunchType LaunchTy,
DiagnosticsEngine &Diags) {
// Validate Compute Shader system value inputs per launch mode
for (ParmVarDecl *param : FD->parameters()) {
for (const hlsl::UnusualAnnotation *it : param->getUnusualAnnotations()) {
@ -11188,88 +11169,376 @@ void Sema::DiagnoseSVForLaunchType(const FunctionDecl *FD,
}
}
// Check HLSL member call constraints for used functions.
void Sema::DiagnoseReachableHLSLMethodCall(const CXXMethodDecl *MD,
SourceLocation Loc,
const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK,
const FunctionDecl *EntryDecl) {
if (MD->hasAttr<HLSLIntrinsicAttr>()) {
hlsl::IntrinsicOp opCode =
(IntrinsicOp)MD->getAttr<HLSLIntrinsicAttr>()->getOpcode();
switch (opCode) {
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetail:
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped: {
QualType SamplerComparisonTy =
HLSLExternalSource::FromSema(this)->GetBasicKindType(
AR_OBJECT_SAMPLERCOMPARISON);
if (MD->getParamDecl(0)->getType() == SamplerComparisonTy) {
/////////////////////////////////////////////////////////////////////////////
// Check HLSL intrinsic calls without call-graph context.
if (!SM->IsSM68Plus()) {
static bool CheckFinishedCrossGroupSharingCall(Sema &S, CXXMethodDecl *MD,
SourceLocation Loc) {
const CXXRecordDecl *NodeRecDecl = MD->getParent();
// Node I/O records are templateTypes
const ClassTemplateSpecializationDecl *templateDecl =
cast<ClassTemplateSpecializationDecl>(NodeRecDecl);
auto &TemplateArgs = templateDecl->getTemplateArgs();
DXASSERT(TemplateArgs.size() == 1,
"Input record types need to have one template argument");
auto &Rec = TemplateArgs.get(0);
clang::QualType RecType = Rec.getAsType();
RecordDecl *RD = RecType->getAs<RecordType>()->getDecl();
if (!RD->hasAttr<HLSLNodeTrackRWInputSharingAttr>()) {
S.Diags.Report(Loc, diag::err_hlsl_wg_nodetrackrwinputsharing_missing);
return true;
}
return false;
}
Diags.Report(Loc,
diag::warn_hlsl_intrinsic_overload_in_wrong_shader_model)
<< MD->getNameAsString() + " with SamplerComparisonState"
<< "6.8";
} else {
static bool CheckBarrierCall(Sema &S, FunctionDecl *FD, CallExpr *CE) {
DXASSERT(FD->getNumParams() == 2, "otherwise, unknown Barrier overload");
switch (EntrySK) {
default: {
if (!SM->AllowDerivatives(EntrySK)) {
Diags.Report(Loc,
diag::warn_hlsl_derivatives_in_wrong_shader_kind)
<< MD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(), diag::note_declared_at);
}
} break;
case DXIL::ShaderKind::Compute:
case DXIL::ShaderKind::Amplification:
case DXIL::ShaderKind::Mesh: {
if (!SM->IsSM66Plus()) {
Diags.Report(Loc,
diag::warn_hlsl_derivatives_in_wrong_shader_model)
<< MD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(), diag::note_declared_at);
}
} break;
case DXIL::ShaderKind::Node: {
if (const auto *pAttr = EntryDecl->getAttr<HLSLNodeLaunchAttr>()) {
if (pAttr->getLaunchType() != "broadcasting") {
Diags.Report(Loc,
diag::warn_hlsl_derivatives_in_wrong_shader_kind)
<< MD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(), diag::note_declared_at);
}
}
} break;
}
if (const HLSLNumThreadsAttr *Attr =
EntryDecl->getAttr<HLSLNumThreadsAttr>()) {
bool invalidNumThreads = false;
if (Attr->getY() != 1) {
// 2D mode requires x and y to be multiple of 2.
invalidNumThreads =
!((Attr->getX() % 2) == 0 && (Attr->getY() % 2) == 0);
} else {
// 1D mode requires x to be multiple of 4 and y and z to be 1.
invalidNumThreads =
(Attr->getX() % 4) != 0 || (Attr->getZ() != 1);
}
if (invalidNumThreads) {
Diags.Report(Loc, diag::warn_hlsl_derivatives_wrong_numthreads)
<< MD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(), diag::note_declared_at);
}
}
}
// Emit error when MemoryTypeFlags are known to be invalid.
QualType Param0Ty = FD->getParamDecl(0)->getType();
if (Param0Ty ==
HLSLExternalSource::FromSema(&S)->GetBasicKindType(AR_BASIC_UINT32)) {
uint32_t MemoryTypeFlags = 0;
Expr *MemoryTypeFlagsExpr = CE->getArg(0);
llvm::APSInt MemoryTypeFlagsVal;
if (MemoryTypeFlagsExpr->isIntegerConstantExpr(MemoryTypeFlagsVal,
S.Context)) {
MemoryTypeFlags = MemoryTypeFlagsVal.getLimitedValue();
if ((uint32_t)MemoryTypeFlags &
~(uint32_t)DXIL::MemoryTypeFlag::ValidMask) {
S.Diags.Report(MemoryTypeFlagsExpr->getExprLoc(),
diag::err_hlsl_barrier_invalid_memory_flags)
<< (uint32_t)MemoryTypeFlags
<< (uint32_t)DXIL::MemoryTypeFlag::ValidMask;
return true;
}
} break;
default:
break;
}
}
// Emit error when SemanticFlags are known to be invalid.
uint32_t SemanticFlags = 0;
Expr *SemanticFlagsExpr = CE->getArg(1);
llvm::APSInt SemanticFlagsVal;
if (SemanticFlagsExpr->isIntegerConstantExpr(SemanticFlagsVal, S.Context)) {
SemanticFlags = SemanticFlagsVal.getLimitedValue();
if ((uint32_t)SemanticFlags &
~(uint32_t)DXIL::BarrierSemanticFlag::ValidMask) {
S.Diags.Report(SemanticFlagsExpr->getExprLoc(),
diag::err_hlsl_barrier_invalid_semantic_flags)
<< (uint32_t)SemanticFlags
<< (uint32_t)DXIL::BarrierSemanticFlag::ValidMask;
return true;
}
}
return false;
}
// Check HLSL call constraints, not fatal to creating the AST.
void Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
const FunctionProtoType *Proto) {
HLSLIntrinsicAttr *IntrinsicAttr = FDecl->getAttr<HLSLIntrinsicAttr>();
if (!IntrinsicAttr)
return;
if (!IsBuiltinTable(IntrinsicAttr->getGroup()))
return;
hlsl::IntrinsicOp opCode = (hlsl::IntrinsicOp)IntrinsicAttr->getOpcode();
switch (opCode) {
case hlsl::IntrinsicOp::MOP_FinishedCrossGroupSharing:
CheckFinishedCrossGroupSharingCall(*this, cast<CXXMethodDecl>(FDecl),
TheCall->getLocStart());
break;
case hlsl::IntrinsicOp::IOP_Barrier:
CheckBarrierCall(*this, FDecl, TheCall);
break;
default:
break;
}
}
/////////////////////////////////////////////////////////////////////////////
// Check HLSL intrinsic calls reachable from entry/export functions.
static void DiagnoseNumThreadsForDerivativeOp(const HLSLNumThreadsAttr *Attr,
SourceLocation LocDeriv,
FunctionDecl *FD,
const FunctionDecl *EntryDecl,
DiagnosticsEngine &Diags) {
bool invalidNumThreads = false;
if (Attr->getY() != 1) {
// 2D mode requires x and y to be multiple of 2.
invalidNumThreads = !((Attr->getX() % 2) == 0 && (Attr->getY() % 2) == 0);
} else {
// 1D mode requires x to be multiple of 4 and y and z to be 1.
invalidNumThreads = (Attr->getX() % 4) != 0 || (Attr->getZ() != 1);
}
if (invalidNumThreads) {
Diags.Report(LocDeriv, diag::warn_hlsl_derivatives_wrong_numthreads)
<< FD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(), diag::note_hlsl_entry_defined_here);
}
}
static void DiagnoseDerivativeOp(Sema &S, FunctionDecl *FD, SourceLocation Loc,
const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK,
DXIL::NodeLaunchType NodeLaunchTy,
const FunctionDecl *EntryDecl,
DiagnosticsEngine &Diags) {
switch (EntrySK) {
default: {
if (!SM->AllowDerivatives(EntrySK)) {
Diags.Report(Loc, diag::warn_hlsl_derivatives_in_wrong_shader_kind)
<< FD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
} break;
case DXIL::ShaderKind::Compute:
case DXIL::ShaderKind::Amplification:
case DXIL::ShaderKind::Mesh: {
if (!SM->IsSM66Plus()) {
Diags.Report(Loc, diag::warn_hlsl_derivatives_in_wrong_shader_model)
<< FD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
} break;
case DXIL::ShaderKind::Node: {
if (NodeLaunchTy != DXIL::NodeLaunchType::Broadcasting) {
Diags.Report(Loc, diag::warn_hlsl_derivatives_in_wrong_shader_kind)
<< FD->getNameAsString() << EntryDecl->getNameAsString();
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
} break;
}
if (const HLSLNumThreadsAttr *Attr =
EntryDecl->getAttr<HLSLNumThreadsAttr>()) {
DiagnoseNumThreadsForDerivativeOp(Attr, Loc, FD, EntryDecl, Diags);
}
}
static void DiagnoseCalculateLOD(Sema &S, FunctionDecl *FD, SourceLocation Loc,
const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK,
DXIL::NodeLaunchType NodeLaunchTy,
const FunctionDecl *EntryDecl,
DiagnosticsEngine &Diags,
bool locallyVisited) {
if (FD->getParamDecl(0)->getType() !=
HLSLExternalSource::FromSema(&S)->GetBasicKindType(
AR_OBJECT_SAMPLERCOMPARISON))
return;
if (!locallyVisited && !SM->IsSM68Plus()) {
Diags.Report(Loc, diag::warn_hlsl_intrinsic_overload_in_wrong_shader_model)
<< FD->getNameAsString() + " with SamplerComparisonState"
<< "6.8";
return;
}
DiagnoseDerivativeOp(S, FD, Loc, SM, EntrySK, NodeLaunchTy, EntryDecl, Diags);
}
static uint32_t
DiagnoseMemoryFlags(SourceLocation ArgLoc, uint32_t MemoryTypeFlags,
bool hasVisibleGroup, DXIL::ShaderKind EntrySK,
const FunctionDecl *EntryDecl, DiagnosticsEngine &Diags) {
// Check flags against context.
// If DXIL::MemoryTypeFlag::AllMemory, filter flags for context, otherwise,
// emit errors for invalid flags.
uint32_t MemoryTypeFiltered = MemoryTypeFlags;
// If group memory specified, must have a visible group.
if (!hasVisibleGroup) {
if ((uint32_t)MemoryTypeFlags &
(uint32_t)DXIL::MemoryTypeFlag::GroupFlags) {
if (MemoryTypeFlags == (uint32_t)DXIL::MemoryTypeFlag::AllMemory) {
// If AllMemory, filter out group flags.
MemoryTypeFiltered &= ~(uint32_t)DXIL::MemoryTypeFlag::GroupFlags;
} else {
Diags.Report(ArgLoc,
diag::warn_hlsl_barrier_group_memory_requires_group);
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
}
}
// If node memory specified, must be a node shader.
if (EntrySK != DXIL::ShaderKind::Node &&
EntrySK != DXIL::ShaderKind::Library &&
((uint32_t)MemoryTypeFlags & (uint32_t)DXIL::MemoryTypeFlag::NodeFlags)) {
if (MemoryTypeFlags == (uint32_t)DXIL::MemoryTypeFlag::AllMemory) {
// If AllMemory, filter out node flags.
MemoryTypeFiltered &= ~(uint32_t)DXIL::MemoryTypeFlag::NodeFlags;
} else {
Diags.Report(ArgLoc, diag::warn_hlsl_barrier_node_memory_requires_node);
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
}
// Return filtered flags.
return MemoryTypeFiltered;
}
static void DiagnoseSemanticFlags(SourceLocation ArgLoc, uint32_t SemanticFlags,
bool hasVisibleGroup,
bool memAtLeastGroupScope,
bool memAtLeastDeviceScope,
const FunctionDecl *EntryDecl,
DiagnosticsEngine &Diags) {
// If hasVisibleGroup is false, emit error for group flags.
if (!hasVisibleGroup) {
if ((uint32_t)SemanticFlags &
(uint32_t)DXIL::BarrierSemanticFlag::GroupFlags) {
Diags.Report(ArgLoc,
diag::warn_hlsl_barrier_group_semantic_requires_group);
Diags.Report(EntryDecl->getLocation(),
diag::note_hlsl_entry_defined_here);
}
}
// Error on DeviceScope or GroupScope when memory lacks this scope.
if (!memAtLeastDeviceScope &&
((uint32_t)SemanticFlags &
(uint32_t)DXIL::BarrierSemanticFlag::DeviceScope)) {
Diags.Report(ArgLoc,
diag::warn_hlsl_barrier_no_mem_with_required_device_scope);
Diags.Report(EntryDecl->getLocation(), diag::note_hlsl_entry_defined_here);
}
if (!memAtLeastGroupScope &&
((uint32_t)SemanticFlags &
(uint32_t)DXIL::BarrierSemanticFlag::GroupScope)) {
Diags.Report(ArgLoc,
diag::warn_hlsl_barrier_no_mem_with_required_group_scope);
Diags.Report(EntryDecl->getLocation(), diag::note_hlsl_entry_defined_here);
}
}
static void DiagnoseReachableBarrier(Sema &S, CallExpr *CE,
const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK,
DXIL::NodeLaunchType NodeLaunchTy,
const FunctionDecl *EntryDecl,
DiagnosticsEngine &Diags) {
FunctionDecl *FD = CE->getDirectCallee();
DXASSERT(FD->getNumParams() == 2, "otherwise, unknown Barrier overload");
// Does shader have visible group?
// Allow exported library functions as well.
bool hasVisibleGroup = ShaderModel::HasVisibleGroup(EntrySK, NodeLaunchTy);
QualType Param0Ty = FD->getParamDecl(0)->getType();
// Used when checking scope flags
// Default to true to avoid over-strict diagnostics
bool memAtLeastGroupScope = true;
bool memAtLeastDeviceScope = true;
if (Param0Ty ==
HLSLExternalSource::FromSema(&S)->GetBasicKindType(AR_BASIC_UINT32)) {
// overload: Barrier(uint MemoryTypeFlags, uint SemanticFlags)
uint32_t MemoryTypeFlags = 0;
Expr *MemoryTypeFlagsExpr = CE->getArg(0);
llvm::APSInt MemoryTypeFlagsVal;
if (MemoryTypeFlagsExpr->isIntegerConstantExpr(MemoryTypeFlagsVal,
S.Context)) {
MemoryTypeFlags = MemoryTypeFlagsVal.getLimitedValue();
MemoryTypeFlags = DiagnoseMemoryFlags(MemoryTypeFlagsExpr->getExprLoc(),
MemoryTypeFlags, hasVisibleGroup,
EntrySK, EntryDecl, Diags);
// Consider group scope if any group flags remain.
memAtLeastGroupScope = 0 != MemoryTypeFlags;
// Consider it device scope if UavMemory or any NodeFlags remain.
memAtLeastDeviceScope =
0 != (MemoryTypeFlags & ((uint32_t)DXIL::MemoryTypeFlag::UavMemory |
(uint32_t)DXIL::MemoryTypeFlag::NodeFlags));
}
} else {
DXIL::NodeIOKind IOKind = GetNodeIOType(Param0Ty);
if (IOKind == DXIL::NodeIOKind::Invalid) {
// overload: Barrier(<UAV Resource>, uint SemanticFlags)
// UAV objects have at least device scope.
DXASSERT(IsHLSLResourceType(Param0Ty),
"otherwise, missed a case for Barrier");
// mem scope flags already set to true.
} else {
// Must be a record object
// overload: Barrier(<node record object>, uint SemanticFlags)
// Only record objects specify a record granularity
DXASSERT((uint32_t)IOKind &
(uint32_t)DXIL::NodeIOFlags::RecordGranularityMask,
"otherwise, missed a Node object case for Barrier");
DXIL::NodeIOFlags RecordGranularity = (DXIL::NodeIOFlags)(
(uint32_t)IOKind &
(uint32_t)DXIL::NodeIOFlags::RecordGranularityMask);
switch (RecordGranularity) {
case DXIL::NodeIOFlags::ThreadRecord:
memAtLeastGroupScope = false;
LLVM_FALLTHROUGH;
case DXIL::NodeIOFlags::GroupRecord:
memAtLeastDeviceScope = false;
break;
default:
break;
}
}
}
// All barrier overloads have SemanticFlags as second paramter
uint32_t SemanticFlags = 0;
Expr *SemanticFlagsExpr = CE->getArg(1);
llvm::APSInt SemanticFlagsVal;
if (SemanticFlagsExpr->isIntegerConstantExpr(SemanticFlagsVal, S.Context)) {
SemanticFlags = SemanticFlagsVal.getLimitedValue();
DiagnoseSemanticFlags(SemanticFlagsExpr->getExprLoc(), SemanticFlags,
hasVisibleGroup, memAtLeastGroupScope,
memAtLeastDeviceScope, EntryDecl, Diags);
}
}
// Check HLSL member call constraints for used functions.
// locallyVisited is true if this call has been visited already from any other
// entry function. Used to avoid duplicate diagnostics when not dependent on
// entry function (or export function) properties.
void Sema::DiagnoseReachableHLSLCall(CallExpr *CE, const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK,
DXIL::NodeLaunchType NodeLaunchTy,
const FunctionDecl *EntryDecl,
bool locallyVisited) {
FunctionDecl *FD = CE->getDirectCallee();
if (!FD)
return;
HLSLIntrinsicAttr *IntrinsicAttr = FD->getAttr<HLSLIntrinsicAttr>();
if (!IntrinsicAttr)
return;
if (!IsBuiltinTable(IntrinsicAttr->getGroup()))
return;
SourceLocation Loc = CE->getExprLoc();
hlsl::IntrinsicOp opCode = (IntrinsicOp)IntrinsicAttr->getOpcode();
switch (opCode) {
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetail:
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped:
DiagnoseCalculateLOD(*this, FD, Loc, SM, EntrySK, NodeLaunchTy, EntryDecl,
Diags, locallyVisited);
break;
case hlsl::IntrinsicOp::IOP_Barrier:
DiagnoseReachableBarrier(*this, CE, SM, EntrySK, NodeLaunchTy, EntryDecl,
Diags);
break;
default:
break;
}
}
/////////////////////////////////////////////////////////////////////////////
bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc,
QualType ArgTy, bool &Empty,
const FieldDecl *FD) {
@ -15770,9 +16039,11 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
}
}
}
S.DiagnoseSVForLaunchType(FD, NodeLaunchTy);
}
}
DiagnoseSVForLaunchType(FD, NodeLaunchTy, S.Diags);
return;
}

Просмотреть файл

@ -302,24 +302,26 @@ clang::FunctionDecl *ValidateNoRecursion(CallGraphWithRecurseGuard &callGraph,
return nullptr;
}
class HLSLMethodCallDiagnoseVisitor
: public RecursiveASTVisitor<HLSLMethodCallDiagnoseVisitor> {
class HLSLCallDiagnoseVisitor
: public RecursiveASTVisitor<HLSLCallDiagnoseVisitor> {
public:
explicit HLSLMethodCallDiagnoseVisitor(
explicit HLSLCallDiagnoseVisitor(
Sema *S, const hlsl::ShaderModel *SM, DXIL::ShaderKind EntrySK,
const FunctionDecl *EntryDecl,
std::set<CXXMemberCallExpr *> &DiagnosedCalls)
: sema(S), SM(SM), EntrySK(EntrySK), EntryDecl(EntryDecl),
DiagnosedCalls(DiagnosedCalls) {}
DXIL::NodeLaunchType NodeLaunchTy, const FunctionDecl *EntryDecl,
llvm::SmallPtrSetImpl<CallExpr *> &DiagnosedCalls)
: sema(S), SM(SM), EntrySK(EntrySK), NodeLaunchTy(NodeLaunchTy),
EntryDecl(EntryDecl), DiagnosedCalls(DiagnosedCalls) {}
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
// Skip if already diagnosed.
if (DiagnosedCalls.count(CE))
return true;
DiagnosedCalls.insert(CE);
bool VisitCallExpr(CallExpr *CE) {
// Set flag if already diagnosed from another entry, allowing some
// diagnostics to be skipped when they are not dependent on entry
// properties.
bool locallyVisited = DiagnosedCalls.count(CE) != 0;
if (!locallyVisited)
DiagnosedCalls.insert(CE);
sema->DiagnoseReachableHLSLMethodCall(CE->getMethodDecl(), CE->getExprLoc(),
SM, EntrySK, EntryDecl);
sema->DiagnoseReachableHLSLCall(CE, SM, EntrySK, NodeLaunchTy, EntryDecl,
locallyVisited);
return true;
}
@ -329,8 +331,9 @@ private:
clang::Sema *sema;
const hlsl::ShaderModel *SM;
DXIL::ShaderKind EntrySK;
DXIL::NodeLaunchType NodeLaunchTy;
const FunctionDecl *EntryDecl;
std::set<CXXMemberCallExpr *> &DiagnosedCalls;
llvm::SmallPtrSetImpl<CallExpr *> &DiagnosedCalls;
};
std::optional<uint32_t>
@ -426,7 +429,7 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
hlsl::ShaderModel::GetByName(self->getLangOpts().HLSLProfile.c_str());
std::set<FunctionDecl *> DiagnosedDecls;
std::set<CXXMemberCallExpr *> DiagnosedCalls;
llvm::SmallPtrSet<CallExpr *, 16> DiagnosedCalls;
// for each FDecl, check for recursion
for (FunctionDecl *FDecl : FDeclsToCheck) {
CallGraphWithRecurseGuard callGraph;
@ -520,30 +523,23 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
}
DXIL::ShaderKind EntrySK = shaderModel->GetKind();
DXIL::NodeLaunchType NodeLaunchTy = DXIL::NodeLaunchType::Invalid;
if (EntrySK == DXIL::ShaderKind::Library) {
// For library, check if the exported function is entry with shader
// attribute.
if (const auto *Attr = FDecl->getAttr<clang::HLSLShaderAttr>())
EntrySK = ShaderModel::KindFromFullName(Attr->getStage());
if (EntrySK == DXIL::ShaderKind::Node)
if (const auto *pAttr = FDecl->getAttr<HLSLNodeLaunchAttr>())
NodeLaunchTy =
ShaderModel::NodeLaunchTypeFromName(pAttr->getLaunchType());
}
// Visit all visited functions in call graph to collect illegal intrinsic
// calls.
for (FunctionDecl *FD : callGraph.GetVisitedFunctions()) {
HLSLMethodCallDiagnoseVisitor Visitor(self, shaderModel, EntrySK, FDecl,
DiagnosedCalls);
HLSLCallDiagnoseVisitor Visitor(self, shaderModel, EntrySK, NodeLaunchTy,
FDecl, DiagnosedCalls);
Visitor.TraverseDecl(FD);
// diagnose any node functions that have incompatible launch types with
// the present SV semantics on each parameter.
if (EntrySK == DXIL::ShaderKind::Node) {
if (const auto *NodeLaunchAttr =
FDecl->getAttr<clang::HLSLNodeLaunchAttr>()) {
llvm::StringRef NodeLaunchTyStr = NodeLaunchAttr->getLaunchType();
hlsl::DXIL::NodeLaunchType NodeLaunchTy =
ShaderModel::NodeLaunchTypeFromName(NodeLaunchTyStr);
Visitor.getSema()->DiagnoseSVForLaunchType(FD, NodeLaunchTy);
}
}
}
}
}

Просмотреть файл

@ -11922,10 +11922,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (Method != FoundDecl.getDecl() &&
DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
return ExprError();
// HLSL Change Start - Check method constraints
if (DiagnoseHLSLMethodCall(Method, MemExprE->getLocStart()))
return ExprError();
// HLSL Change End
break;
case OR_No_Viable_Function:

Просмотреть файл

@ -63,14 +63,14 @@ void node04([MaxRecords(6)] RWGroupNodeInputRecords<RECORD> input)
void node05([MaxRecords(5)] NodeOutput<RECORD> outputs)
{
ThreadNodeOutputRecords<RECORD> outrec = outputs.GetThreadNodeOutputRecords(1);
Barrier(outrec, 3);
Barrier(outrec, 0);
}
// CHECK: define void @node05() {
// CHECK: [[NODE05_A:%[0-9]+]] = call %dx.types.NodeHandle @dx.op.createNodeOutputHandle(i32 {{[0-9]+}}, i32 0) ; CreateNodeOutputHandle(MetadataIdx)
// CHECK: [[ANN_NODE05_A:%[0-9]+]] = call %dx.types.NodeHandle @dx.op.annotateNodeHandle(i32 {{[0-9]+}}, %dx.types.NodeHandle [[NODE05_A]], %dx.types.NodeInfo { i32 6, i32 4 })
// CHECK: [[NODE05_B:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.allocateNodeOutputRecords(i32 {{[0-9]+}}, %dx.types.NodeHandle [[ANN_NODE05_A]], i32 1, i1 true) ; AllocateNodeOutputRecords(output,numRecords,perThread)
// CHECK: [[ANN_NODE05_B:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.annotateNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[NODE05_B]], %dx.types.NodeRecordInfo { i32 38, i32 4 })
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE05_B]], i32 3) ; BarrierByNodeRecordHandle(object,SemanticFlags)
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE05_B]], i32 0) ; BarrierByNodeRecordHandle(object,SemanticFlags)
[Shader("node")]
[NodeLaunch("thread")]

Просмотреть файл

@ -1,4 +1,5 @@
// RUN: %dxilver 1.8 | %dxc -T lib_6_8 -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
// RUN: %dxilver 1.8 | %dxc -T lib_6_8 -Wno-hlsl-barrier -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
// RUN: %dxilver 1.8 | %dxc -T lib_6_8 -verify %s
// Verifies that a Barrier requiring a visible group in a noinline function
// called by a vertex shader is correctly marked as requiring a group in RDAT.
@ -29,6 +30,8 @@ void write_value(uint value) {
[noinline] export
void barrier_group() {
write_value(1);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
write_value(2);
}
@ -54,6 +57,8 @@ void intermediate() {
// MinShaderTarget still indicates vertex shader.
// RDAT: MinShaderTarget: 0x10060
// expected-note@+3{{entry function defined here}}
// expected-note@+2{{entry function defined here}}
[shader("vertex")]
void main() {
intermediate();

Просмотреть файл

@ -0,0 +1,33 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// RUN: %dxc -Tcs_6_8 -verify %s
// REQUIRES: dxil-1-8
// Test the ordinary compute shader model case with node memory flags.
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Node barriers not supported in non-node shaders.
[noinline] export
void NodeBarriers() {
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_INPUT_MEMORY, 0);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_INPUT_MEMORY, DEVICE_SCOPE);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_OUTPUT_MEMORY, 0);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_OUTPUT_MEMORY, DEVICE_SCOPE);
}
// expected-note@+6{{entry function defined here}}
// expected-note@+5{{entry function defined here}}
// expected-note@+4{{entry function defined here}}
// expected-note@+3{{entry function defined here}}
[Shader("compute")]
[numthreads(1, 1, 1)]
void main() {
NodeBarriers();
}

Просмотреть файл

@ -0,0 +1,21 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// RUN: %dxc -Tcs_6_8 -verify %s
// REQUIRES: dxil-1-8
// Test the ordinary compute shader model case with local call-site errors.
// Since these errors are emitted before we do diagnostics for reachable calls,
// and because those diagnostics are skipped if an error is already produced,
// we must do these tests separately from the ones based on reachability.
[Shader("compute")]
[numthreads(1, 1, 1)]
void main() {
// expected-error@+1{{invalid MemoryTypeFlags for Barrier operation; expected 0, ALL_MEMORY, or some combination of UAV_MEMORY, GROUP_SHARED_MEMORY, NODE_INPUT_MEMORY, NODE_OUTPUT_MEMORY flags}}
Barrier(16, 0);
// expected-error@+1{{invalid MemoryTypeFlags for Barrier operation; expected 0, ALL_MEMORY, or some combination of UAV_MEMORY, GROUP_SHARED_MEMORY, NODE_INPUT_MEMORY, NODE_OUTPUT_MEMORY flags}}
Barrier(-1, 0);
// expected-error@+1{{invalid SemanticFlags for Barrier operation; expected 0 or some combination of GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE flags}}
Barrier(0, 8);
// expected-error@+1{{invalid SemanticFlags for Barrier operation; expected 0 or some combination of GROUP_SYNC, GROUP_SCOPE, DEVICE_SCOPE flags}}
Barrier(0, -1);
}

Просмотреть файл

@ -0,0 +1,62 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// RUN: %dxc -Tcs_6_8 -verify %s
// REQUIRES: dxil-1-8
// Test the compute shader model case with visible group.
// expected-no-diagnostics
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Barriers not requiring visible group, compatible with any shader stage.
[noinline] export
void DeviceBarriers() {
Barrier(0, 0);
Barrier(ALL_MEMORY, 0);
Barrier(ALL_MEMORY, DEVICE_SCOPE);
Barrier(ALL_MEMORY, 2 + 2);
Barrier(UAV_MEMORY, 0);
Barrier(UAV_MEMORY, DEVICE_SCOPE);
// No diagnostic for non-constant expressions.
Barrier(ALL_MEMORY, i + i);
Barrier(i + i, 0);
}
// Barriers requiring visible group.
[noinline] export
void GroupBarriers() {
Barrier(0, GROUP_SYNC);
Barrier(ALL_MEMORY, GROUP_SYNC);
Barrier(ALL_MEMORY, GROUP_SCOPE);
Barrier(ALL_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(ALL_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(ALL_MEMORY, 1 + 2 + 4);
Barrier(UAV_MEMORY, GROUP_SYNC);
Barrier(UAV_MEMORY, GROUP_SCOPE);
Barrier(UAV_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(UAV_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(GROUP_SHARED_MEMORY, 0);
Barrier(GROUP_SHARED_MEMORY, GROUP_SYNC);
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE | GROUP_SYNC);
}
[Shader("compute")]
[numthreads(1, 1, 1)]
void main() {
DeviceBarriers();
GroupBarriers();
Barrier(buf0, 0);
Barrier(buf0, GROUP_SYNC);
Barrier(buf0, GROUP_SCOPE);
Barrier(buf0, DEVICE_SCOPE);
Barrier(buf0, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
}

Просмотреть файл

@ -0,0 +1,195 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// REQUIRES: dxil-1-8
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Errors expected when called without visible group.
[noinline] export
void GroupBarriers() {
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(0, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, 1 + 2 + 4);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
// expected-error@+1{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, 0);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SYNC);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
}
// Errors expected when called without visible group.
[noinline] export
void GroupNodeBarriers() {
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_INPUT_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_INPUT_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_INPUT_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_INPUT_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_OUTPUT_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_OUTPUT_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_OUTPUT_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(NODE_OUTPUT_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
}
// expected-note@+7{{entry function defined here}}
// expected-note@+6{{entry function defined here}}
// expected-note@+5{{entry function defined here}}
[Shader("node")]
[NodeLaunch("broadcasting")]
[NumThreads(64,1,1)]
[NodeDispatchGrid(1, 1, 1)]
void node01(RWDispatchNodeInputRecord<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
// expected-error@+1{{GROUP_SCOPE specified for Barrier operation without applicable memory}}
Barrier(threadRec, GROUP_SCOPE);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}
// expected-note@+7{{entry function defined here}}
// expected-note@+6{{entry function defined here}}
// expected-note@+5{{entry function defined here}}
// expected-note@+4{{entry function defined here}}
[Shader("node")]
[NodeLaunch("coalescing")]
[NumThreads(64,1,1)]
void node01([MaxRecords(64)] RWGroupNodeInputRecords<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(input, DEVICE_SCOPE);
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
// expected-error@+1{{GROUP_SCOPE specified for Barrier operation without applicable memory}}
Barrier(threadRec, GROUP_SCOPE);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}
// expected-note@+40{{entry function defined here}}
// expected-note@+39{{entry function defined here}}
// expected-note@+38{{entry function defined here}}
// expected-note@+37{{entry function defined here}}
// expected-note@+36{{entry function defined here}}
// expected-note@+35{{entry function defined here}}
// expected-note@+34{{entry function defined here}}
// expected-note@+33{{entry function defined here}}
// expected-note@+32{{entry function defined here}}
// expected-note@+31{{entry function defined here}}
// expected-note@+30{{entry function defined here}}
// expected-note@+29{{entry function defined here}}
// expected-note@+28{{entry function defined here}}
// expected-note@+27{{entry function defined here}}
// expected-note@+26{{entry function defined here}}
// expected-note@+25{{entry function defined here}}
// expected-note@+24{{entry function defined here}}
// expected-note@+23{{entry function defined here}}
// expected-note@+22{{entry function defined here}}
// expected-note@+21{{entry function defined here}}
// expected-note@+20{{entry function defined here}}
// expected-note@+19{{entry function defined here}}
// expected-note@+18{{entry function defined here}}
// expected-note@+17{{entry function defined here}}
// expected-note@+16{{entry function defined here}}
// expected-note@+15{{entry function defined here}}
// expected-note@+14{{entry function defined here}}
// expected-note@+13{{entry function defined here}}
// expected-note@+12{{entry function defined here}}
// expected-note@+11{{entry function defined here}}
// expected-note@+10{{entry function defined here}}
// expected-note@+9{{entry function defined here}}
// expected-note@+8{{entry function defined here}}
// expected-note@+7{{entry function defined here}}
// expected-note@+6{{entry function defined here}}
// expected-note@+5{{entry function defined here}}
// expected-note@+4{{entry function defined here}}
// expected-note@+3{{entry function defined here}}
[Shader("node")]
[NodeLaunch("thread")]
void node02(RWThreadNodeInputRecord<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
GroupBarriers();
GroupNodeBarriers();
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(buf0, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(buf0, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(input, GROUP_SYNC);
// expected-error@+2{{GROUP_SCOPE specified for Barrier operation without applicable memory}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(input, GROUP_SCOPE);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(input, DEVICE_SCOPE);
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(groupRec, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(groupRec, GROUP_SYNC);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(threadRec, GROUP_SYNC);
// expected-error@+2{{GROUP_SCOPE specified for Barrier operation without applicable memory}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(threadRec, GROUP_SCOPE);
// expected-error@+1{{DEVICE_SCOPE specified for Barrier operation without applicable memory}}
Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}

Просмотреть файл

@ -0,0 +1,196 @@
// RUN: %dxc -Tlib_6_8 -Wno-unused-value -verify %s
// REQUIRES: dxil-1-8
// Legal cases, no diagnostics expected for this file.
// expected-no-diagnostics
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Barriers not requiring visible group, compatible with any shader stage.
[noinline] export
void DeviceBarriers() {
Barrier(0, 0);
Barrier(ALL_MEMORY, 0);
Barrier(ALL_MEMORY, DEVICE_SCOPE);
Barrier(ALL_MEMORY, 2 + 2);
Barrier(UAV_MEMORY, 0);
Barrier(UAV_MEMORY, DEVICE_SCOPE);
// No diagnostic for non-constant expressions.
Barrier(ALL_MEMORY, i + i);
Barrier(i + i, 0);
}
// Barriers requiring visible group.
[noinline] export
void GroupBarriers() {
Barrier(0, GROUP_SYNC);
Barrier(ALL_MEMORY, GROUP_SYNC);
Barrier(ALL_MEMORY, GROUP_SCOPE);
Barrier(ALL_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(ALL_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(ALL_MEMORY, 1 + 2 + 4);
Barrier(UAV_MEMORY, GROUP_SYNC);
Barrier(UAV_MEMORY, GROUP_SCOPE);
Barrier(UAV_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(UAV_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(GROUP_SHARED_MEMORY, 0);
Barrier(GROUP_SHARED_MEMORY, GROUP_SYNC);
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE | GROUP_SYNC);
}
// Node barriers not requiring visible group, compatible with all launch modes.
[noinline] export
void NodeBarriers() {
Barrier(NODE_INPUT_MEMORY, 0);
Barrier(NODE_INPUT_MEMORY, DEVICE_SCOPE);
Barrier(NODE_OUTPUT_MEMORY, 0);
Barrier(NODE_OUTPUT_MEMORY, DEVICE_SCOPE);
}
// Node barriers requiring visible group.
[noinline] export
void GroupNodeBarriers() {
Barrier(NODE_INPUT_MEMORY, GROUP_SYNC);
Barrier(NODE_INPUT_MEMORY, GROUP_SCOPE);
Barrier(NODE_INPUT_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(NODE_INPUT_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(NODE_OUTPUT_MEMORY, GROUP_SYNC);
Barrier(NODE_OUTPUT_MEMORY, GROUP_SCOPE);
Barrier(NODE_OUTPUT_MEMORY, GROUP_SCOPE | GROUP_SYNC);
Barrier(NODE_OUTPUT_MEMORY, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
}
//////////////////////////////////////////////////////////////////////////////
// Entry Points
[Shader("node")]
[NodeLaunch("broadcasting")]
[NumThreads(64,1,1)]
[NodeDispatchGrid(1, 1, 1)]
void node01(RWDispatchNodeInputRecord<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
DeviceBarriers();
GroupBarriers();
NodeBarriers();
GroupNodeBarriers();
Barrier(buf0, 0);
Barrier(buf0, GROUP_SYNC);
Barrier(buf0, GROUP_SCOPE);
Barrier(buf0, DEVICE_SCOPE);
Barrier(buf0, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(input, 0);
Barrier(input, GROUP_SYNC);
Barrier(input, GROUP_SCOPE);
Barrier(input, DEVICE_SCOPE);
Barrier(input, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
Barrier(groupRec, 0);
Barrier(groupRec, GROUP_SYNC);
Barrier(groupRec, GROUP_SCOPE);
Barrier(groupRec, GROUP_SCOPE | GROUP_SYNC);
// Not allowed:
// Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
Barrier(threadRec, 0);
Barrier(threadRec, GROUP_SYNC);
// Not allowed:
// Barrier(threadRec, GROUP_SCOPE);
// Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}
[Shader("node")]
[NodeLaunch("coalescing")]
[NumThreads(64,1,1)]
void node01([MaxRecords(64)] RWGroupNodeInputRecords<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
DeviceBarriers();
GroupBarriers();
NodeBarriers();
GroupNodeBarriers();
Barrier(buf0, 0);
Barrier(buf0, GROUP_SYNC);
Barrier(buf0, GROUP_SCOPE);
Barrier(buf0, DEVICE_SCOPE);
Barrier(buf0, DEVICE_SCOPE | GROUP_SCOPE | GROUP_SYNC);
Barrier(input, 0);
Barrier(input, GROUP_SYNC);
Barrier(input, GROUP_SCOPE);
Barrier(input, GROUP_SCOPE | GROUP_SYNC);
// Not allowed:
// Barrier(input, DEVICE_SCOPE);
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
Barrier(groupRec, 0);
Barrier(groupRec, GROUP_SCOPE);
Barrier(groupRec, GROUP_SYNC);
Barrier(groupRec, GROUP_SCOPE | GROUP_SYNC);
// Not allowed:
// Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
Barrier(threadRec, 0);
Barrier(threadRec, GROUP_SYNC);
// Not allowed:
// Barrier(threadRec, GROUP_SCOPE);
// Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}
[Shader("node")]
[NodeLaunch("thread")]
void node02(RWThreadNodeInputRecord<RECORD> input,
[MaxRecords(11)] NodeOutput<RECORD> output) {
DeviceBarriers();
NodeBarriers();
// Not allowed:
// GroupBarriers();
// GroupNodeBarriers();
Barrier(buf0, 0);
Barrier(buf0, DEVICE_SCOPE);
// Not allowed:
// Barrier(buf0, GROUP_SYNC);
// Barrier(buf0, GROUP_SCOPE);
Barrier(input, 0);
// Not allowed:
// Barrier(input, GROUP_SYNC);
// Barrier(input, GROUP_SCOPE);
// Barrier(input, DEVICE_SCOPE);
GroupNodeOutputRecords<RECORD> groupRec = output.GetGroupNodeOutputRecords(1);
Barrier(groupRec, 0);
// Not allowed:
// Barrier(groupRec, GROUP_SCOPE);
// Barrier(groupRec, GROUP_SYNC);
// Barrier(groupRec, DEVICE_SCOPE);
groupRec.OutputComplete();
ThreadNodeOutputRecords<RECORD> threadRec = output.GetThreadNodeOutputRecords(1);
Barrier(threadRec, 0);
// Not allowed:
// Barrier(threadRec, GROUP_SYNC);
// Barrier(threadRec, GROUP_SCOPE);
// Barrier(threadRec, DEVICE_SCOPE);
threadRec.OutputComplete();
}

Просмотреть файл

@ -0,0 +1,99 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// RUN: %dxc -Tvs_6_8 -verify %s
// REQUIRES: dxil-1-8
// Test the ordinary shader model case with no visible group.
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Errors expected when called without visible group.
[noinline] export
void GroupBarriers() {
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(0, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(ALL_MEMORY, 1 + 2 + 4);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SCOPE);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, GROUP_SCOPE | GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(UAV_MEMORY, DEVICE_SCOPE | GROUP_SCOPE);
// expected-error@+1{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, 0);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SYNC);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
// expected-error@+2{{GROUP_SHARED_MEMORY specified for Barrier operation when context has no visible group}}
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
}
// Node barriers not supported in non-node shaders.
[noinline] export
void NodeBarriers() {
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_INPUT_MEMORY, 0);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_INPUT_MEMORY, DEVICE_SCOPE);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_OUTPUT_MEMORY, 0);
// expected-error@+1{{NODE_INPUT_MEMORY or NODE_OUTPUT_MEMORY may only be specified for Barrier operation in a node shader}}
Barrier(NODE_OUTPUT_MEMORY, DEVICE_SCOPE);
}
// expected-note@+24{{entry function defined here}}
// expected-note@+23{{entry function defined here}}
// expected-note@+22{{entry function defined here}}
// expected-note@+21{{entry function defined here}}
// expected-note@+20{{entry function defined here}}
// expected-note@+19{{entry function defined here}}
// expected-note@+18{{entry function defined here}}
// expected-note@+17{{entry function defined here}}
// expected-note@+16{{entry function defined here}}
// expected-note@+15{{entry function defined here}}
// expected-note@+14{{entry function defined here}}
// expected-note@+13{{entry function defined here}}
// expected-note@+12{{entry function defined here}}
// expected-note@+11{{entry function defined here}}
// expected-note@+10{{entry function defined here}}
// expected-note@+9{{entry function defined here}}
// expected-note@+8{{entry function defined here}}
// expected-note@+7{{entry function defined here}}
// expected-note@+6{{entry function defined here}}
// expected-note@+5{{entry function defined here}}
// expected-note@+4{{entry function defined here}}
// expected-note@+3{{entry function defined here}}
// expected-note@+2{{entry function defined here}}
[Shader("vertex")]
uint main() : OUT {
GroupBarriers();
NodeBarriers();
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(buf0, GROUP_SYNC);
// expected-error@+1{{GROUP_SYNC or GROUP_SCOPE specified for Barrier operation when context has no visible group}}
Barrier(buf0, GROUP_SCOPE);
return buf0[0];
}

Просмотреть файл

@ -0,0 +1,38 @@
// RUN: %dxc -Tlib_6_8 -verify %s
// RUN: %dxc -Tvs_6_8 -verify %s
// REQUIRES: dxil-1-8
// Test the ordinary shader model case with no visible group.
// expected-no-diagnostics
struct RECORD { uint a; };
RWBuffer<uint> buf0;
static uint i = 7;
// Barriers not requiring visible group, compatible with any shader stage.
[noinline] export
void DeviceBarriers() {
Barrier(0, 0);
Barrier(ALL_MEMORY, 0);
Barrier(ALL_MEMORY, DEVICE_SCOPE);
Barrier(ALL_MEMORY, 2 + 2);
Barrier(UAV_MEMORY, 0);
Barrier(UAV_MEMORY, DEVICE_SCOPE);
// No diagnostic for non-constant expressions.
Barrier(ALL_MEMORY, i + i);
Barrier(i + i, 0);
}
[Shader("vertex")]
uint main() : OUT {
DeviceBarriers();
Barrier(buf0, 0);
Barrier(buf0, DEVICE_SCOPE);
return buf0[0];
}

Просмотреть файл

@ -160,7 +160,7 @@ void node_RWGroupNodeInputRecords([MaxRecords(4)] RWGroupNodeInputRecords<RECORD
[NodeLaunch("thread")]
void node_ThreadNodeInputRecord(ThreadNodeInputRecord<RECORD> input)
{
Barrier(wrapper(input), 3);
Barrier(wrapper(input), 0);
}
// RWThreadNodeInputRecord
@ -180,7 +180,7 @@ void node_ThreadNodeInputRecord(ThreadNodeInputRecord<RECORD> input)
[NodeLaunch("thread")]
void node_RWThreadNodeInputRecord(RWThreadNodeInputRecord<RECORD> input)
{
Barrier(wrapper(input), 3);
Barrier(wrapper(input), 0);
}
// EmptyNodeInput
// AST: FunctionDecl 0x{{.+}} node_EmptyNodeInput 'void (EmptyNodeInput)'
@ -238,7 +238,8 @@ void node_NodeOutput(NodeOutput<RECORD> output3)
// EmptyNodeOutput
// AST: FunctionDecl 0x{{.+}} node_EmptyNodeOutput 'void (EmptyNodeOutput)'
// AST: | |-ParmVarDecl 0x[[Param:[0-9a-f]+]] {{.+}} col:40 used loadStressChild 'EmptyNodeOutput'
// AST: | |-ParmVarDecl 0x[[Param:[0-9a-f]+]] {{.+}} col:35 used loadStressChild 'EmptyNodeOutput'
// AST: | | `-HLSLMaxRecordsAttr 0x{{.+}} 12
// call to wrapper
// AST: CallExpr 0x{{.+}} <col:27, col:50> 'EmptyNodeOutput':'EmptyNodeOutput'
// AST: |-ImplicitCastExpr 0x{{.+}} <col:27> 'EmptyNodeOutput (*)(EmptyNodeOutput)' <FunctionToPointerDecay>
@ -259,7 +260,7 @@ EmptyNodeOutput outputNode)
[NodeDispatchGrid(1, 1, 1)]
[NumThreads(1, 1, 1)]
void node_EmptyNodeOutput(
[MaxOutputRecords(1)] EmptyNodeOutput loadStressChild
[MaxRecords(12)] EmptyNodeOutput loadStressChild
)
{
loadStressEmptyRecWorker(wrapper(loadStressChild));

Просмотреть файл

@ -7,7 +7,7 @@ SamplerComparisonState ss : register(s2);
RWStructuredBuffer<uint> o;
Texture1D <float> t1;
// expected-note@+3{{declared here}}
// expected-note@+3{{entry function defined here}}
[numthreads(3,8,1)]
[shader("compute")]
void foo(uint3 id : SV_GroupThreadID)
@ -24,7 +24,7 @@ void foo2(uint3 id : SV_GroupThreadID)
o[0] = t1.CalculateLevelOfDetail(ss, 0.5);
}
// expected-note@+3{{declared here}}
// expected-note@+3{{entry function defined here}}
[numthreads(3,1,1)]
[shader("compute")]
void bar(uint3 id : SV_GroupThreadID)
@ -33,7 +33,7 @@ void bar(uint3 id : SV_GroupThreadID)
o[0] = t1.CalculateLevelOfDetail(ss, 0.5);
}
// expected-note@+4{{declared here}}
// expected-note@+4{{entry function defined here}}
[shader("mesh")]
[numthreads(3,1,1)]
[outputtopology("triangle")]
@ -47,7 +47,7 @@ struct Payload {
float2 dummy;
};
// expected-note@+3{{declared here}}
// expected-note@+3{{entry function defined here}}
[numthreads(3, 2, 1)]
[shader("amplification")]
void ASmain()
@ -63,7 +63,7 @@ struct RECORD {
uint a;
};
// expected-note@+5{{declared here}}
// expected-note@+5{{entry function defined here}}
[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeDispatchGrid(1, 1, 1)]
@ -73,7 +73,7 @@ void node01(DispatchNodeInputRecord<RECORD> input) {
o[0] = t1.CalculateLevelOfDetail(ss, 0.5);
}
// expected-note@+5{{declared here}}
// expected-note@+5{{entry function defined here}}
[Shader("node")]
[NodeLaunch("coalescing")]
[NumThreads(1024,1,1)]
@ -84,7 +84,7 @@ void node02()
o[0] = t1.CalculateLevelOfDetail(ss, 0.5);
}
// expected-note@+2 {{declared here}}
// expected-note@+2 {{entry function defined here}}
[Shader("vertex")]
float4 vs(float2 a :A) :SV_POSTION {
float r = 0;
@ -96,8 +96,8 @@ float4 vs(float2 a :A) :SV_POSTION {
SamplerComparisonState s;
Texture1D t;
// expected-note@+3{{declared here}}
// expected-note@+2{{declared here}}
// expected-note@+3{{entry function defined here}}
// expected-note@+2{{entry function defined here}}
[shader("vertex")]
float4 vs2(float a:A) : SV_Position {
// expected-error@+1 {{Intrinsic CalculateLevelOfDetail potentially used by 'vs2' requires derivatives - only available in pixel, compute, amplification, mesh, or broadcast node shaders}}

Просмотреть файл

@ -563,7 +563,7 @@ FileRunCommandPart::RunDxc(dxc::DxcDllSupport &DllSupport,
FileRunCommandResult result = {};
if (SUCCEEDED(resultStatus)) {
IFT(pResult->GetResult(&pCompiledBlob));
if (!opts.AstDump && !opts.DumpDependencies) {
if (!opts.AstDump && !opts.DumpDependencies && !opts.VerifyDiagnostics) {
IFT(pCompiler->Disassemble(pCompiledBlob, &pDisassembly));
result.StdOut = BlobToUtf8(pDisassembly);
} else {