@@ -487,14 +487,9 @@ bool LowerFragColorExport::runImpl(Module &module, PipelineShadersResult &pipeli
487
487
}
488
488
489
489
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
- }
495
490
bool dummyExport =
496
491
(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);
498
493
return !m_info.empty () || dummyExport;
499
494
}
500
495
@@ -878,68 +873,85 @@ Value *FragColorExport::dualSourceSwizzle(BuilderBase &builder) {
878
873
// @param values : The values that are to be exported. Indexed by the hw color target.
879
874
// @param exportFormat : The export format for each color target. Indexed by the hw color target.
880
875
// @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) {
884
878
SmallVector<ExportFormat> finalExportFormats;
885
879
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 ;
915
904
}
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 ;
930
941
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);
938
943
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;
940
950
}
941
951
}
942
952
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.)
943
955
if (m_pipelineState->getTargetInfo ().getGfxIpVersion ().major >= 11 &&
944
956
(m_pipelineState->getColorExportState ().dualSourceBlendEnable ||
945
957
m_pipelineState->getColorExportState ().dynamicDualSourceBlendEnable ))
0 commit comments