2024-05-22 01:35:12 +03:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#include "shader_recompiler/frontend/translate/translate.h"
|
2024-09-03 14:04:30 +03:00
|
|
|
#include "shader_recompiler/runtime_info.h"
|
2024-05-22 01:35:12 +03:00
|
|
|
|
|
|
|
namespace Shader::Gcn {
|
|
|
|
|
2024-07-31 00:32:40 +03:00
|
|
|
void Translator::EmitExport(const GcnInst& inst) {
|
2024-07-15 13:33:57 +03:00
|
|
|
if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) {
|
2024-07-13 14:40:39 +02:00
|
|
|
ir.Discard(ir.LogicalNot(ir.GetExec()));
|
|
|
|
}
|
|
|
|
|
2024-05-22 01:35:12 +03:00
|
|
|
const auto& exp = inst.control.exp;
|
|
|
|
const IR::Attribute attrib{exp.target};
|
|
|
|
const std::array vsrc = {
|
|
|
|
IR::VectorReg(inst.src[0].code),
|
|
|
|
IR::VectorReg(inst.src[1].code),
|
|
|
|
IR::VectorReg(inst.src[2].code),
|
|
|
|
IR::VectorReg(inst.src[3].code),
|
|
|
|
};
|
|
|
|
|
2024-09-03 14:04:30 +03:00
|
|
|
const auto swizzle = [&](u32 comp) {
|
|
|
|
if (!IR::IsMrt(attrib)) {
|
|
|
|
return comp;
|
|
|
|
}
|
|
|
|
const u32 index = u32(attrib) - u32(IR::Attribute::RenderTarget0);
|
|
|
|
switch (runtime_info.fs_info.mrt_swizzles[index]) {
|
|
|
|
case MrtSwizzle::Identity:
|
|
|
|
return comp;
|
|
|
|
case MrtSwizzle::Alt:
|
|
|
|
static constexpr std::array<u32, 4> AltSwizzle = {2, 1, 0, 3};
|
|
|
|
return AltSwizzle[comp];
|
2024-09-07 00:14:51 +03:00
|
|
|
case MrtSwizzle::Reverse:
|
|
|
|
static constexpr std::array<u32, 4> RevSwizzle = {3, 2, 1, 0};
|
|
|
|
return RevSwizzle[comp];
|
|
|
|
case MrtSwizzle::ReverseAlt:
|
|
|
|
static constexpr std::array<u32, 4> AltRevSwizzle = {3, 0, 1, 2};
|
|
|
|
return AltRevSwizzle[comp];
|
2024-09-03 14:04:30 +03:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-05-22 01:35:12 +03:00
|
|
|
const auto unpack = [&](u32 idx) {
|
|
|
|
const IR::Value value = ir.UnpackHalf2x16(ir.GetVectorReg(vsrc[idx]));
|
|
|
|
const IR::F32 r = IR::F32{ir.CompositeExtract(value, 0)};
|
|
|
|
const IR::F32 g = IR::F32{ir.CompositeExtract(value, 1)};
|
2024-09-03 14:04:30 +03:00
|
|
|
ir.SetAttribute(attrib, r, swizzle(idx * 2));
|
|
|
|
ir.SetAttribute(attrib, g, swizzle(idx * 2 + 1));
|
2024-05-22 01:35:12 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// Components are float16 packed into a VGPR
|
|
|
|
if (exp.compr) {
|
|
|
|
// Export R, G
|
|
|
|
if (exp.en & 1) {
|
|
|
|
unpack(0);
|
|
|
|
}
|
|
|
|
// Export B, A
|
|
|
|
if ((exp.en >> 2) & 1) {
|
|
|
|
unpack(1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Components are float32 into separate VGPRS
|
|
|
|
u32 mask = exp.en;
|
|
|
|
for (u32 i = 0; i < 4; i++, mask >>= 1) {
|
|
|
|
if ((mask & 1) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const IR::F32 comp = ir.GetVectorReg<IR::F32>(vsrc[i]);
|
2024-09-03 14:04:30 +03:00
|
|
|
ir.SetAttribute(attrib, comp, swizzle(i));
|
2024-05-22 01:35:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Shader::Gcn
|