Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The included licenses apply to the following files:
- Fixed regression: [#7508](https://github.com/microsoft/DirectXShaderCompiler/issues/7508) crash when calling `Load` with `status`.
- Header file `dxcpix.h` was added to the release package.
- Moved Linear Algebra (Cooperative Vector) DXIL Opcodes to experimental Shader Model 6.10
- Added support for the groupshared attribute for parameters to Shader Model 6.10
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it would be good to start a habit of linking the PR with the note? I like the idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't have a preference although I'd be inclined to follow the seeming convention of not including, unless you can find further support for this change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Some of the items link issues. Some link PRs (the highlights for 1.8.2502). Others do nothing. Just seems random.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Some of the items link issues. Some link PRs (the highlights for 1.8.2502). Others do nothing. Just seems random.

ok i guess the ones i looked at didn't link, but i must have missed some.


### Version 1.8.2505

Expand Down
3 changes: 2 additions & 1 deletion lib/HLSL/HLLegalizeParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ bool HLLegalizeParameter::runOnModule(Module &M) {
continue;

for (Argument &Arg : F.args()) {
if (!Arg.getType()->isPointerTy())
Type *PtrTy = dyn_cast<PointerType>(Arg.getType());
if (!PtrTy || DXIL::kTGSMAddrSpace == PtrTy->getPointerAddressSpace())
continue;
Type *EltTy = dxilutil::GetArrayEltTy(Arg.getType());
if (dxilutil::IsHLSLObjectType(EltTy) ||
Expand Down
8 changes: 8 additions & 0 deletions tools/clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// Whether the parameter is copied out.
unsigned IsModifierOut : 1;

/// Whether the parameter should be treated as a reference.
unsigned IsModifierRef : 1;

/// The number of parameters preceding this parameter in the
/// function parameter scope in which it was declared.
unsigned ParameterIndex : NumParameterIndexBits;
Expand Down Expand Up @@ -1377,6 +1380,7 @@ class ParmVarDecl : public VarDecl {
assert(ParmVarDeclBits.IsObjCMethodParam == false);
setDefaultArg(DefArg);
// HLSL Change Start
setModifierRef(ParamMod.isRef());
setModifierIn(ParamMod.isAnyIn());
setModifierOut(ParamMod.isAnyOut());
// change to reference type for out param
Expand Down Expand Up @@ -1456,8 +1460,12 @@ class ParmVarDecl : public VarDecl {
void setModifierIn(bool value) { ParmVarDeclBits.IsKNRPromoted = !value; }
bool isModifierOut() const { return ParmVarDeclBits.IsModifierOut; }
void setModifierOut(bool value) { ParmVarDeclBits.IsModifierOut = value; }
bool isModifierRef() const { return ParmVarDeclBits.IsModifierRef; }
void setModifierRef(bool value) { ParmVarDeclBits.IsModifierRef = value; }
/// Synthesize a ParameterModifier value for this parameter.
hlsl::ParameterModifier getParamModifiers() const {
if (isModifierRef())
return hlsl::ParameterModifier(hlsl::ParameterModifier::Kind::Ref);
if (isModifierIn() && !isModifierOut())
return hlsl::ParameterModifier(hlsl::ParameterModifier::Kind::In);
if (isModifierIn() && isModifierOut())
Expand Down
7 changes: 7 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,13 @@ def warn_hlsl_sometimes_uninit_out_param : Warning<
"its declaration is reached|"
"%3 is called}2">,
InGroup<HLSLParameterUsage>;
def warn_hlsl_groupshared_202x: Warning<
"Support for groupshared parameter annotation not added until HLSL 202x">,
InGroup<HLSLParameterUsage>;
def warn_hlsl_groupshared_inout: Warning<
"Passing groupshared variable to a parameter annotated with inout. See "
"'groupshared' parameter annotation added in 202x.">,
InGroup<HLSLParameterUsage>;
// HLSL Change End - Add warning for uninitialized out param
def warn_maybe_uninit_var : Warning<
"variable %0 may be uninitialized when "
Expand Down
1 change: 1 addition & 0 deletions tools/clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ namespace hlsl {

unsigned getAsUnsigned() const { return (unsigned)m_Kind; }

bool isRef() const { return m_Kind == Kind::Ref; }
bool isIn() const { return m_Kind == Kind::In; }
bool isOut() const { return m_Kind == Kind::Out; }
bool isInOut() const { return m_Kind == Kind::InOut; }
Expand Down
14 changes: 14 additions & 0 deletions tools/clang/lib/AST/HlslTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ bool HasHLSLReorderCoherent(clang::QualType type) {
return false;
}

/// Checks whether the pAttributes indicate a parameter is groupshared
bool IsParamAttributedAsGroupShared(clang::AttributeList *pAttributes);

/// Checks whether the pAttributes indicate a parameter is inout or out; if
/// inout, pIsIn will be set to true.
bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn);
Expand Down Expand Up @@ -934,6 +937,15 @@ unsigned GetHLSLOutputPatchCount(QualType type) {
return argList[1].getAsIntegral().getLimitedValue();
}

bool IsParamAttributedAsGroupShared(clang::AttributeList *pAttributes) {
while (pAttributes != nullptr) {
if (pAttributes->getKind() == AttributeList::AT_HLSLGroupShared)
return true;
pAttributes = pAttributes->getNext();
}
return false;
}

bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn) {
bool anyFound = false;
bool inFound = false;
Expand Down Expand Up @@ -967,6 +979,8 @@ bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn) {

hlsl::ParameterModifier
ParamModFromAttributeList(clang::AttributeList *pAttributes) {
if (IsParamAttributedAsGroupShared(pAttributes))
return ParameterModifier(hlsl::ParameterModifier::Kind::Ref);
bool isIn, isOut;
isOut = IsParamAttributedAsOut(pAttributes, &isIn);
return ParameterModifier::FromInOut(isIn, isOut);
Expand Down
5 changes: 5 additions & 0 deletions tools/clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//

#include "dxc/DXIL/DxilConstants.h"

#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
Expand Down Expand Up @@ -2033,6 +2035,9 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
Out << (Quals.hasVolatile() ? 'B' : 'A');
if (PointeeType.getQualifiers().getAddressSpace() ==
hlsl::DXIL::kTGSMAddrSpace)
Out << 'G';
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
Expand Down
6 changes: 5 additions & 1 deletion tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,9 @@ unsigned CGMSHLSLRuntime::AddTypeAnnotation(QualType Ty,
if (const ReferenceType *RefType = dyn_cast<ReferenceType>(paramTy))
paramTy = RefType->getPointeeType();

if (const ReferenceType *RefType = dyn_cast<ReferenceType>(Ty))
Ty = RefType->getPointeeType();

// Get size.
llvm::Type *Type = CGM.getTypes().ConvertType(paramTy);
unsigned size = dataLayout.getTypeAllocSize(Type);
Expand Down Expand Up @@ -6232,7 +6235,8 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(
}
} else if (isAggregateType) {
// aggregate in-only - emit RValue, unless LValueToRValue cast
EmitRValueAgg = true;
if (Param->isModifierIn())
EmitRValueAgg = true;
if (const ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(Arg)) {
if (cast->getCastKind() == CastKind::CK_LValueToRValue) {
EmitRValueAgg = false;
Expand Down
6 changes: 6 additions & 0 deletions tools/clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4945,6 +4945,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
break;
case AttributeList::AT_NoInline:
if (S.LangOpts.HLSL) {
Copy link

Choose a reason for hiding this comment

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

I am not quite sure I understand this change. Would we otherwise not parse the attributes of the parameter without this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the basic handling wouldn't check if a parameter of a function with the noinline attribute has the groupshared attribute.

bool Handled = false;
hlsl::HandleDeclAttributeForHLSL(S, D, Attr, Handled);
if (Handled)
break;
}
handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
break;
case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
Expand Down
34 changes: 33 additions & 1 deletion tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14474,6 +14474,21 @@ void Sema::DiagnoseHLSLDeclAttr(const Decl *D, const Attr *A) {
HLSLExternalSource *ExtSource = HLSLExternalSource::FromSema(this);
const bool IsGCAttr = isa<HLSLGloballyCoherentAttr>(A);
const bool IsRCAttr = isa<HLSLReorderCoherentAttr>(A);
const bool IsExportAttr = isa<HLSLExportAttr>(A);
const bool IsNoInlineAttr = isa<NoInlineAttr>(A);
if (IsExportAttr || IsNoInlineAttr) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can remove an indentation level by just retrning early if neither condition is true

Suggested change
if (IsExportAttr || IsNoInlineAttr) {
if (!IsExportAttr || !IsNoInlineAttr)
return;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The function doesn't return if this is false.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the if statement should probably not be returning either.

Copy link
Contributor

Choose a reason for hiding this comment

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

The function doesn't return if this is false.

🤦‍♂️

if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
for (ParmVarDecl *PVD : FD->parameters()) {
if (PVD->hasAttr<HLSLGroupSharedAttr>()) {
Diag(A->getLocation(), diag::err_hlsl_varmodifiersna)
<< "groupshared"
<< "export/noinline"
<< "parameter";
return;
}
}
}
}
if (IsGCAttr || IsRCAttr) {
const ValueDecl *TD = cast<ValueDecl>(D);
if (TD->getType()->isDependentType())
Expand Down Expand Up @@ -14655,6 +14670,8 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
VD->setType(
S.Context.getAddrSpaceQualType(VD->getType(), DXIL::kTGSMAddrSpace));
}
if (ParmVarDecl *VD = dyn_cast<ParmVarDecl>(D))
VD->setType(S.Context.getLValueReferenceType(VD->getType()));
break;
case AttributeList::AT_HLSLUniform:
declAttr = ::new (S.Context) HLSLUniformAttr(
Expand Down Expand Up @@ -14996,6 +15013,7 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
}

if (declAttr != nullptr) {
S.DiagnoseHLSLDeclAttr(D, declAttr);
DXASSERT_NOMSG(Handled);
D->addAttr(declAttr);

Expand Down Expand Up @@ -15749,7 +15767,17 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth,
break;
case AttributeList::AT_HLSLGroupShared:
isGroupShared = true;
if (!isGlobal) {
if (isParameter && getLangOpts().HLSLVersion < hlsl::LangStd::v202x)
Diag(pAttr->getLoc(), diag::warn_hlsl_groupshared_202x);
if (isParameter && (usageIn || usageOut)) {
Diag(pAttr->getLoc(), diag::err_hlsl_varmodifiersna)
<< (usageIn && usageOut ? "'inout'"
: usageIn ? "'in'"
: "'out'")
<< pAttr->getName() << declarationType;
result = false;
}
if (!(isGlobal || isParameter)) {
Diag(pAttr->getLoc(), diag::err_hlsl_varmodifierna)
<< pAttr->getName() << declarationType << pAttr->getRange();
result = false;
Expand Down Expand Up @@ -15786,6 +15814,10 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth,
Diag(pAttr->getLoc(), diag::err_hlsl_usage_not_on_parameter)
<< pAttr->getName() << pAttr->getRange();
result = false;
} else if (isGroupShared) {
Copy link

Choose a reason for hiding this comment

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

Is it guaranteed that groupshared will be processed/specified before inout?

Otherwise, we might need to handle the opposite case above

Copy link
Collaborator Author

@spall spall Jan 16, 2026

Choose a reason for hiding this comment

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

Looking at the cases for inout and for groupshared I think it is handled regardless of order, but good point and I think this points to a test is missing for this.

Diag(pAttr->getLoc(), diag::err_hlsl_varmodifiersna)
<< pAttr->getName() << "'groupshared'" << declarationType;
result = false;
}
if (!IsUsageAttributeCompatible(pAttr->getKind(), usageIn, usageOut)) {
Diag(pAttr->getLoc(), diag::err_hlsl_duplicate_parameter_usages)
Expand Down
20 changes: 20 additions & 0 deletions tools/clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4953,6 +4953,26 @@ InitCallParamConversions(Sema &S, const FunctionProtoType *Proto,
ImplicitConversionSequence &OutConversion) {
hlsl::ParameterModifier paramMods = Proto->getParamMods()[ArgIdx];
QualType ParamType = Proto->getParamType(ArgIdx);

// must be a Ref; don't allow any conversions
if (!(paramMods.isAnyIn() || paramMods.isAnyOut())) {
if (!S.getASTContext().hasSameUnqualifiedType(
ParamType.getNonReferenceType(), Arg->getType()) ||
Arg->getType().getQualifiers().getAddressSpace() !=
hlsl::DXIL::kTGSMAddrSpace) {
InConversion.setBad(BadConversionSequence::no_conversion, Arg->getType(),
ParamType.getNonReferenceType());
InConversion.Bad.FromExpr = Arg;
return;
}
}

if (S.getLangOpts().HLSLVersion >= hlsl::LangStd::v202x &&
paramMods.isAnyIn() && paramMods.isAnyOut() &&
Arg->getType().getQualifiers().getAddressSpace() ==
hlsl::DXIL::kTGSMAddrSpace)
S.Diag(Arg->getLocStart(), diag::warn_hlsl_groupshared_inout);

if (paramMods.isAnyIn()) {
InConversion =
TryCopyInitialization(S, Arg, ParamType, SuppressUserConversions,
Expand Down
16 changes: 16 additions & 0 deletions tools/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %dxc -E main -T cs_6_0 -HV 202x -fcgl %s | FileCheck %s

groupshared float4 SharedArr[64];

// CHECK-LABEL: define internal void @"\01?fn@@YAXAGAY0EA@$$CAV?$vector@M$03@@M@Z"([64 x <4 x float>] addrspace(3)* dereferenceable(1024) %Arr, float %F)
// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [64 x <4 x float>], [64 x <4 x float>] addrspace(3)* %Arr, i32 0, i32 5
// CHECK-NEXT: store <4 x float> {{.*}}, <4 x float> addrspace(3)* [[ArrIdx]], align 4
void fn(groupshared float4 Arr[64], float F) {
float4 tmp = F.xxxx;
Arr[5] = tmp;
}

[numthreads(4,1,1)]
void main() {
fn(SharedArr, 6.0);
}
18 changes: 18 additions & 0 deletions tools/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %dxc -E main -T cs_6_3 -HV 202x -fcgl %s | FileCheck %s

groupshared float4x4 SharedData;

// CHECK-LABEL: @"\01?fn1@@YAXAGAV?$matrix@M$03$03@@@Z"
// CHECK: [[M1:%.*]] = addrspacecast %class.matrix.float.4.4 addrspace(3)* %Sh to %class.matrix.float.4.4*
// CHECK: [[A:%.*]] = call <4 x float>* @"dx.hl.subscript.colMajor[].rn.<4 x float>* (i32, %class.matrix.float.4.4*, i32, i32, i32, i32)"(i32 1, %class.matrix.float.4.4* [[M1]], i32 0, i32 4, i32 8, i32 12)
// CHECK: [[B:%.*]] = getelementptr <4 x float>, <4 x float>* [[A]], i32 0, i32 1
// CHECK: store float 5.000000e+00, float* [[B]]
// CHECK: ret void
void fn1(groupshared float4x4 Sh) {
Sh[0][1] = 5.0;
}

[numthreads(4,1,1)]
void main(uint3 TID : SV_GroupThreadID) {
fn1(SharedData);
}
37 changes: 37 additions & 0 deletions tools/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: %dxc -E main -T cs_6_0 -HV 202x -fcgl %s | FileCheck %s

// Verify we are calling the correct overloads
void fn(groupshared float4 Arr[2]);
void fn(inout float4 Arr[2]);

void fn2(groupshared int4 Shared);
void fn2(int4 Local);

// CHECK-LABEL: define void @main()
[numthreads(4,1,1)]
void main() {
float4 Local[2] = {1.0.xxxx, 2.0.xxxx};
// CHECK: call void @"\01?fn@@YAXY01$$CAV?$vector@M$03@@@Z"([2 x <4 x float>]* %Local)
fn(Local);

// CHECK: call void @"\01?fn2@@YAXV?$vector@H$03@@@Z"(<4 x i32>
fn2(11.xxxx);
}

void fn(groupshared float4 Arr[2]) {
Arr[1] = 7.0.xxxx;
}

// CHECK-LABEL: define internal void @"\01?fn@@YAXY01$$CAV?$vector@M$03@@@Z"([2 x <4 x float>]* noalias %Arr)
void fn(inout float4 Arr[2]) {
Arr[1] = 5.0.xxxx;
}

void fn2(groupshared int4 Shared) {
Shared.x = 10;
}

// CHECK-LABEL: define internal void @"\01?fn2@@YAXV?$vector@H$03@@@Z"(<4 x i32> %Local)
void fn2(int4 Local) {
int X = Local.y;
}
16 changes: 16 additions & 0 deletions tools/clang/test/CodeGenHLSL/groupsharedArgs/ScalarTest.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %dxc -E main -T cs_6_2 -enable-16bit-types -HV 202x -fcgl %s | FileCheck %s

groupshared uint16_t SharedData;

// Make sure the mangling changes for groupshared parameter annotation is reflected in the function signature (the first G)
// The mangled function signature for void fn(uint16_t Sh) should be @"\01?fn1@@YAXAAG@Z" (without the extra G)
// CHECK-LABEL: @"\01?fn1@@YAXAGAG@Z"
// CHECK: store i16 5, i16 addrspace(3)* %Sh, align 4
void fn1(groupshared uint16_t Sh) {
Sh = 5;
}

[numthreads(4, 1, 1)]
void main(uint3 TID : SV_GroupThreadID) {
fn1(SharedData);
}
32 changes: 32 additions & 0 deletions tools/clang/test/CodeGenHLSL/groupsharedArgs/StructTest.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %dxc -E main -T cs_6_3 -HV 202x -fcgl %s | FileCheck %s

struct Shared {
int A;
float F;
double Arr[4];
};

groupshared Shared SharedData;

// CHECK-LABEL: @"\01?fn1@@YAXAGAUShared@@@Z"
// CHECK: [[D:%.*]] = alloca double, align 8
// CHECK: [[A:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 0
// CHECK: store i32 10, i32 addrspace(3)* [[A]], align 4
// CHECK: [[F:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 1
// CHECK: store float 0x40263851E0000000, float addrspace(3)* %F, align 4
// CHECK: store double 1.000000e+01, double* [[D]], align 8
// CHECK: [[Z:%.*]] = load double, double* [[D]], align 8
// CHECK: [[Arr:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 2
// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [4 x double], [4 x double] addrspace(3)* [[Arr]], i32 0, i32 1
// CHECK: store double [[Z]], double addrspace(3)* [[ArrIdx]], align 4
void fn1(groupshared Shared Sh) {
Sh.A = 10;
Sh.F = 11.11;
double D = 10.0;
Sh.Arr[1] = D;
}

[numthreads(4, 1, 1)]
void main(uint3 TID : SV_GroupThreadID) {
fn1(SharedData);
}
Loading