[Sema] Move outputcontrolpoints check to Sema (#6460)

DXIL had a check in the backend for those values.
Moving it to Sema to share it between DXIL and SPIR-V.

Fixes #6387

Signed-off-by: Nathan Gauër <brioche@google.com>
This commit is contained in:
Nathan Gauër 2024-03-29 11:13:31 +01:00 коммит произвёл GitHub
Родитель 773246eddc
Коммит 3aabc019ec
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 88 добавлений и 30 удалений

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

@ -7837,8 +7837,8 @@ def err_hlsl_missing_patch_constant_function : Error<
"patch constant function '%0' must be defined">; "patch constant function '%0' must be defined">;
def err_hlsl_patch_reachability_not_allowed : Error< def err_hlsl_patch_reachability_not_allowed : Error<
"%select{patch constant|entry}0 function '%1' should not be reachable from %select{patch constant|entry}2 function '%3'">; "%select{patch constant|entry}0 function '%1' should not be reachable from %select{patch constant|entry}2 function '%3'">;
def err_hlsl_patch_input_size_mismatch : Error< def err_hlsl_patch_size_mismatch : Error<
"Patch constant function's input patch input should have %0 elements, but has %1.">; "Patch constant function's %0 patch input should have %1 elements, but has %2.">;
def warn_hlsl_structurize_exits_lifetime_markers_conflict : Warning < def warn_hlsl_structurize_exits_lifetime_markers_conflict : Warning <
"structurize-returns skipped function '%0' due to incompatibility with lifetime markers. Use -disable-lifetime-markers to enable structurize-exits on this function.">, "structurize-returns skipped function '%0' due to incompatibility with lifetime markers. Use -disable-lifetime-markers to enable structurize-exits on this function.">,
InGroup< HLSLStructurizeExitsLifetimeMarkersConflict >; InGroup< HLSLStructurizeExitsLifetimeMarkersConflict >;

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

@ -1475,7 +1475,6 @@ void SetPatchConstantFunctionWithAttr(
HLM.HasDxilFunctionProps(EntryFunc.Func), HLM.HasDxilFunctionProps(EntryFunc.Func),
" else AddHLSLFunctionInfo did not save the dxil function props for the " " else AddHLSLFunctionInfo did not save the dxil function props for the "
"HS entry."); "HS entry.");
DxilFunctionProps *HSProps = &HLM.GetDxilFunctionProps(EntryFunc.Func);
HLM.SetPatchConstantFunctionForHS(EntryFunc.Func, patchConstFunc); HLM.SetPatchConstantFunctionForHS(EntryFunc.Func, patchConstFunc);
DXASSERT_NOMSG(patchConstantFunctionPropsMap.count(patchConstFunc)); DXASSERT_NOMSG(patchConstantFunctionPropsMap.count(patchConstFunc));
// Check no inout parameter for patch constant function. // Check no inout parameter for patch constant function.
@ -1491,24 +1490,6 @@ void SetPatchConstantFunctionWithAttr(
Diags.Report(Entry->second.SL, DiagID) << funcName; Diags.Report(Entry->second.SL, DiagID) << funcName;
} }
} }
// Input/Output control point validation.
if (patchConstantFunctionPropsMap.count(patchConstFunc)) {
const DxilFunctionProps &patchProps =
*patchConstantFunctionPropsMap[patchConstFunc];
if (patchProps.ShaderProps.HS.outputControlPoints != 0 &&
patchProps.ShaderProps.HS.outputControlPoints !=
HSProps->ShaderProps.HS.outputControlPoints) {
clang::DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID =
Diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"Patch constant function's output patch input "
"should have %0 elements, but has %1.");
Diags.Report(Entry->second.SL, DiagID)
<< HSProps->ShaderProps.HS.outputControlPoints
<< patchProps.ShaderProps.HS.outputControlPoints;
}
}
} }
void SetPatchConstantFunction( void SetPatchConstantFunction(

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

@ -344,6 +344,25 @@ getFunctionInputPatchCount(const FunctionDecl *function) {
return std::nullopt; return std::nullopt;
} }
std::optional<uint32_t>
getFunctionOutputPatchCount(const FunctionDecl *function) {
for (const auto *param : function->params()) {
if (!hlsl::IsHLSLOutputPatchType(param->getType()))
continue;
return hlsl::GetHLSLOutputPatchCount(param->getType());
}
return std::nullopt;
}
std::optional<uint32_t>
getFunctionOutputControlPointsCount(const FunctionDecl *function) {
if (const auto *Attr = function->getAttr<HLSLOutputControlPointsAttr>()) {
return Attr->getCount();
}
return std::nullopt;
}
} // namespace } // namespace
void hlsl::DiagnoseTranslationUnit(clang::Sema *self) { void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
@ -475,13 +494,28 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
} }
} }
// Input/Output control point validation.
{
auto hullPatchCount = getFunctionInputPatchCount(pPatchFnDecl); auto hullPatchCount = getFunctionInputPatchCount(pPatchFnDecl);
auto functionPatchCount = getFunctionInputPatchCount(FDecl); auto functionPatchCount = getFunctionInputPatchCount(FDecl);
if (hullPatchCount.has_value() && functionPatchCount.has_value() && if (hullPatchCount.has_value() && functionPatchCount.has_value() &&
hullPatchCount.value() != functionPatchCount.value()) { hullPatchCount.value() != functionPatchCount.value()) {
self->Diag(pPatchFnDecl->getSourceRange().getBegin(), self->Diag(pPatchFnDecl->getSourceRange().getBegin(),
diag::err_hlsl_patch_input_size_mismatch) diag::err_hlsl_patch_size_mismatch)
<< functionPatchCount.value() << hullPatchCount.value(); << "input" << functionPatchCount.value()
<< hullPatchCount.value();
}
}
{
auto hullPatchCount = getFunctionOutputPatchCount(pPatchFnDecl);
auto functionPatchCount = getFunctionOutputControlPointsCount(FDecl);
if (hullPatchCount.has_value() && functionPatchCount.has_value() &&
hullPatchCount.value() != functionPatchCount.value()) {
self->Diag(pPatchFnDecl->getSourceRange().getBegin(),
diag::err_hlsl_patch_size_mismatch)
<< "output" << functionPatchCount.value()
<< hullPatchCount.value();
}
} }
} }

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

@ -0,0 +1,22 @@
// RUN: %dxc -T hs_6_0 -E main %s -verify
struct ControlPoint { float4 position : POSITION; };
struct HullPatchOut {
float edge [3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
HullPatchOut HullConst (InputPatch<ControlPoint,3> v, OutputPatch<ControlPoint, 2> outpoints) { /* expected-error{{Patch constant function's output patch input should have 5 elements, but has 2.}} */
return (HullPatchOut)0;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HullConst")]
[outputcontrolpoints(5)]
ControlPoint main(InputPatch<ControlPoint,3> v, uint id : SV_OutputControlPointID) {
return v[id];
}

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

@ -0,0 +1,22 @@
// RUN: %dxc -T hs_6_0 -E main %s -spirv -verify
struct ControlPoint { float4 position : POSITION; };
struct HullPatchOut {
float edge [3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
HullPatchOut HullConst (InputPatch<ControlPoint,3> v, OutputPatch<ControlPoint, 2> outpoints) { /* expected-error{{Patch constant function's output patch input should have 5 elements, but has 2.}} */
return (HullPatchOut)0;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HullConst")]
[outputcontrolpoints(5)]
ControlPoint main(InputPatch<ControlPoint,3> v, uint id : SV_OutputControlPointID) {
return v[id];
}

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

@ -1,7 +1,6 @@
// RUN: %dxc -E main -T hs_6_0 %s | FileCheck %s // RUN: %dxc -E main -T hs_6_0 %s | FileCheck %s
// CHECK-DAG: Patch Constant function HSPerPatchFunc should not have inout param // CHECK-DAG: Patch Constant function HSPerPatchFunc should not have inout param
// CHECK-DAG: Patch constant function's output patch input should have 3 elements, but has 5.
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// SimpleTessellation.hlsl // SimpleTessellation.hlsl
@ -62,7 +61,7 @@ HSPerPatchData HSPerPatchFunc( const InputPatch< PSSceneIn, 12 > points, OutputP
[partitioning("fractional_odd")] [partitioning("fractional_odd")]
[outputtopology("triangle_cw")] [outputtopology("triangle_cw")]
[patchconstantfunc("HSPerPatchFunc")] [patchconstantfunc("HSPerPatchFunc")]
[outputcontrolpoints(3)] [outputcontrolpoints(5)]
HSPerVertexData main(const uint id : SV_OutputControlPointID, HSPerVertexData main(const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 12 > points ) const InputPatch< PSSceneIn, 12 > points )
{ {