@@ -487,14 +487,9 @@ bool LowerFragColorExport::runImpl(Module &module, PipelineShadersResult &pipeli
487487 }
488488
489489 FragColorExport fragColorExport (m_context, m_pipelineState);
490- SmallVector<ExportFormat, 8 > exportFormat (MaxColorTargets + 1 , EXP_FORMAT_ZERO);
491- for (auto &exp : m_info) {
492- exportFormat[exp.hwColorTarget ] =
493- static_cast <ExportFormat>(m_pipelineState->computeExportFormat (exp.ty , exp.location ));
494- }
495490 bool dummyExport =
496491 (m_pipelineState->getTargetInfo ().getGfxIpVersion ().major < 10 || m_resUsage->builtInUsage .fs .discard );
497- fragColorExport.generateExportInstructions (m_info, m_exportValues, exportFormat, dummyExport, builder);
492+ fragColorExport.generateExportInstructions (m_info, m_exportValues, dummyExport, builder);
498493 return !m_info.empty () || dummyExport;
499494}
500495
@@ -878,68 +873,85 @@ Value *FragColorExport::dualSourceSwizzle(BuilderBase &builder) {
878873// @param values : The values that are to be exported. Indexed by the hw color target.
879874// @param exportFormat : The export format for each color target. Indexed by the hw color target.
880875// @param builder : The builder object that will be used to create new instructions.
881- void FragColorExport::generateExportInstructions (ArrayRef<lgc::ColorExportInfo> info, ArrayRef<llvm::Value *> values,
882- ArrayRef<ExportFormat> exportFormat, bool dummyExport,
883- BuilderBase &builder) {
876+ void FragColorExport::generateExportInstructions (ArrayRef<ColorExportInfo> info, ArrayRef<Value *> values,
877+ bool dummyExport, BuilderBase &builder) {
884878 SmallVector<ExportFormat> finalExportFormats;
885879 Value *lastExport = nullptr ;
886- unsigned hwColorExport = 0 ;
887- for (const ColorExportInfo &exp : info) {
888- Value *output = values[exp.hwColorTarget ];
889- if (exp.hwColorTarget != MaxColorTargets) {
890- ExportFormat expFmt = exportFormat[exp.hwColorTarget ];
891- if (expFmt != EXP_FORMAT_ZERO) {
892- lastExport = handleColorExportInstructions (output, hwColorExport, builder, expFmt, exp.isSigned );
893- finalExportFormats.push_back (expFmt);
894- ++hwColorExport;
895- }
896- } else {
897- // Depth export alpha comes from MRT0.a if there is MRT0.a and A2C is enable on GFX11+
898- Value *alpha = PoisonValue::get (Type::getFloatTy (*m_context));
899- unsigned depthMask = exp.location ;
900- if (!dummyExport && m_pipelineState->getTargetInfo ().getGfxIpVersion ().major >= 11 &&
901- m_pipelineState->getColorExportState ().alphaToCoverageEnable ) {
902- bool canCopyAlpha = false ;
903- for (auto &curInfo : info) {
904- if (curInfo.hwColorTarget == EXP_TARGET_MRT_0 && (exportFormat[EXP_TARGET_MRT_0] > EXP_FORMAT_32_GR)) {
905- // Mrt0 is enabled and its alpha channel is enabled
906- canCopyAlpha = true ;
907- break ;
908- }
909- }
910- if (canCopyAlpha) {
911- // Update Mrtz.a and its mask
912- alpha = builder.CreateExtractElement (values[EXP_TARGET_MRT_0], 3 );
913- depthMask |= 0x8 ;
914- }
880+
881+ // MRTZ export comes first if it exists (this is a HW requirement on gfx11+ and an optional good idea on earlier HW).
882+ // We make the assume here that it is also first in the info list.
883+ if (!info.empty () && info[0 ].hwColorTarget == MaxColorTargets) {
884+ unsigned depthMask = info[0 ].location ;
885+
886+ // Depth export alpha comes from MRT0.a if there is MRT0.a and A2C is enabled on GFX11+
887+ Value *alpha = PoisonValue::get (Type::getFloatTy (*m_context));
888+ if (!dummyExport && m_pipelineState->getTargetInfo ().getGfxIpVersion ().major >= 11 &&
889+ m_pipelineState->getColorExportState ().alphaToCoverageEnable ) {
890+ for (auto &curInfo : info) {
891+ if (curInfo.location != 0 )
892+ continue ;
893+
894+ auto *vecTy = dyn_cast<FixedVectorType>(values[curInfo.hwColorTarget ]->getType ());
895+ if (!vecTy || vecTy->getNumElements () < 4 )
896+ break ;
897+
898+ // Mrt0 is enabled and its alpha channel is enabled
899+ alpha = builder.CreateExtractElement (values[curInfo.hwColorTarget ], 3 );
900+ if (alpha->getType ()->isIntegerTy ())
901+ alpha = builder.CreateBitCast (alpha, builder.getFloatTy ());
902+ depthMask |= 0x8 ;
903+ break ;
915904 }
916- Value *fragDepth = builder.CreateExtractElement (output, static_cast <uint64_t >(0 ));
917- Value *fragStencilRef = builder.CreateExtractElement (output, 1 );
918- Value *sampleMask = builder.CreateExtractElement (output, 2 );
919- Value *args[] = {
920- builder.getInt32 (EXP_TARGET_Z), // tgt
921- builder.getInt32 (depthMask), // en
922- fragDepth, // src0
923- fragStencilRef, // src1
924- sampleMask, // src2
925- alpha, // src3
926- builder.getFalse (), // done
927- builder.getTrue () // vm
928- };
929- lastExport = builder.CreateIntrinsic (Intrinsic::amdgcn_exp, builder.getFloatTy (), args);
905+ }
906+
907+ Value *output = values[MaxColorTargets];
908+ Value *fragDepth = builder.CreateExtractElement (output, static_cast <uint64_t >(0 ));
909+ Value *fragStencilRef = builder.CreateExtractElement (output, 1 );
910+ Value *sampleMask = builder.CreateExtractElement (output, 2 );
911+ Value *args[] = {
912+ builder.getInt32 (EXP_TARGET_Z), // tgt
913+ builder.getInt32 (depthMask), // en
914+ fragDepth, // src0
915+ fragStencilRef, // src1
916+ sampleMask, // src2
917+ alpha, // src3
918+ builder.getFalse (), // done
919+ builder.getTrue () // vm
920+ };
921+ lastExport = builder.CreateIntrinsic (Intrinsic::amdgcn_exp, builder.getFloatTy (), args);
922+
923+ unsigned depthExpFmt = EXP_FORMAT_ZERO;
924+ if (depthMask & 0x4 )
925+ depthExpFmt = EXP_FORMAT_32_ABGR;
926+ else if (depthMask & 0x2 )
927+ depthExpFmt = (depthMask & 0x8 ) ? EXP_FORMAT_32_ABGR : EXP_FORMAT_32_GR;
928+ else if (depthMask & 0x1 )
929+ depthExpFmt = (depthMask & 0x8 ) ? EXP_FORMAT_32_AR : EXP_FORMAT_32_R;
930+
931+ m_pipelineState->getPalMetadata ()->setSpiShaderZFormat (depthExpFmt);
932+ info = info.drop_front (1 );
933+ }
934+
935+ // Now do color exports by color buffer.
936+ unsigned hwColorExport = 0 ;
937+ for (unsigned location = 0 ; location < MaxColorTargets; ++location) {
938+ auto infoIt = llvm::find_if (info, [&](const ColorExportInfo &info) { return info.location == location; });
939+ if (infoIt == info.end ())
940+ continue ;
930941
931- unsigned depthExpFmt = EXP_FORMAT_ZERO;
932- if (depthMask & 0x4 )
933- depthExpFmt = EXP_FORMAT_32_ABGR;
934- else if (depthMask & 0x2 )
935- depthExpFmt = (depthMask & 0x8 ) ? EXP_FORMAT_32_ABGR : EXP_FORMAT_32_GR;
936- else if (depthMask & 0x1 )
937- depthExpFmt = (depthMask & 0x8 ) ? EXP_FORMAT_32_AR : EXP_FORMAT_32_R;
942+ assert (infoIt->hwColorTarget < MaxColorTargets);
938943
939- m_pipelineState->getPalMetadata ()->setSpiShaderZFormat (depthExpFmt);
944+ auto expFmt = static_cast <ExportFormat>(m_pipelineState->computeExportFormat (infoIt->ty , location));
945+ if (expFmt != EXP_FORMAT_ZERO) {
946+ lastExport = handleColorExportInstructions (values[infoIt->hwColorTarget ], hwColorExport, builder, expFmt,
947+ infoIt->isSigned );
948+ finalExportFormats.push_back (expFmt);
949+ ++hwColorExport;
940950 }
941951 }
942952
953+ // Special case of color exports: dual swizzle on gfx11+. They are implicitly captured above, and this case implies
954+ // no other color exports. (TODO: Cleanup the implicit capture; we should just check this up-front.)
943955 if (m_pipelineState->getTargetInfo ().getGfxIpVersion ().major >= 11 &&
944956 (m_pipelineState->getColorExportState ().dualSourceBlendEnable ||
945957 m_pipelineState->getColorExportState ().dynamicDualSourceBlendEnable ))
0 commit comments