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
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -13231,6 +13231,9 @@ def err_hlsl_semantic_indexing_not_supported
def err_hlsl_init_priority_unsupported : Error<
"initializer priorities are not supported in HLSL">;
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
: Error<"semantic %0 is unsupported in %2 shaders as %1, requires one of "
"the following: %3">;

def warn_hlsl_user_defined_type_missing_member: Warning<"binding type '%select{t|u|b|s|c}0' only applies to types containing %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric types}0">, InGroup<LegacyConstantRegisterBinding>;
def err_hlsl_binding_type_mismatch: Error<"binding type '%select{t|u|b|s|c}0' only applies to %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric variables in the global scope}0">;
Expand Down
22 changes: 19 additions & 3 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,6 @@ class SemaHLSL : public SemaBase {
void CheckEntryPoint(FunctionDecl *FD);
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc);
void DiagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);

QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,
QualType LHSType, QualType RHSType,
Expand Down Expand Up @@ -244,6 +241,17 @@ class SemaHLSL : public SemaBase {
std::optional<uint32_t> Index;
};

enum IOType {
In = 0b01,
Out = 0b10,
InOut = 0b11,
};

struct SemanticStageInfo {
llvm::Triple::EnvironmentType Stage;
IOType AllowedIOTypesMask;
};

private:
void collectResourceBindingsOnVarDecl(VarDecl *D);
void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
Expand All @@ -269,6 +277,14 @@ class SemaHLSL : public SemaBase {

void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);

void diagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);

void diagnoseSemanticStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
std::initializer_list<SemanticStageInfo> AllowedStages);

uint32_t getNextImplicitBindingOrderID() {
return ImplicitBindingNextOrderID++;
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,11 @@ void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
}
}

if (SemanticName == "SV_TARGET") {
emitUserSemanticStore(B, Source, Decl, Semantic, Index);
return;
}

llvm_unreachable(
"Store hasn't been implemented yet for this system semantic. FIXME");
}
Expand Down
76 changes: 68 additions & 8 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -873,14 +873,14 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
case llvm::Triple::Miss:
case llvm::Triple::Callable:
if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
DiagnoseAttrStageMismatch(NT, ST,
diagnoseAttrStageMismatch(NT, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
FD->setInvalidDecl();
}
if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
DiagnoseAttrStageMismatch(WS, ST,
diagnoseAttrStageMismatch(WS, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
Expand Down Expand Up @@ -954,7 +954,8 @@ void SemaHLSL::checkSemanticAnnotation(
SemanticName == "SV_GROUPID") {

if (ST != llvm::Triple::Compute)
DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute});
diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
{{llvm::Triple::Compute, IOType::In}});

if (SemanticAttr->getSemanticIndex() != 0) {
std::string PrettyName =
Expand All @@ -969,10 +970,15 @@ void SemaHLSL::checkSemanticAnnotation(
if (SemanticName == "SV_POSITION") {
// SV_Position can be an input or output in vertex shaders,
// but only an input in pixel shaders.
if (ST == llvm::Triple::Vertex || (ST == llvm::Triple::Pixel && IsInput))
return;
DiagnoseAttrStageMismatch(SemanticAttr, ST,
{llvm::Triple::Pixel, llvm::Triple::Vertex});
diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
{{llvm::Triple::Vertex, IOType::InOut},
{llvm::Triple::Pixel, IOType::In}});
return;
}

if (SemanticName == "SV_TARGET") {
diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
{{llvm::Triple::Pixel, IOType::Out}});
return;
}

Expand All @@ -982,7 +988,7 @@ void SemaHLSL::checkSemanticAnnotation(
llvm_unreachable("Unknown SemanticAttr");
}

void SemaHLSL::DiagnoseAttrStageMismatch(
void SemaHLSL::diagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
SmallVector<StringRef, 8> StageStrings;
Expand All @@ -996,6 +1002,50 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
<< (AllowedStages.size() != 1) << join(StageStrings, ", ");
}

void SemaHLSL::diagnoseSemanticStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
std::initializer_list<SemanticStageInfo> Allowed) {

for (auto &Case : Allowed) {
if (Case.Stage != Stage)
continue;

if (IsInput && Case.AllowedIOTypesMask & IOType::In)
return;
if (!IsInput && Case.AllowedIOTypesMask & IOType::Out)
return;

SmallVector<std::string, 8> ValidCases;
llvm::transform(
Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {
SmallVector<std::string, 2> ValidType;
if (Case.AllowedIOTypesMask & IOType::In)
ValidType.push_back("input");
if (Case.AllowedIOTypesMask & IOType::Out)
ValidType.push_back("output");
return std::string(
HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
" " + join(ValidType, "/");
});
Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
<< A->getAttrName() << (IsInput ? "input" : "output")
<< llvm::Triple::getEnvironmentTypeName(Case.Stage)
<< join(ValidCases, ", ");
return;
}

SmallVector<StringRef, 8> StageStrings;
llvm::transform(
Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
return StringRef(
HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
});

Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
<< A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
<< (Allowed.size() != 1) << join(StageStrings, ", ");
}

template <CastKind Kind>
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
if (const auto *VTy = Ty->getAs<VectorType>())
Expand Down Expand Up @@ -1797,6 +1847,16 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
return;
}

if (SemanticName == "SV_TARGET") {
const auto *VT = ValueType->getAs<VectorType>();
if (!ValueType->hasFloatingRepresentation() ||
(VT && VT->getNumElements() > 4))
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
<< AL << "float/float1/float2/float3/float4";
D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
return;
}

Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
}

Expand Down
19 changes: 19 additions & 0 deletions clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL

// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]

// CHECK: define void @main() {{.*}} {
float4 main(float4 p : SV_Position) : SV_Target {
// CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#]])
// CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16

// CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
// CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
return p;
}

// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 0}
// | `-> Location index
// `-> SPIR-V decoration 'Location'
2 changes: 1 addition & 1 deletion clang/test/SemaHLSL/Semantics/position.ps.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s

float4 main(float4 a : A) : SV_Position {
// expected-error@-1 {{attribute 'SV_Position' is unsupported in 'pixel' shaders, requires one of the following: pixel, vertex}}
// expected-error@-1 {{semantic 'SV_Position' is unsupported in pixel shaders as output, requires one of the following: vertex input/output, pixel input}}
return a;
}
7 changes: 7 additions & 0 deletions clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -finclude-default-header -x hlsl -verify -o - %s
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s

float4 main(float4 a : SV_Target) : A {
// expected-error@-1 {{semantic 'SV_Target' is unsupported in pixel shaders as input, requires one of the following: pixel out}}
return a;
}
8 changes: 8 additions & 0 deletions clang/test/SemaHLSL/Semantics/target.vs.input.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -finclude-default-header -x hlsl -verify -o - %s
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-vertex -finclude-default-header -x hlsl -verify -o - %s

float4 main(float4 a : SV_Target) : A {
// expected-error@-1 {{attribute 'SV_Target' is unsupported in 'vertex' shaders, requires pixel}}
return a;
}

7 changes: 7 additions & 0 deletions clang/test/SemaHLSL/Semantics/target.vs.output.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -finclude-default-header -x hlsl -verify -o - %s
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-vertex -finclude-default-header -x hlsl -verify -o - %s

float4 main(float4 a : SV_Position) : SV_Target {
// expected-error@-1 {{attribute 'SV_Target' is unsupported in 'vertex' shaders, requires pixel}}
return a;
}
33 changes: 33 additions & 0 deletions llvm/test/CodeGen/SPIRV/semantics/target.ps.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: OpDecorate %[[#INPUT:]] BuiltIn FragCoord
; CHECK-DAG: OpDecorate %[[#OUTPUT:]] Location 0

; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
; CHECK-DAG: %[[#v4:]] = OpTypeVector %[[#float]] 4
; CHECK-DAG: %[[#ptr_i:]] = OpTypePointer Input %[[#v4]]
; CHECK-DAG: %[[#ptr_o:]] = OpTypePointer Output %[[#v4]]

; CHECK-DAG: %[[#INPUT]] = OpVariable %[[#ptr_i]] Input
; CHECK-DAG: %[[#OUTPUT]] = OpVariable %[[#ptr_o]] Output

@SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
@SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations !2

define void @main() #1 {
entry:
%0 = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
store <4 x float> %0, ptr addrspace(8) @SV_Target0, align 16
ret void

; CHECK: %[[#TMP:]] = OpLoad %[[#v4]] %[[#INPUT]] Aligned 16
; CHECK: OpStore %[[#OUTPUT]] %[[#TMP]] Aligned 16
}

!0 = !{!1}
!1 = !{i32 11, i32 15}
!2 = !{!3}
!3 = !{i32 30, i32 0}


Loading