Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shader_recompiler: Add swizzle support for unsupported formats. #1869

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
32 changes: 13 additions & 19 deletions src/shader_recompiler/frontend/translate/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,28 @@ void Translator::EmitExport(const GcnInst& inst) {
IR::VectorReg(inst.src[3].code),
};

const auto swizzle = [&](u32 comp) {
const auto set_attribute = [&](u32 comp, IR::F32 value) {
if (!IR::IsMrt(attrib)) {
return comp;
ir.SetAttribute(attrib, value, comp);
return;
}
const u32 index = u32(attrib) - u32(IR::Attribute::RenderTarget0);
switch (runtime_info.fs_info.color_buffers[index].mrt_swizzle) {
case MrtSwizzle::Identity:
return comp;
case MrtSwizzle::Alt:
static constexpr std::array<u32, 4> AltSwizzle = {2, 1, 0, 3};
return AltSwizzle[comp];
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];
default:
UNREACHABLE();
const auto [r, g, b, a] = runtime_info.fs_info.color_buffers[index].swizzle;
const std::array swizzle_array = {r, g, b, a};
const auto swizzled_comp = swizzle_array[comp];
if (u32(swizzled_comp) < u32(AmdGpu::CompSwizzle::Red)) {
ir.SetAttribute(attrib, value, comp);
return;
}
ir.SetAttribute(attrib, value, u32(swizzled_comp) - u32(AmdGpu::CompSwizzle::Red));
};

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)};
ir.SetAttribute(attrib, r, swizzle(idx * 2));
ir.SetAttribute(attrib, g, swizzle(idx * 2 + 1));
set_attribute(idx * 2, r);
set_attribute(idx * 2 + 1, g);
};

// Components are float16 packed into a VGPR
Expand All @@ -73,7 +67,7 @@ void Translator::EmitExport(const GcnInst& inst) {
continue;
}
const IR::F32 comp = ir.GetVectorReg<IR::F32>(vsrc[i]);
ir.SetAttribute(attrib, comp, swizzle(i));
set_attribute(i, comp);
}
}
if (IR::IsMrt(attrib)) {
Expand Down
25 changes: 5 additions & 20 deletions src/shader_recompiler/frontend/translate/translate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,26 +475,11 @@ void Translator::EmitFetch(const GcnInst& inst) {

// Read the V# of the attribute to figure out component number and type.
const auto buffer = info.ReadUdReg<AmdGpu::Buffer>(attrib.sgpr_base, attrib.dword_offset);
for (u32 i = 0; i < 4; i++) {
const IR::F32 comp = [&] {
switch (buffer.GetSwizzle(i)) {
case AmdGpu::CompSwizzle::One:
return ir.Imm32(1.f);
case AmdGpu::CompSwizzle::Zero:
return ir.Imm32(0.f);
case AmdGpu::CompSwizzle::Red:
return ir.GetAttribute(attr, 0);
case AmdGpu::CompSwizzle::Green:
return ir.GetAttribute(attr, 1);
case AmdGpu::CompSwizzle::Blue:
return ir.GetAttribute(attr, 2);
case AmdGpu::CompSwizzle::Alpha:
return ir.GetAttribute(attr, 3);
default:
UNREACHABLE();
}
}();
ir.SetVectorReg(dst_reg++, comp);
const std::array components = buffer.DstSelect().Apply<IR::F32>(
[&](const u32 index) { return ir.GetAttribute(attr, index); },
[&](const u32 imm) { return ir.Imm32(float(imm)); });
for (u32 i = 0; i < components.size(); i++) {
ir.SetVectorReg(dst_reg++, components[i]);
}

// In case of programmable step rates we need to fallback to instance data pulling in
Expand Down
30 changes: 4 additions & 26 deletions src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,32 +129,10 @@ bool IsImageInstruction(const IR::Inst& inst) {
}

IR::Value SwizzleVector(IR::IREmitter& ir, auto sharp, IR::Value texel) {
boost::container::static_vector<IR::Value, 4> comps;
for (u32 i = 0; i < 4; i++) {
switch (sharp.GetSwizzle(i)) {
case AmdGpu::CompSwizzle::Zero:
comps.emplace_back(ir.Imm32(0.f));
break;
case AmdGpu::CompSwizzle::One:
comps.emplace_back(ir.Imm32(1.f));
break;
case AmdGpu::CompSwizzle::Red:
comps.emplace_back(ir.CompositeExtract(texel, 0));
break;
case AmdGpu::CompSwizzle::Green:
comps.emplace_back(ir.CompositeExtract(texel, 1));
break;
case AmdGpu::CompSwizzle::Blue:
comps.emplace_back(ir.CompositeExtract(texel, 2));
break;
case AmdGpu::CompSwizzle::Alpha:
comps.emplace_back(ir.CompositeExtract(texel, 3));
break;
default:
UNREACHABLE();
}
}
return ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]);
const std::array components = sharp.DstSelect().template Apply<IR::Value>(
squidbus marked this conversation as resolved.
Show resolved Hide resolved
[&](const u32 index) { return ir.CompositeExtract(texel, index); },
[&](const u32 imm) { return ir.Imm32(float(imm)); });
return ir.CompositeConstruct(components[0], components[1], components[2], components[3]);
};

class Descriptors {
Expand Down
2 changes: 1 addition & 1 deletion src/shader_recompiler/runtime_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ struct FragmentRuntimeInfo {
std::array<PsInput, 32> inputs;
struct PsColorBuffer {
AmdGpu::NumberFormat num_format;
MrtSwizzle mrt_swizzle;
AmdGpu::CompMapping swizzle;

auto operator<=>(const PsColorBuffer&) const noexcept = default;
};
Expand Down
10 changes: 3 additions & 7 deletions src/shader_recompiler/specialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct BufferSpecialization {

struct TextureBufferSpecialization {
bool is_integer = false;
u32 dst_select = 0;
AmdGpu::CompMapping dst_select{};

auto operator<=>(const TextureBufferSpecialization&) const = default;
};
Expand All @@ -40,13 +40,9 @@ struct ImageSpecialization {
AmdGpu::ImageType type = AmdGpu::ImageType::Color2D;
bool is_integer = false;
bool is_storage = false;
u32 dst_select = 0;
AmdGpu::CompMapping dst_select{};

bool operator==(const ImageSpecialization& other) const {
return type == other.type && is_integer == other.is_integer &&
is_storage == other.is_storage &&
(dst_select != 0 ? dst_select == other.dst_select : true);
}
auto operator<=>(const ImageSpecialization&) const = default;
};

struct FMaskSpecialization {
Expand Down
50 changes: 47 additions & 3 deletions src/video_core/amdgpu/liverpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -889,10 +889,54 @@ struct Liverpool {
return !info.linear_general;
}

NumberFormat NumFormat() const {
[[nodiscard]] DataFormat DataFormat() const {
return RemapDataFormat(info.format);
}

[[nodiscard]] NumberFormat NumFormat() const {
// There is a small difference between T# and CB number types, account for it.
return info.number_type == AmdGpu::NumberFormat::SnormNz ? AmdGpu::NumberFormat::Srgb
: info.number_type.Value();
return RemapNumberFormat(info.number_type == NumberFormat::SnormNz
? NumberFormat::Srgb
: info.number_type.Value());
}

[[nodiscard]] CompMapping Swizzle() const {
// clang-format off
static constexpr std::array<std::array<CompMapping, 4>, 4> mrt_swizzles{{
raphaelthegreat marked this conversation as resolved.
Show resolved Hide resolved
// Standard
std::array<CompMapping, 4>{{
{.r = CompSwizzle::Red, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero},
{.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero},
{.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Blue, .a = CompSwizzle::Zero},
{.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Blue, .a = CompSwizzle::Alpha},
}},
// Alternate
std::array<CompMapping, 4>{{
{.r = CompSwizzle::Zero, .g = CompSwizzle::Red, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero},
{.r = CompSwizzle::Red, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Green},
{.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Zero, .a = CompSwizzle::Blue},
{.r = CompSwizzle::Blue, .g = CompSwizzle::Green, .b = CompSwizzle::Red, .a = CompSwizzle::Alpha},
}},
// StandardReverse
std::array<CompMapping, 4>{{
{CompSwizzle::Zero, CompSwizzle::Zero, CompSwizzle::Red, CompSwizzle::Zero},
{CompSwizzle::Green, CompSwizzle::Red, CompSwizzle::Zero, CompSwizzle::Zero},
{CompSwizzle::Blue, CompSwizzle::Green, CompSwizzle::Red, CompSwizzle::Zero},
{CompSwizzle::Alpha, CompSwizzle::Blue, CompSwizzle::Green, CompSwizzle::Red},
}},
// AlternateReverse
std::array<CompMapping, 4>{{
{CompSwizzle::Zero, CompSwizzle::Zero, CompSwizzle::Zero, CompSwizzle::Red},
{CompSwizzle::Green, CompSwizzle::Zero, CompSwizzle::Zero, CompSwizzle::Red},
{CompSwizzle::Blue, CompSwizzle::Green, CompSwizzle::Zero, CompSwizzle::Red},
{CompSwizzle::Alpha, CompSwizzle::Red, CompSwizzle::Green, CompSwizzle::Blue},
}},
}};
// clang-format on
const auto swap_idx = static_cast<u32>(info.comp_swap.Value());
const auto components_idx = NumComponents(info.format) - 1;
const auto mrt_swizzle = mrt_swizzles[swap_idx][components_idx];
return RemapComponents(info.format, mrt_swizzle);
}
};

Expand Down
Loading
Loading