From 72f306c8832f30133469965cfc2415e5d547d726 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Thu, 5 Sep 2024 11:09:06 -0700 Subject: [PATCH] [ViewID] build viewid mask for primitive output (#6886) Currently, viewid mask for primitive output is always empty. This change will fix it by treat entry as PC entry and skip output when it is not what is checking. For #6817 --- lib/HLSL/ComputeViewIdStateBuilder.cpp | 28 +++- tools/clang/test/DXC/dumpPSV_MS.hlsl | 4 +- .../sv_viewid/mesh_shader_dependence.hlsl | 143 ++++++++++++++++++ 3 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/hlsl/semantics/sv_viewid/mesh_shader_dependence.hlsl diff --git a/lib/HLSL/ComputeViewIdStateBuilder.cpp b/lib/HLSL/ComputeViewIdStateBuilder.cpp index 4e2b0fd0fd..6299209e71 100644 --- a/lib/HLSL/ComputeViewIdStateBuilder.cpp +++ b/lib/HLSL/ComputeViewIdStateBuilder.cpp @@ -111,7 +111,6 @@ class DxilViewIdStateBuilder { // Contributing instructions per output. std::unordered_map ContributingInstructions[kNumStreams]; - void Clear(); }; @@ -142,7 +141,8 @@ class DxilViewIdStateBuilder { llvm::CallGraphNode *pNode, FunctionSetType &FuncSet); void AnalyzeFunctions(EntryInfo &Entry); - void CollectValuesContributingToOutputs(EntryInfo &Entry); + void CollectValuesContributingToOutputs(EntryInfo &Entry, + bool IsForPatchConstant); void CollectValuesContributingToOutputRec( EntryInfo &Entry, llvm::Value *pContributingValue, InstructionSetType &ContributingInstructions); @@ -190,9 +190,12 @@ void DxilViewIdStateBuilder::Compute() { CallGraph CG = CGA.run(m_pModule->GetModule()); m_Entry.pEntryFunc = m_pModule->GetEntryFunction(); m_PCEntry.pEntryFunc = m_pModule->GetPatchConstantFunction(); + // For MS, use main entry as PC entry to collect primitive outputs. + if (pSM->IsMS()) + m_PCEntry.pEntryFunc = m_pModule->GetEntryFunction(); ComputeReachableFunctionsRec(CG, CG[m_Entry.pEntryFunc], m_Entry.Functions); if (m_PCEntry.pEntryFunc) { - DXASSERT_NOMSG(pSM->IsHS()); + DXASSERT_NOMSG(pSM->IsHS() || pSM->IsMS()); ComputeReachableFunctionsRec(CG, CG[m_PCEntry.pEntryFunc], m_PCEntry.Functions); } @@ -205,10 +208,11 @@ void DxilViewIdStateBuilder::Compute() { } // 4. Collect sets of values contributing to outputs. - CollectValuesContributingToOutputs(m_Entry); - if (m_PCEntry.pEntryFunc) { - CollectValuesContributingToOutputs(m_PCEntry); - } + CollectValuesContributingToOutputs(m_Entry, + /*IsForPatchConstantOrPrimitive*/ false); + if (m_PCEntry.pEntryFunc) + CollectValuesContributingToOutputs(m_PCEntry, + /*IsForPatchConstantOrPrimitive*/ true); // 5. Construct dependency sets. for (unsigned StreamId = 0; StreamId < (pSM->IsGS() ? kNumStreams : 1u); @@ -454,7 +458,7 @@ void DxilViewIdStateBuilder::AnalyzeFunctions(EntryInfo &Entry) { } void DxilViewIdStateBuilder::CollectValuesContributingToOutputs( - EntryInfo &Entry) { + EntryInfo &Entry, bool IsForPatchConstantOrPrimitive) { for (auto *CI : Entry.Outputs) { // CI = call instruction DxilSignature *pDxilSig = nullptr; Value *pContributingValue = nullptr; @@ -462,6 +466,8 @@ void DxilViewIdStateBuilder::CollectValuesContributingToOutputs( int startRow = Semantic::kUndefinedRow, endRow = Semantic::kUndefinedRow; unsigned col = (unsigned)-1; if (DxilInst_StoreOutput SO = DxilInst_StoreOutput(CI)) { + if (IsForPatchConstantOrPrimitive) + continue; pDxilSig = &m_pModule->GetOutputSignature(); pContributingValue = SO.get_value(); GetUnsignedVal(SO.get_outputSigId(), &id); @@ -469,6 +475,8 @@ void DxilViewIdStateBuilder::CollectValuesContributingToOutputs( GetUnsignedVal(SO.get_rowIndex(), (uint32_t *)&startRow); } else if (DxilInst_StoreVertexOutput SVO = DxilInst_StoreVertexOutput(CI)) { + if (IsForPatchConstantOrPrimitive) + continue; pDxilSig = &m_pModule->GetOutputSignature(); pContributingValue = SVO.get_value(); GetUnsignedVal(SVO.get_outputSigId(), &id); @@ -476,6 +484,8 @@ void DxilViewIdStateBuilder::CollectValuesContributingToOutputs( GetUnsignedVal(SVO.get_rowIndex(), (uint32_t *)&startRow); } else if (DxilInst_StorePrimitiveOutput SPO = DxilInst_StorePrimitiveOutput(CI)) { + if (!IsForPatchConstantOrPrimitive) + continue; pDxilSig = &m_pModule->GetPatchConstOrPrimSignature(); pContributingValue = SPO.get_value(); GetUnsignedVal(SPO.get_outputSigId(), &id); @@ -483,6 +493,8 @@ void DxilViewIdStateBuilder::CollectValuesContributingToOutputs( GetUnsignedVal(SPO.get_rowIndex(), (uint32_t *)&startRow); } else if (DxilInst_StorePatchConstant SPC = DxilInst_StorePatchConstant(CI)) { + if (!IsForPatchConstantOrPrimitive) + continue; pDxilSig = &m_pModule->GetPatchConstOrPrimSignature(); pContributingValue = SPC.get_value(); GetUnsignedVal(SPC.get_outputSigID(), &id); diff --git a/tools/clang/test/DXC/dumpPSV_MS.hlsl b/tools/clang/test/DXC/dumpPSV_MS.hlsl index 6e8db9eb1e..ec89870dfc 100644 --- a/tools/clang/test/DXC/dumpPSV_MS.hlsl +++ b/tools/clang/test/DXC/dumpPSV_MS.hlsl @@ -126,7 +126,7 @@ // CHECK-NEXT: Outputs affected by ViewID as a bitmask for stream 0: // CHECK-NEXT: ViewID influencing Outputs[0] : 0 1 2 3 4 8 12 16 // CHECK-NEXT: PCOutputs affected by ViewID as a bitmask: -// CHECK-NEXT: ViewID influencing PCOutputs : None +// CHECK-NEXT: ViewID influencing PCOutputs : 3 // CHECK-NEXT: Outputs affected by inputs as a table of bitmasks for stream 0: // CHECK-NEXT: Inputs contributing to computation of Outputs[0]: None @@ -189,7 +189,7 @@ void main( op.normal = mpl.normal; op.malnor = gsMem[tig / 3 + 1]; op.alnorm = mpl.alnorm; - op.ormaln = mpl.ormaln; + op.ormaln = mpl.ormaln + vid; op.layer[0] = mpl.layer[0]; op.layer[1] = mpl.layer[1]; op.layer[2] = mpl.layer[2]; diff --git a/tools/clang/test/HLSLFileCheck/hlsl/semantics/sv_viewid/mesh_shader_dependence.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/semantics/sv_viewid/mesh_shader_dependence.hlsl new file mode 100644 index 0000000000..97f1d95f4a --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/hlsl/semantics/sv_viewid/mesh_shader_dependence.hlsl @@ -0,0 +1,143 @@ +// RUN: %dxc -E main -T ms_6_5 %s | FileCheck %s + +// RUN: %dxc -E main -T ms_6_5 -DVIEWID %s | FileCheck %s -check-prefix=VIEWID + +// RUN: %dxc -E main -T ms_6_5 -DVIEWID -DVIEWID_A %s | FileCheck %s -check-prefix=VIEWID_A + +// RUN: %dxc -E main -T ms_6_5 -DVIEWID -DVIEWID_B %s | FileCheck %s -check-prefix=VIEWID_B + +// RUN: %dxc -E main -T ms_6_5 -DVIEWID -DVIEWID_C %s | FileCheck %s -check-prefix=VIEWID_C + +// RUN: %dxc -E main -T ms_6_5 -DVIEWID -DVIEWID_D %s | FileCheck %s -check-prefix=VIEWID_D + + +// CHECK:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// CHECK:; Outputs dependent on ViewId: { } +// CHECK:; Primitive Outputs dependent on ViewId: { } +// CHECK:; Inputs contributing to computation of Outputs: +// CHECK:; Inputs contributing to computation of Primitive Outputs: + +// VIEWID:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// VIEWID:; Outputs dependent on ViewId: { } +// VIEWID:; Primitive Outputs dependent on ViewId: { } +// VIEWID:; Inputs contributing to computation of Outputs: +// VIEWID:; Inputs contributing to computation of Primitive Outputs: + +// VIEWID_A:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// VIEWID_A:; Outputs dependent on ViewId: { 12 } +// VIEWID_A:; Primitive Outputs dependent on ViewId: { } +// VIEWID_A:; Inputs contributing to computation of Outputs: +// VIEWID_A:; Inputs contributing to computation of Primitive Outputs: + + +// VIEWID_B:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// VIEWID_B:; Outputs dependent on ViewId: { } +// VIEWID_B:; Primitive Outputs dependent on ViewId: { 0, 1, 2, 3, 4, 8, 12, 16, 20, 24 } +// VIEWID_B:; Inputs contributing to computation of Outputs: +// VIEWID_B:; Inputs contributing to computation of Primitive Outputs: + + +// VIEWID_C:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// VIEWID_C:; Outputs dependent on ViewId: { 8 } +// VIEWID_C:; Primitive Outputs dependent on ViewId: { } +// VIEWID_C:; Inputs contributing to computation of Outputs: +// VIEWID_C:; Inputs contributing to computation of Primitive Outputs: + + +// VIEWID_D:; Number of inputs: 0, outputs: 17, primitive outputs: 25 +// VIEWID_D:; Outputs dependent on ViewId: { } +// VIEWID_D:; Primitive Outputs dependent on ViewId: { 24 } +// VIEWID_D:; Inputs contributing to computation of Outputs: +// VIEWID_D:; Inputs contributing to computation of Primitive Outputs: + +#define MAX_VERT 32 +#define MAX_PRIM 16 +#define NUM_THREADS 32 +struct MeshPerVertex { + float4 position : SV_Position; + float color[4] : COLOR; +}; + +struct MeshPerPrimitive { + float normal : NORMAL; + float malnor : MALNOR; + float alnorm : ALNORM; + float ormaln : ORMALN; + int layer[6] : LAYER; + bool cullPrimitive : SV_CullPrimitive; +}; + +struct MeshPayload { + float normal; + float malnor; + float alnorm; + float ormaln; + int layer[6]; +}; + +groupshared float gsMem[MAX_PRIM]; + +[numthreads(NUM_THREADS, 1, 1)] +[outputtopology("triangle")] +void main( + out indices uint3 primIndices[MAX_PRIM], + out vertices MeshPerVertex verts[MAX_VERT], + out primitives MeshPerPrimitive prims[MAX_PRIM], + in payload MeshPayload mpl, + in uint tig : SV_GroupIndex +#ifdef VIEWID + ,in uint vid : SV_ViewID +#endif + ) +{ + SetMeshOutputCounts(MAX_VERT, MAX_PRIM); + MeshPerVertex ov; + if (tig % 2) { + ov.position = float4(4.0,5.0,6.0,7.0); + ov.color[0] = 4.0; + ov.color[1] = 5.0; +#ifdef VIEWID_A + ov.color[2] = vid; +#else + ov.color[2] = 6.0; +#endif + ov.color[3] = 7.0; + } else { + ov.position = float4(14.0,15.0,16.0,17.0); + ov.color[0] = 14.0; +#ifdef VIEWID_C + ov.color[1] = vid; +#else + ov.color[1] = 15.0; +#endif + ov.color[2] = 16.0; + ov.color[3] = 17.0; + } + +#ifdef VIEWID_B + if (vid % 3) { +#else + if (tig % 3) { +#endif + primIndices[tig / 3] = uint3(tig, tig + 1, tig + 2); + MeshPerPrimitive op; + op.normal = mpl.normal; + op.malnor = gsMem[tig / 3 + 1]; + op.alnorm = mpl.alnorm; + op.ormaln = mpl.ormaln; + op.layer[0] = mpl.layer[0]; + op.layer[1] = mpl.layer[1]; + op.layer[2] = mpl.layer[2]; + op.layer[3] = mpl.layer[3]; + op.layer[4] = mpl.layer[4]; +#ifdef VIEWID_D + op.layer[5] = mpl.layer[5] + vid; +#else + op.layer[5] = mpl.layer[5]; +#endif + op.cullPrimitive = false; + gsMem[tig / 3] = op.normal; + prims[tig / 3] = op; + } + verts[tig] = ov; +}