Skip to content

Commit 58c9aea

Browse files
committed
lgc: centralize color export format calculations
Avoid the problematic duplication across the cases with and without color export shaders. (cherry picked from commit 4b589a1dd2de0961b1c35615c7b350aaa0315688)
1 parent ab32813 commit 58c9aea

File tree

4 files changed

+74
-73
lines changed

4 files changed

+74
-73
lines changed

lgc/elfLinker/ColorExportShader.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ ColorExportShader::ColorExportShader(PipelineState *pipelineState, ArrayRef<Colo
4646
: GlueShader(pipelineState), m_killEnabled(false) {
4747
m_exports.append(exports.begin(), exports.end());
4848

49-
memset(m_exportFormat, 0, sizeof(m_exportFormat));
50-
for (auto &exp : m_exports) {
51-
if (exp.hwColorTarget == MaxColorTargets)
52-
continue;
53-
m_exportFormat[exp.hwColorTarget] =
54-
static_cast<ExportFormat>(pipelineState->computeExportFormat(exp.ty, exp.location));
55-
}
56-
5749
if (!pipelineState->getOptions().enableColorExportShader) {
5850
PalMetadata *metadata = pipelineState->getPalMetadata();
5951
if (pipelineState->useRegisterFieldFormat()) {
@@ -77,7 +69,6 @@ StringRef ColorExportShader::getString() {
7769
if (m_shaderString.empty()) {
7870
constexpr uint32_t estimatedTypeSize = 10;
7971
uint32_t sizeEstimate = (sizeof(ColorExportInfo) + estimatedTypeSize) * m_exports.size();
80-
sizeEstimate += sizeof(m_exportFormat);
8172
sizeEstimate += sizeof(m_killEnabled);
8273
m_shaderString.reserve(sizeEstimate);
8374

@@ -90,7 +81,6 @@ StringRef ColorExportShader::getString() {
9081
StringRef(reinterpret_cast<const char *>(&colorExportInfo.location), sizeof(colorExportInfo.location));
9182
m_shaderString += getTypeName(colorExportInfo.ty);
9283
}
93-
m_shaderString += StringRef(reinterpret_cast<const char *>(m_exportFormat), sizeof(m_exportFormat)).str();
9484
m_shaderString += StringRef(reinterpret_cast<const char *>(&m_killEnabled), sizeof(m_killEnabled));
9585
}
9686
return m_shaderString;
@@ -119,7 +109,7 @@ Module *ColorExportShader::generate() {
119109
}
120110

121111
bool dummyExport = m_lgcContext->getTargetInfo().getGfxIpVersion().major < 10 || m_killEnabled;
122-
fragColorExport.generateExportInstructions(m_exports, values, m_exportFormat, dummyExport, builder);
112+
fragColorExport.generateExportInstructions(m_exports, values, dummyExport, builder);
123113

124114
if (m_pipelineState->getOptions().enableColorExportShader) {
125115
builder.CreateIntrinsic(Intrinsic::amdgcn_endpgm, {}, {});

lgc/elfLinker/ColorExportShader.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ class ColorExportShader : public GlueShader {
7979
// have access to PipelineState, so we can hash the information here and let the front-end use it as the
8080
// key for a cache of glue shaders.
8181
llvm::SmallVector<ColorExportInfo, 8> m_exports;
82-
ExportFormat m_exportFormat[MaxColorTargets] = {}; // The export format for each hw color target.
8382
// The encoded or hashed (in some way) single string version of the above.
8483
std::string m_shaderString;
8584
bool m_killEnabled; // True if this fragment shader has kill enabled.

lgc/include/lgc/patch/FragColorExport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class FragColorExport {
6262
FragColorExport(llvm::LLVMContext *context, PipelineState *pipelineState);
6363

6464
void generateExportInstructions(llvm::ArrayRef<lgc::ColorExportInfo> info, llvm::ArrayRef<llvm::Value *> values,
65-
llvm::ArrayRef<ExportFormat> exportFormat, bool dummyExport, BuilderBase &builder);
65+
bool dummyExport, BuilderBase &builder);
6666
static void setDoneFlag(llvm::Value *exportInst, BuilderBase &builder);
6767
static llvm::CallInst *addDummyExport(BuilderBase &builder);
6868
static llvm::Function *generateNullFragmentShader(llvm::Module &module, PipelineState *pipelineState,

lgc/patch/FragColorExport.cpp

Lines changed: 72 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)