[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:
Родитель
773246eddc
Коммит
3aabc019ec
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче