From 686608cbd0b8830d020e6917e6c2081e581efff2 Mon Sep 17 00:00:00 2001 From: xazhang Date: Mon, 23 Oct 2023 15:02:36 -0400 Subject: [PATCH] lgc: extend InputAssemlyState::enableMultiView to an enum Vulkan view index is used to set RT layer when multiview extension is enabled. But HLSL SV_ViewID stands for a combination of viewport index, RT layer and view index. To support HLSL and future Vulkan extension, this bool enableMultiView is expandede as an enum which is one of: - Disabled - Simple: Current Vulkan behavior, i.e. RT layer set to view index, viewport index set by shader - PerView: both RT layer and viewport index set by shader (with shader output defaulting to 0), offset by a base that's taken from the ViewId userdata There is also key change in RegisterMetadataBuilder because even the viewport index is written when multiView is PerView mode, vertex reuse can still be enabled because the viewport index is uniform. --- lgc/builder/ImageBuilder.cpp | 10 ++-- lgc/builder/InOutBuilder.cpp | 8 ++- .../lgc/patch/PatchInOutImportExport.h | 2 +- lgc/interface/lgc/Pipeline.h | 10 +++- lgc/patch/Gfx6ConfigBuilder.cpp | 6 +- lgc/patch/Gfx9ConfigBuilder.cpp | 6 +- lgc/patch/MeshTaskShader.cpp | 53 ++++++++++++----- lgc/patch/PatchCopyShader.cpp | 2 +- lgc/patch/PatchEntryPointMutate.cpp | 6 +- lgc/patch/PatchInOutImportExport.cpp | 59 +++++++++++++------ lgc/patch/PatchResourceCollect.cpp | 5 +- lgc/patch/RegisterMetadataBuilder.cpp | 13 +++- llpc/context/llpcGraphicsContext.cpp | 2 +- 13 files changed, 128 insertions(+), 54 deletions(-) diff --git a/lgc/builder/ImageBuilder.cpp b/lgc/builder/ImageBuilder.cpp index 91eb11cb7f..a0837f5053 100644 --- a/lgc/builder/ImageBuilder.cpp +++ b/lgc/builder/ImageBuilder.cpp @@ -1964,7 +1964,7 @@ Value *BuilderImpl::patchCubeDescriptor(Value *desc, unsigned dim) { Value *BuilderImpl::handleFragCoordViewIndex(Value *coord, unsigned flags, unsigned &dim) { bool useViewIndex = false; if (flags & ImageFlagCheckMultiView) { - if (getPipelineState()->getInputAssemblyState().enableMultiView) { + if (getPipelineState()->getInputAssemblyState().multiView != MultiViewModeDisable) { useViewIndex = true; dim = Dim2DArray; unsigned coordCount = cast(coord->getType())->getNumElements(); @@ -2031,9 +2031,11 @@ Value *BuilderImpl::handleFragCoordViewIndex(Value *coord, unsigned flags, unsig std::string callName = lgcName::InputImportBuiltIn; Type *builtInTy = getInt32Ty(); addTypeMangling(builtInTy, {}, callName); - Value *viewIndex = CreateNamedCall(callName, builtInTy, getInt32(BuiltInViewIndex), {}); - viewIndex->setName("ViewIndex"); - coord = CreateInsertElement(coord, viewIndex, 2); + Value *rtLayer = CreateNamedCall(callName, builtInTy, getInt32(BuiltInViewIndex), {}); + if (getPipelineState()->getInputAssemblyState().multiView == MultiViewModePerView) + rtLayer = CreateLShr(rtLayer, getInt32(8)); // RT layer id is in the high 24 bits of view index. + rtLayer->setName("Layer"); + coord = CreateInsertElement(coord, rtLayer, 2); } return coord; diff --git a/lgc/builder/InOutBuilder.cpp b/lgc/builder/InOutBuilder.cpp index fb83c43331..46f5452b96 100644 --- a/lgc/builder/InOutBuilder.cpp +++ b/lgc/builder/InOutBuilder.cpp @@ -837,7 +837,11 @@ Value *BuilderImpl::CreateReadBaryCoord(BuiltInKind builtIn, InOutInfo inputInfo Value *BuilderImpl::CreateReadBuiltInInput(BuiltInKind builtIn, InOutInfo inputInfo, Value *vertexIndex, Value *index, const Twine &instName) { assert(isBuiltInInput(builtIn)); - return readBuiltIn(false, builtIn, inputInfo, vertexIndex, index, instName); + Value *builtInVal = readBuiltIn(false, builtIn, inputInfo, vertexIndex, index, instName); + if (builtIn == BuiltInViewIndex) + // View index can only use bit[3:0] of view id register. + builtInVal = CreateAnd(builtInVal, getInt32(0xF)); + return builtInVal; } // ===================================================================================================================== @@ -1306,7 +1310,7 @@ Value *BuilderImpl::readVsBuiltIn(BuiltInKind builtIn, const Twine &instName) { case BuiltInInstanceIndex: return ShaderInputs::getInstanceIndex(builder, *getLgcContext()); case BuiltInViewIndex: - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) return ShaderInputs::getSpecialUserData(UserDataMapping::ViewId, builder); return builder.getInt32(0); case BuiltInVertexId: diff --git a/lgc/include/lgc/patch/PatchInOutImportExport.h b/lgc/include/lgc/patch/PatchInOutImportExport.h index 38bad91166..63dd23daa8 100644 --- a/lgc/include/lgc/patch/PatchInOutImportExport.h +++ b/lgc/include/lgc/patch/PatchInOutImportExport.h @@ -218,7 +218,7 @@ class PatchInOutImportExport : public Patch, public llvm::PassInfoMixin void ConfigBuilder::buildVsRegConfig(ShaderStage shaderSta cullDistanceCount = builtInUsage.gs.cullDistance; } + // In this mode, API shader may not export viewport index but LGC does so. + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) + useViewportIndex = true; + SET_REG_FIELD(&config->vsRegs, VGT_PRIMITIVEID_EN, PRIMITIVEID_EN, usePrimitiveId); SET_REG_FIELD(&config->vsRegs, SPI_VS_OUT_CONFIG, VS_EXPORT_COUNT, resUsage->inOutUsage.expCount - 1); setUsesViewportArrayIndex(useViewportIndex); @@ -472,7 +476,7 @@ template void ConfigBuilder::buildVsRegConfig(ShaderStage shaderSta SET_REG_FIELD(&config->vsRegs, VGT_VERTEX_REUSE_BLOCK_CNTL, VTX_REUSE_DEPTH, 14); - useLayer = useLayer || m_pipelineState->getInputAssemblyState().enableMultiView; + useLayer = useLayer || m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; bool miscExport = usePointSize || useLayer || useViewportIndex || useEdgeFlag; if (miscExport) { diff --git a/lgc/patch/Gfx9ConfigBuilder.cpp b/lgc/patch/Gfx9ConfigBuilder.cpp index 4f03ac2ce4..bac7b9442d 100644 --- a/lgc/patch/Gfx9ConfigBuilder.cpp +++ b/lgc/patch/Gfx9ConfigBuilder.cpp @@ -1864,7 +1864,7 @@ template void ConfigBuilder::buildMeshRegConfig(ShaderStage shaderS SET_REG_FIELD(&config->meshRegs, GE_NGG_SUBGRP_CNTL, PRIM_AMP_FACTOR, calcFactor.primAmpFactor); SET_REG_FIELD(&config->meshRegs, GE_NGG_SUBGRP_CNTL, THDS_PER_SUBGRP, calcFactor.primAmpFactor); - const bool enableMultiView = m_pipelineState->getInputAssemblyState().enableMultiView; + const bool enableMultiView = m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; bool hasPrimitivePayload = builtInUsage.layer || builtInUsage.viewportIndex || builtInUsage.primitiveShadingRate || enableMultiView; if (m_gfxIp.major < 11) @@ -2166,7 +2166,9 @@ template void ConfigBuilder::setupPaSpecificRegisters(T *config) { expCount = resUsage->inOutUsage.expCount; } - useLayer = useLayer || m_pipelineState->getInputAssemblyState().enableMultiView; + useLayer = useLayer || m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) + useViewportIndex = true; if (usePrimitiveId) { SET_REG_FIELD(config, VGT_PRIMITIVEID_EN, PRIMITIVEID_EN, true); diff --git a/lgc/patch/MeshTaskShader.cpp b/lgc/patch/MeshTaskShader.cpp index 93ba2bb0b4..f98adc167a 100644 --- a/lgc/patch/MeshTaskShader.cpp +++ b/lgc/patch/MeshTaskShader.cpp @@ -1242,7 +1242,7 @@ void MeshTaskShader::lowerGetMeshBuiltinInput(GetMeshBuiltinInputOp &getMeshBuil break; } case BuiltInViewIndex: { - if (m_pipelineState->getInputAssemblyState().enableMultiView) { + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) { auto &entryArgIdxs = m_pipelineState->getShaderInterfaceData(ShaderStageMesh)->entryArgIdxs.mesh; input = getFunctionArgument(entryPoint, entryArgIdxs.viewIndex); } else { @@ -1754,23 +1754,46 @@ void MeshTaskShader::exportPrimitive() { if (builtInUsage.layer) layer = readMeshBuiltInFromLds(BuiltInLayer); - Value *viewIndex = nullptr; - const bool enableMultiView = m_pipelineState->getInputAssemblyState().enableMultiView; + Value *viewportIndex = nullptr; + if (builtInUsage.viewportIndex) + viewportIndex = readMeshBuiltInFromLds(BuiltInViewportIndex); + + Value *layerForFs = layer; + Value *viewportIndexForFs = viewportIndex; + + const bool enableMultiView = m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; if (enableMultiView) { auto entryPoint = m_builder.GetInsertBlock()->getParent(); const auto entryArgIdxs = m_pipelineState->getShaderInterfaceData(ShaderStageMesh)->entryArgIdxs.mesh; - viewIndex = getFunctionArgument(entryPoint, entryArgIdxs.viewIndex); + Value *viewId = getFunctionArgument(entryPoint, entryArgIdxs.viewIndex); + + // RT layer id is view id in simple mode (view index only). + Value *layerFromViewId = viewId; + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) { + // RT layer id is in the high 24 bits of view id in per-view mode. + layerFromViewId = m_builder.CreateLShr(viewId, m_builder.getInt32(8)); + if (layer) + layerFromViewId = m_builder.CreateAdd(layerFromViewId, layer); + // Viewport index is in [7:4] of view id. + Value *viewportIndexFromViewId = + m_builder.CreateAnd(m_builder.CreateLShr(viewId, m_builder.getInt32(4)), m_builder.getInt32(0xF)); + if (viewportIndex) + viewportIndexFromViewId = m_builder.CreateAdd(viewportIndexFromViewId, viewportIndex); + viewportIndex = viewportIndexFromViewId; + } + + layer = layerFromViewId; } - if (enableMultiView || builtInUsage.layer) { + if (layer) { // [19:17] = RT slice index (on GFX11, [12:0] = RT slice index) // When multi-view is enabled, the input view index is treated as the output layer. Value *layerMaskAndShift = nullptr; if (m_gfxIp.major < 11) { - layerMaskAndShift = m_builder.CreateAnd(enableMultiView ? viewIndex : layer, 0x7); + layerMaskAndShift = m_builder.CreateAnd(layer, 0x7); layerMaskAndShift = m_builder.CreateShl(layerMaskAndShift, 17); } else { - layerMaskAndShift = m_builder.CreateAnd(enableMultiView ? viewIndex : layer, 0x1FFF); + layerMaskAndShift = m_builder.CreateAnd(layer, 0x1FFF); } if (primitivePayload) primitivePayload = m_builder.CreateOr(primitivePayload, layerMaskAndShift); @@ -1778,10 +1801,8 @@ void MeshTaskShader::exportPrimitive() { primitivePayload = layerMaskAndShift; } - Value *viewportIndex = nullptr; - if (builtInUsage.viewportIndex) { + if (viewportIndex) { // [23:20] = Viewport index - viewportIndex = readMeshBuiltInFromLds(BuiltInViewportIndex); auto viewportIndexMaskAndShift = m_builder.CreateAnd(viewportIndex, 0xF); viewportIndexMaskAndShift = m_builder.CreateShl(viewportIndexMaskAndShift, 20); if (primitivePayload) @@ -1853,7 +1874,7 @@ void MeshTaskShader::exportPrimitive() { if (fsBuiltInUsage.layer) { // NOTE: In such case, mesh shader doesn't export layer while fragment shader expects to read it. We // export 0 to fragment shader, which is required by the spec. - layer = m_builder.getInt32(0); + layerForFs = m_builder.getInt32(0); exportLayer = true; } } @@ -1861,9 +1882,9 @@ void MeshTaskShader::exportPrimitive() { if (exportLayer) { if (inOutUsage.mesh.perPrimitiveBuiltInExportLocs.count(BuiltInLayer) > 0) { - assert(layer); + assert(layerForFs); const unsigned exportLoc = inOutUsage.mesh.perPrimitiveBuiltInExportLocs[BuiltInLayer]; - primAttrExports.push_back({startLoc + exportLoc, layer}); + primAttrExports.push_back({startLoc + exportLoc, layerForFs}); ++inOutUsage.primExpCount; } } @@ -1878,7 +1899,7 @@ void MeshTaskShader::exportPrimitive() { if (fsBuiltInUsage.viewportIndex) { // NOTE: In such case, mesh shader doesn't export viewport index while fragment shader expects to read it. We // export 0 to fragment shader, which is required by spec. - viewportIndex = m_builder.getInt32(0); + viewportIndexForFs = m_builder.getInt32(0); exportViewportIndex = true; } } @@ -1886,9 +1907,9 @@ void MeshTaskShader::exportPrimitive() { if (exportViewportIndex) { if (inOutUsage.mesh.perPrimitiveBuiltInExportLocs.count(BuiltInViewportIndex) > 0) { - assert(viewportIndex); + assert(viewportIndexForFs); const unsigned exportLoc = inOutUsage.mesh.perPrimitiveBuiltInExportLocs[BuiltInViewportIndex]; - primAttrExports.push_back({startLoc + exportLoc, viewportIndex}); + primAttrExports.push_back({startLoc + exportLoc, viewportIndexForFs}); ++inOutUsage.primExpCount; } } diff --git a/lgc/patch/PatchCopyShader.cpp b/lgc/patch/PatchCopyShader.cpp index 1a124c68e9..6c4646b02c 100644 --- a/lgc/patch/PatchCopyShader.cpp +++ b/lgc/patch/PatchCopyShader.cpp @@ -511,7 +511,7 @@ void PatchCopyShader::exportOutput(unsigned streamId, BuilderBase &builder) { if (builtInUsage.viewportIndex) builtInPairs.push_back(std::make_pair(BuiltInViewportIndex, builder.getInt32Ty())); - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) builtInPairs.push_back(std::make_pair(BuiltInViewIndex, builder.getInt32Ty())); if (builtInUsage.primitiveShadingRate) diff --git a/lgc/patch/PatchEntryPointMutate.cpp b/lgc/patch/PatchEntryPointMutate.cpp index a14100f8fa..ebdd870fa2 100644 --- a/lgc/patch/PatchEntryPointMutate.cpp +++ b/lgc/patch/PatchEntryPointMutate.cpp @@ -1459,7 +1459,7 @@ void PatchEntryPointMutate::addSpecialUserDataArgs(SmallVectorImpl // NOTE: The user data to emulate gl_ViewIndex is somewhat common. To make it consistent for GFX9 // merged shader, we place it prior to any other special user data. - if (m_pipelineState->getInputAssemblyState().enableMultiView) { + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) { unsigned *argIdx = nullptr; auto userDataValue = UserDataMapping::ViewId; switch (m_shaderStage) { @@ -1571,7 +1571,7 @@ void PatchEntryPointMutate::addSpecialUserDataArgs(SmallVectorImpl specialUserDataArgs.push_back(UserDataArg(builder.getInt32Ty(), "drawIndex", UserDataMapping::DrawIndex, &intfData->entryArgIdxs.mesh.drawIndex)); } - if (m_pipelineState->getInputAssemblyState().enableMultiView) { + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) { specialUserDataArgs.push_back( UserDataArg(builder.getInt32Ty(), "viewId", UserDataMapping::ViewId, &intfData->entryArgIdxs.mesh.viewIndex)); } @@ -1587,7 +1587,7 @@ void PatchEntryPointMutate::addSpecialUserDataArgs(SmallVectorImpl &intfData->entryArgIdxs.mesh.pipeStatsBuf)); } } else if (m_shaderStage == ShaderStageFragment) { - if (m_pipelineState->getInputAssemblyState().enableMultiView && + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable && m_pipelineState->getShaderResourceUsage(ShaderStageFragment)->builtInUsage.fs.viewIndex) { // NOTE: Only add special user data of view index when multi-view is enabled and gl_ViewIndex is used in fragment // shader. diff --git a/lgc/patch/PatchInOutImportExport.cpp b/lgc/patch/PatchInOutImportExport.cpp index ac9abb92b2..dfe9399b06 100644 --- a/lgc/patch/PatchInOutImportExport.cpp +++ b/lgc/patch/PatchInOutImportExport.cpp @@ -1090,7 +1090,7 @@ void PatchInOutImportExport::visitCallInst(CallInst &callInst) { // NOTE: Implicitly store the value of view index to GS-VS ring buffer for raster stream if multi-view is // enabled. Copy shader will read the value from GS-VS ring and export it to vertex position data. - if (m_pipelineState->getInputAssemblyState().enableMultiView) { + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) { auto resUsage = m_pipelineState->getShaderResourceUsage(ShaderStageGeometry); auto rasterStream = m_pipelineState->getRasterizerState().rasterStream; @@ -1252,7 +1252,7 @@ void PatchInOutImportExport::visitReturnInst(ReturnInst &retInst) { cullDistanceCount = builtInUsage.cullDistance; } - const auto enableMultiView = m_pipelineState->getInputAssemblyState().enableMultiView; + const auto enableMultiView = m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; if (enableMultiView) { if (m_shaderStage == ShaderStageVertex) { auto &entryArgIdxs = m_pipelineState->getShaderInterfaceData(ShaderStageVertex)->entryArgIdxs.vs; @@ -1445,23 +1445,46 @@ void PatchInOutImportExport::visitReturnInst(ReturnInst &retInst) { // Export gl_Layer and gl_ViewportIndex before entry-point returns if (m_gfxIp.major >= 9 && (useLayer || useViewportIndex || enableMultiView)) { + Value *viewportIndex = nullptr; + Value *layer = nullptr; Value *viewportIndexAndLayer = ConstantInt::get(Type::getInt32Ty(*m_context), 0); + BuilderBase builder(*m_context); + builder.SetInsertPoint(insertPos); + + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) { + assert(m_viewIndex); + // Get viewportIndex from viewIndex. + viewportIndex = builder.CreateAnd(builder.CreateLShr(m_viewIndex, builder.getInt32(4)), builder.getInt32(0xF)); + // Get layer from viewIndex + layer = builder.CreateLShr(m_viewIndex, builder.getInt32(8)); + if (useLayer) + layer = builder.CreateAdd(m_layer, layer); + } else if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModeSimple) { + assert(m_viewIndex); + layer = m_viewIndex; + } else if (useLayer) { + assert(!enableMultiView && m_layer); + layer = m_layer; + } + if (useViewportIndex) { assert(m_viewportIndex); - viewportIndexAndLayer = BinaryOperator::CreateShl( - m_viewportIndex, ConstantInt::get(Type::getInt32Ty(*m_context), 16), "", insertPos); + if (viewportIndex) + viewportIndex = builder.CreateAdd(m_viewportIndex, viewportIndex); + else + viewportIndex = m_viewportIndex; } - if (enableMultiView) { - assert(m_viewIndex); - viewportIndexAndLayer = BinaryOperator::CreateOr(viewportIndexAndLayer, m_viewIndex, "", insertPos); - } else if (useLayer) { - assert(m_layer); - viewportIndexAndLayer = BinaryOperator::CreateOr(viewportIndexAndLayer, m_layer, "", insertPos); + if (viewportIndex) { + viewportIndexAndLayer = builder.CreateShl(viewportIndex, builder.getInt32(16)); + } + + if (layer) { + viewportIndexAndLayer = builder.CreateOr(viewportIndexAndLayer, layer); } - viewportIndexAndLayer = new BitCastInst(viewportIndexAndLayer, Type::getFloatTy(*m_context), "", insertPos); + viewportIndexAndLayer = builder.CreateBitCast(viewportIndexAndLayer, Type::getFloatTy(*m_context)); Value *args[] = { ConstantInt::get(Type::getInt32Ty(*m_context), EXP_TARGET_POS_1), // tgt @@ -1474,7 +1497,7 @@ void PatchInOutImportExport::visitReturnInst(ReturnInst &retInst) { ConstantInt::get(Type::getInt1Ty(*m_context), false) // vm }; - emitCall("llvm.amdgcn.exp.f32", Type::getVoidTy(*m_context), args, {}, insertPos); + builder.CreateNamedCall("llvm.amdgcn.exp.f32", Type::getVoidTy(*m_context), args, {}); // NOTE: We have to export gl_ViewportIndex via generic outputs as well. if (useViewportIndex) { @@ -1489,7 +1512,7 @@ void PatchInOutImportExport::visitReturnInst(ReturnInst &retInst) { assert(builtInOutLocs.find(BuiltInViewportIndex) != builtInOutLocs.end()); const unsigned loc = builtInOutLocs.find(BuiltInViewportIndex)->second; - Value *viewportIndex = new BitCastInst(m_viewportIndex, Type::getFloatTy(*m_context), "", insertPos); + Value *viewportIndex = builder.CreateBitCast(m_viewportIndex, Type::getFloatTy(*m_context)); recordVertexAttribExport(loc, {viewportIndex, poison, poison, poison}); } @@ -1508,7 +1531,7 @@ void PatchInOutImportExport::visitReturnInst(ReturnInst &retInst) { assert(builtInOutLocs.find(BuiltInLayer) != builtInOutLocs.end()); const unsigned loc = builtInOutLocs.find(BuiltInLayer)->second; - Value *layer = new BitCastInst(m_layer, Type::getFloatTy(*m_context), "", insertPos); + Value *layer = builder.CreateBitCast(m_layer, Type::getFloatTy(*m_context)); recordVertexAttribExport(loc, {layer, poison, poison, poison}); } @@ -2179,7 +2202,7 @@ Value *PatchInOutImportExport::patchTcsBuiltInInputImport(Type *inputTy, unsigne break; } case BuiltInViewIndex: { - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) input = getFunctionArgument(m_entryPoint, entryArgIdxs.viewIndex); else input = builder.getInt32(0); @@ -2307,7 +2330,7 @@ Value *PatchInOutImportExport::patchTesBuiltInInputImport(Type *inputTy, unsigne break; } case BuiltInViewIndex: { - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) input = getFunctionArgument(m_entryPoint, entryArgIdxs.viewIndex); else input = builder.getInt32(0); @@ -2358,7 +2381,7 @@ Value *PatchInOutImportExport::patchGsBuiltInInputImport(Type *inputTy, unsigned break; } case BuiltInViewIndex: { - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) input = getFunctionArgument(m_entryPoint, entryArgIdxs.viewIndex); else input = builder.getInt32(0); @@ -4964,7 +4987,7 @@ void PatchInOutImportExport::addExportInstForBuiltInOutput(Value *output, unsign // NOTE: Only export gl_Layer when multi-view is disabled. Otherwise, we will export gl_ViewIndex to vertex position // data. - const auto enableMultiView = m_pipelineState->getInputAssemblyState().enableMultiView; + const auto enableMultiView = m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; if (!enableMultiView) { Value *args[] = { ConstantInt::get(Type::getInt32Ty(*m_context), EXP_TARGET_POS_1), // tgt diff --git a/lgc/patch/PatchResourceCollect.cpp b/lgc/patch/PatchResourceCollect.cpp index e339fbe03b..b4afb480c4 100644 --- a/lgc/patch/PatchResourceCollect.cpp +++ b/lgc/patch/PatchResourceCollect.cpp @@ -1238,6 +1238,9 @@ bool PatchResourceCollect::isVertexReuseDisabled() { } else if (hasVs) useViewportIndex = m_pipelineState->getShaderResourceUsage(ShaderStageVertex)->builtInUsage.vs.viewportIndex; + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) + useViewportIndex = true; + disableVertexReuse |= useViewportIndex; return disableVertexReuse; @@ -2353,7 +2356,7 @@ void PatchResourceCollect::mapBuiltInToGenericInOut() { if (builtInUsage.gs.viewportIndex) mapGsBuiltInOutput(BuiltInViewportIndex, 1); - if (m_pipelineState->getInputAssemblyState().enableMultiView) + if (m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable) mapGsBuiltInOutput(BuiltInViewIndex, 1); if (builtInUsage.gs.primitiveShadingRate) diff --git a/lgc/patch/RegisterMetadataBuilder.cpp b/lgc/patch/RegisterMetadataBuilder.cpp index a82f210eaf..4a1973d75f 100644 --- a/lgc/patch/RegisterMetadataBuilder.cpp +++ b/lgc/patch/RegisterMetadataBuilder.cpp @@ -563,7 +563,7 @@ void RegisterMetadataBuilder::buildPrimShaderRegisters() { if (m_hasMesh) { maxVertsPerSubgroup = std::min(meshMode.outputVertices, NggMaxThreadsPerSubgroup); threadsPerSubgroup = calcFactor.primAmpFactor; - const bool enableMultiView = m_pipelineState->getInputAssemblyState().enableMultiView; + const bool enableMultiView = m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; bool hasPrimitivePayload = meshBuiltInUsage.layer || meshBuiltInUsage.viewportIndex || meshBuiltInUsage.primitiveShadingRate || enableMultiView; if (m_gfxIp.major < 11) @@ -1133,6 +1133,7 @@ void RegisterMetadataBuilder::buildPaSpecificRegisters() { bool usePointSize = false; bool useLayer = false; bool useViewportIndex = false; + bool useViewportIndexImplicitly = false; bool useShadingRate = false; unsigned clipDistanceCount = 0; unsigned cullDistanceCount = 0; @@ -1207,7 +1208,12 @@ void RegisterMetadataBuilder::buildPaSpecificRegisters() { expCount = resUsage->inOutUsage.expCount; } - useLayer = useLayer || m_pipelineState->getInputAssemblyState().enableMultiView; + useLayer = useLayer || m_pipelineState->getInputAssemblyState().multiView != MultiViewModeDisable; + // useViewportIndex must be set in this mode as API shader may not export viewport index. + if (m_pipelineState->getInputAssemblyState().multiView == MultiViewModePerView) { + useViewportIndexImplicitly = !useViewportIndex; + useViewportIndex = true; + } if (usePrimitiveId) { getGraphicsRegNode()[Util::Abi::GraphicsRegisterMetadataKey::VgtPrimitiveIdEn] = true; @@ -1238,7 +1244,8 @@ void RegisterMetadataBuilder::buildPaSpecificRegisters() { // VGT_REUSE_OFF bool disableVertexReuse = m_pipelineState->getInputAssemblyState().disableVertexReuse; disableVertexReuse |= meshPipeline; // Mesh pipeline always disable vertex reuse - if (useViewportIndex) + // If viewport index is implicitly set by multiview, then it must be uniform and reuse should be allowed. + if (useViewportIndex && !useViewportIndexImplicitly) disableVertexReuse = true; getGraphicsRegNode()[Util::Abi::GraphicsRegisterMetadataKey::VgtReuseOff] = diff --git a/llpc/context/llpcGraphicsContext.cpp b/llpc/context/llpcGraphicsContext.cpp index cdc9c46383..45e66b9653 100644 --- a/llpc/context/llpcGraphicsContext.cpp +++ b/llpc/context/llpcGraphicsContext.cpp @@ -433,7 +433,7 @@ void GraphicsContext::setGraphicsStateInPipeline(Pipeline *pipeline, Util::Metro const auto &inputRsState = static_cast(getPipelineBuildInfo())->rsState; InputAssemblyState inputAssemblyState = {}; - inputAssemblyState.enableMultiView = inputIaState.enableMultiView; + inputAssemblyState.multiView = inputIaState.enableMultiView ? MultiViewModeSimple : MultiViewModeDisable; RasterizerState rasterizerState = {}; if (stageMask & ~shaderStageToMask(ShaderStageFragment)) {