Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 3 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ line upon naming the release. Refer to previous for appropriate section names.
- HLSL 202x now supports variadic templates and template function parameter
packs, pack expansions, and `sizeof...()`
[#8905](https://github.com/microsoft/DirectXShaderCompiler/issues/8905).
- HLSL 202x disallows initializers on variables in explicit and implicit
constant buffers and texture buffers
[#8483](https://github.com/microsoft/DirectXShaderCompiler/issues/8483).
Comment thread
Copilot marked this conversation as resolved.
- HLSL 202x disallows putting cbuffer, tbuffer, or namespace declarations inside
a cbuffer or tbuffer
[#8484](https://github.com/microsoft/DirectXShaderCompiler/issues/8484).
Expand Down
3 changes: 3 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,9 @@ def HLSLParameterUsage : DiagGroup<"parameter-usage">;
def HLSLAvailability: DiagGroup<"hlsl-availability">;
def HLSLAvailabilityConstant: DiagGroup<"hlsl-availability-constant">;
def HLSLBarrier : DiagGroup<"hlsl-barrier">;
def HLSLBufferInitializer : DiagGroup<"hlsl-buffer-initializer">;
def HLSLGroupSharedInitializer :
DiagGroup<"hlsl-groupshared-initializer">;

// HLSL 2026 compatibility warnings: these warn on code in older language modes
// that changes meaning or becomes illegal in HLSL 2026.
Expand Down
8 changes: 8 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7575,6 +7575,14 @@ def err_hlsl_packoffset_requires_cbuffer : Error<
"packoffset is only allowed in a constant buffer">;
def warn_hlsl_packoffset_mix : Warning<
"cannot mix packoffset elements with nonpackoffset elements in a cbuffer">;
def warn_hlsl_buffer_initializer : Warning<
"initializer for a variable in a %select{tbuffer|cbuffer}0 will be ignored">,
InGroup<HLSLBufferInitializer>;
def err_hlsl_buffer_initializer : Error<
"variable in a %select{tbuffer|cbuffer}0 cannot have an initializer">;
def warn_hlsl_groupshared_initializer : Warning<
"initializer of 'groupshared' variable will be ignored">,
InGroup<HLSLGroupSharedInitializer>;
def err_hlsl_packoffset_overlap : Error<"packoffset overlap between %0, %1">;
def err_hlsl_register_semantics_conflicting : Error<
"conflicting register semantics">;
Expand Down
14 changes: 2 additions & 12 deletions tools/clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2109,12 +2109,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
NeedsGlobalCtor = true;
// HLSL Change Begins.
if (getLangOpts().HLSL && D->isExternallyVisible()) {
// For global constant with init, the init will be ignored.
// Warning here.
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Warning,
"Initializer of external global will be ignored");
Diags.Report(D->getLocation(), DiagID);
// Don't create global ctor for it.
NeedsGlobalCtor = false;
}
Expand All @@ -2130,13 +2124,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
if (getLangOpts().CPlusPlus && !NeedsGlobalDtor)
DelayedCXXInitPosition.erase(D);
// HLSL Change Begins.
if (getLangOpts().HLSL && D->isExternallyVisible() && !D->isStaticDataMember()) {
// For global constant with init, the init will be ignored.
if (getLangOpts().HLSL && D->isExternallyVisible() &&
!D->isStaticDataMember()) {
Init = EmitNullConstant(D->getType());
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Warning,
"Initializer of external global will be ignored");
Diags.Report(D->getLocation(), DiagID);
}
// HLSL Change Ends.
}
Expand Down
7 changes: 0 additions & 7 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1780,13 +1780,6 @@ void DeclResultIdMapper::createGlobalsCBuffer(const VarDecl *var) {
uint32_t index = 0;
for (const auto *decl : collectDeclsInDeclContext(context)) {
if (const auto *varDecl = dyn_cast<VarDecl>(decl)) {
if (!spirvOptions.noWarnIgnoredFeatures) {
if (const auto *init = varDecl->getInit())
emitWarning(
"variable '%0' will be placed in $Globals so initializer ignored",
init->getExprLoc())
<< var->getName() << init->getSourceRange();
}
if (const auto *attr = varDecl->getAttr<VKBindingAttr>()) {
emitError("variable '%0' will be placed in $Globals so cannot have "
"vk::binding attribute",
Expand Down
14 changes: 0 additions & 14 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1937,21 +1937,11 @@ void SpirvEmitter::registerCapabilitiesAndExtensionsForVarDecl(

void SpirvEmitter::doHLSLBufferDecl(const HLSLBufferDecl *bufferDecl) {
// This is a cbuffer/tbuffer decl.
// Check and emit warnings for member intializers which are not
// supported in Vulkan
for (const auto *member : bufferDecl->decls()) {
if (const auto *varMember = dyn_cast<VarDecl>(member)) {
if (varMember->getStorageClass() == StorageClass::SC_Static)
continue;

if (!spirvOptions.noWarnIgnoredFeatures) {
if (const auto *init = varMember->getInit())
emitWarning("%select{tbuffer|cbuffer}0 member initializer "
"ignored since no Vulkan equivalent",
init->getExprLoc())
<< bufferDecl->isCBuffer() << init->getSourceRange();
}

// We cannot handle external initialization of column-major matrices now.
if (isOrContainsNonFpColMajorMatrix(astContext, spirvOptions,
varMember->getType(), varMember)) {
Expand Down Expand Up @@ -2199,10 +2189,6 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) {
// variables) belongs to the Function storage class.
if (isExternalVar(decl)) {
var = declIdMapper.createExternVar(decl);
if (decl->hasInit()) {
emitWarning("Initializer of external global will be ignored",
decl->getLocation());
}
} else {
// We already know the variable is not externally visible here. If it does
// not have local storage, it should be file scope variable.
Expand Down
44 changes: 44 additions & 0 deletions tools/clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {

namespace {

// HLSL Change Begin
// Returns true if VD is a shader constant: a variable stored in an explicit
// cbuffer/tbuffer declaration, or in the implicit $Globals constant buffer.
// On success IsConstantBuffer is false only for tbuffer members.
bool IsHLSLShaderConstant(const VarDecl *VD, bool &IsConstantBuffer) {
if (const auto *Buffer = dyn_cast<HLSLBufferDecl>(VD->getDeclContext())) {
IsConstantBuffer = Buffer->isCBuffer();
return VD->getStorageClass() != SC_Static;
}

IsConstantBuffer = true;
const DeclContext *DC = VD->getDeclContext();
return (DC->isTranslationUnit() || DC->isNamespace()) &&
VD->hasExternalFormalLinkage() &&
!VD->hasAttr<HLSLGroupSharedAttr>() &&
Comment thread
Copilot marked this conversation as resolved.
!VD->hasAttr<VKConstantIdAttr>() &&
!VD->hasAttr<VKPushConstantAttr>() &&
!VD->hasAttr<VKStorageClassExtAttr>() &&
hlsl::IsHLSLNumericOrAggregateOfNumericType(VD->getType());
}
// HLSL Change End

class TypeNameValidatorCCC : public CorrectionCandidateCallback {
public:
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
Expand Down Expand Up @@ -9334,6 +9356,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// Attach the initializer to the decl.
VDecl->setInit(Init);

// HLSL Change Begin
if (getLangOpts().HLSL) {
if (VDecl->hasAttr<HLSLGroupSharedAttr>() &&
(getLangOpts().SPIRV || VDecl->isExternallyVisible())) {
Diag(Init->getExprLoc(), diag::warn_hlsl_groupshared_initializer)
<< Init->getSourceRange();
} else {
// Variables in a cbuffer/tbuffer declaration, or in the implicit
// $Globals constant buffer, are initialized by the pipeline, so any
// initializer is ignored. This is an error starting with HLSL 202x.
bool IsConstantBuffer = false;
if (IsHLSLShaderConstant(VDecl, IsConstantBuffer)) {
Diag(Init->getExprLoc(),
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x
? diag::err_hlsl_buffer_initializer
: diag::warn_hlsl_buffer_initializer)
<< IsConstantBuffer << Init->getSourceRange();
}
}
}
// HLSL Change End

if (VDecl->isLocalVarDecl()) {
// C99 6.7.8p4: All the expressions in an initializer for an object that has
// static storage duration shall be constant expressions or string literals.
Expand Down
13 changes: 7 additions & 6 deletions tools/clang/test/CodeGenSPIRV/groupshared.init.warning.hlsl
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
// RUN: %dxc -T cs_6_0 -E main -spirv %s 2>&1 | FileCheck %s
// RUN: %dxc -T cs_6_0 -E main -spirv -verify %s

groupshared uint testing = 0;
// expected-warning@-1 {{initializer of 'groupshared' variable will be ignored}}

static groupshared uint staticTesting = 1;
// expected-warning@-1 {{initializer of 'groupshared' variable will be ignored}}

[numthreads(64, 1, 1)]
void main(uint local_thread_id_flat : SV_GroupIndex) {

InterlockedAdd(testing, 1);
InterlockedAdd(testing, staticTesting);
GroupMemoryBarrierWithGroupSync();

if (local_thread_id_flat == 0) {
if (testing > 64) {
printf("testing is %u wtf", testing);
}
}
}

// CHECK: warning: Initializer of external global will be ignored
// CHECK-NEXT: groupshared uint testing = 0;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

newline

3 changes: 2 additions & 1 deletion tools/clang/test/CodeGenSPIRV/implicit.global.ubo.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %dxc -T ps_6_0 -E main %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -Werror %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -HV 202x %s -spirv | FileCheck %s

// This test checks that the specialization constant and push constants are not
// included in the implicit global ubo.
Expand Down
7 changes: 4 additions & 3 deletions tools/clang/test/CodeGenSPIRV/var.globals.error.hlsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// RUN: not %dxc -T vs_6_0 -E main -fcgl %s -spirv 2>&1 | FileCheck %s

// Note: this test uses FileCheck instead of -verify because the error
// diagnostic comes from the code generation layer instead of sema.
[[vk::binding(10, 2)]] float4 gVec = 1.0;

float4 main() : A { return gVec; }

// CHECK: :3:38: warning: variable 'gVec' will be placed in $Globals so initializer ignored
// CHECK: :3:3: error: variable 'gVec' will be placed in $Globals so cannot have vk::binding attribute
// CHECK: :4:38: warning: initializer for a variable in a cbuffer will be ignored
// CHECK: :4:3: error: variable 'gVec' will be placed in $Globals so cannot have vk::binding attribute
9 changes: 3 additions & 6 deletions tools/clang/test/CodeGenSPIRV/var.init.cbuffer.hlsl
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// RUN: %dxc -T vs_6_0 -E main -fcgl %s -spirv 2>&1 | FileCheck %s
// RUN: %dxc -T vs_6_0 -E main -verify %s -spirv

cbuffer MyCBuffer {
float a = 1.0;
float4 b = 2.0;
float a = 1.0; // expected-warning{{initializer for a variable in a cbuffer will be ignored}}
float4 b = 2.0; // expected-warning{{initializer for a variable in a cbuffer will be ignored}}
};

float main() : A {
return 1.0;
}

// CHECK: :4:15: warning: cbuffer member initializer ignored since no Vulkan equivalent
// CHECK: :5:16: warning: cbuffer member initializer ignored since no Vulkan equivalent
9 changes: 3 additions & 6 deletions tools/clang/test/CodeGenSPIRV/var.init.tbuffer.hlsl
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// RUN: %dxc -T vs_6_0 -E main -fcgl %s -spirv 2>&1 | FileCheck %s
// RUN: %dxc -T vs_6_0 -E main -verify %s -spirv

tbuffer MyTBuffer {
float a = 1.0;
float4 b = 2.0;
float a = 1.0; //expected-warning{{initializer for a variable in a tbuffer will be ignored}}
float4 b = 2.0; //expected-warning{{initializer for a variable in a tbuffer will be ignored}}
};

float main() : A {
return 1.0;
}

// CHECK: :4:15: warning: tbuffer member initializer ignored since no Vulkan equivalent
// CHECK: :5:16: warning: tbuffer member initializer ignored since no Vulkan equivalent
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %dxc -T vs_6_0 -E main -Wno-vk-ignored-features -fcgl %s -spirv 2>&1 | FileCheck %s
// RUN: %dxc -T vs_6_0 -E main -Wno-vk-ignored-features -Wno-hlsl-buffer-initializer -fcgl %s -spirv 2>&1 | FileCheck %s

cbuffer MyCBuffer {
float a = 1.0;
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/test/HLSL/cpp-errors-hv2015.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -HV 2015 -fsyntax-only -Wno-unused-value -ffreestanding -verify %s
// RUN: %clang_cc1 -Wno-hlsl-buffer-initializer -HV 2015 -fsyntax-only -Wno-unused-value -ffreestanding -verify %s

float f_arr_empty_init[] = { 1, 2, 3 };
float f_arr_empty_pack[] = { 1, 2 ... }; // expected-error {{expansion is unsupported in HLSL}}
Expand Down
12 changes: 6 additions & 6 deletions tools/clang/test/HLSL/cpp-errors.hlsl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -ffreestanding -HV 2018 -verify %s

float f_arr_empty_init[] = { 1, 2, 3 };
float f_arr_empty_init[] = { 1, 2, 3 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
float f_arr_empty_pack[] = { 1, 2 ... }; // expected-error {{expansion is unsupported in HLSL}}

struct s_arr_i_f { int i; float f; };
s_arr_i_f arr_struct_none[] = { }; // TODO: this should fail - see comments in HLSLExternalSource::InitializeInitSequenceForHLSL
s_arr_i_f arr_struct_one[] = { 1, 2 };
s_arr_i_f arr_struct_none[] = { }; // TODO: this should fail - see comments in HLSLExternalSource::InitializeInitSequenceForHLSL /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
s_arr_i_f arr_struct_one[] = { 1, 2 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
s_arr_i_f arr_struct_incomplete[] = { 1, 2, 3 }; // expected-error {{too few elements in vector initialization (expected 4 elements, have 3)}}
s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 };
s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */

int g_int;
typeof(g_int) g_typeof_int; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}} expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}}
typedef int (*fn_int)(int); // expected-error {{pointers are unsupported in HLSL}}
auto g_auto = 3; // auto is now supported in HLSL via type deduction; no error expected
auto g_auto = 3; // auto is now supported in HLSL via type deduction; no error expected /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
__is_signed g_is_signed; // expected-error {{'__is_signed' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
register int g_register; // expected-error {{'register' is a reserved keyword in HLSL}}
__thread int g_thread; // expected-error {{'__thread' is a reserved keyword in HLSL}}
Expand Down Expand Up @@ -321,7 +321,7 @@ struct forward_struct; // this fails in fxc, but we allow it now
struct my_struct_type_decl { int a; } my_struct_var_decl;
struct my_struct_type_decl_parens { int a; } (my_struct_var_decl_parens); // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after struct}}
struct my_struct_type_const { int a; } const my_struct_type_var; // // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after struct}}
struct my_struct_type_init { int a; } my_struct_type_init_one = { 1 }, my_struct_type_init_two = { 2 };
struct my_struct_type_init { int a; } my_struct_type_init_one = { 1 }, my_struct_type_init_two = { 2 }; /* expected-warning 2 {{initializer for a variable in a cbuffer will be ignored}} */
struct my_struct_type_static { int a; } static my_struct_type_static; // expected-error {{expected ';' after struct}} expected-warning {{declaration does not declare anything}}
struct { int my_anon_struct_field; } my_anon_struct_type;

Expand Down
10 changes: 5 additions & 5 deletions tools/clang/test/HLSL/rewriter/cpp-errors_noerr.hlsl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -ffreestanding -verify %s

float f_arr_empty_init[] = { 1, 2, 3 };
float f_arr_empty_init[] = { 1, 2, 3 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
//float f_arr_empty_pack[] = { 1, 2 ... }; // expected-error {{expansion is unsupported in HLSL}}

struct s_arr_i_f { int i; float f; };
s_arr_i_f arr_struct_none[] = { }; // TODO: this should fail - see comments in HLSLExternalSource::InitializeInitSequenceForHLSL
s_arr_i_f arr_struct_one[] = { 1, 2 };
s_arr_i_f arr_struct_none[] = { }; // TODO: this should fail - see comments in HLSLExternalSource::InitializeInitSequenceForHLSL /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
s_arr_i_f arr_struct_one[] = { 1, 2 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */
//s_arr_i_f arr_struct_incomplete[] = { 1, 2, 3 }; // expected-error {{too few elements in vector initialization (expected 4 elements, have 3)}}
s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 };
s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 }; /* expected-warning {{initializer for a variable in a cbuffer will be ignored}} */

int g_int;
//typeof(g_int) g_typeof_int; // expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}} expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}}
Expand Down Expand Up @@ -332,7 +332,7 @@ struct my_struct_5 : my_class, my_interface { };
struct my_struct_type_decl { int a; } my_struct_var_decl;
//struct my_struct_type_decl_parens { int a; } (my_struct_var_decl_parens); // expected-error {{expected ';' after struct}} expected-error {{HLSL requires a type specifier for all declarations}}
//struct my_struct_type_const { int a; } const my_struct_type_var; // // expected-error {{expected ';' after struct}} expected-error {{HLSL requires a type specifier for all declarations}}
struct my_struct_type_init { int a; } my_struct_type_init_one = { 1 }, my_struct_type_init_two = { 2 };
struct my_struct_type_init { int a; } my_struct_type_init_one = { 1 }, my_struct_type_init_two = { 2 }; /* expected-warning 2 {{initializer for a variable in a cbuffer will be ignored}} */
//struct my_struct_type_static { int a; } static my_struct_type_static; // expected-error {{expected ';' after struct}} expected-warning {{declaration does not declare anything}}
struct { int my_anon_struct_field; } my_anon_struct_type;

Expand Down
Loading
Loading