shader_recompiler: Add swizzle support for unsupported formats.

This commit is contained in:
squidbus 2024-12-24 16:34:47 -08:00
parent a89c29c2ca
commit 8a006a2bc6
7 changed files with 127 additions and 120 deletions

View File

@ -475,27 +475,29 @@ 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 auto comp = [&](AmdGpu::CompSwizzle swizzle) -> IR::F32 {
switch (swizzle) {
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();
}
};
const auto [r, g, b, a] = buffer.DstSelect();
ir.SetVectorReg(dst_reg++, comp(r));
ir.SetVectorReg(dst_reg++, comp(g));
ir.SetVectorReg(dst_reg++, comp(b));
ir.SetVectorReg(dst_reg++, comp(a));
// In case of programmable step rates we need to fallback to instance data pulling in
// shader, so VBs should be bound as regular data buffers

View File

@ -129,32 +129,26 @@ 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)) {
const auto comp = [&](AmdGpu::CompSwizzle swizzle) -> IR::Value {
switch (swizzle) {
case AmdGpu::CompSwizzle::Zero:
comps.emplace_back(ir.Imm32(0.f));
break;
return ir.Imm32(0.f);
case AmdGpu::CompSwizzle::One:
comps.emplace_back(ir.Imm32(1.f));
break;
return ir.Imm32(1.f);
case AmdGpu::CompSwizzle::Red:
comps.emplace_back(ir.CompositeExtract(texel, 0));
break;
return ir.CompositeExtract(texel, 0);
case AmdGpu::CompSwizzle::Green:
comps.emplace_back(ir.CompositeExtract(texel, 1));
break;
return ir.CompositeExtract(texel, 1);
case AmdGpu::CompSwizzle::Blue:
comps.emplace_back(ir.CompositeExtract(texel, 2));
break;
return ir.CompositeExtract(texel, 2);
case AmdGpu::CompSwizzle::Alpha:
comps.emplace_back(ir.CompositeExtract(texel, 3));
break;
return ir.CompositeExtract(texel, 3);
default:
UNREACHABLE();
}
}
return ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]);
};
const auto [r, g, b, a] = sharp.DstSelect();
return ir.CompositeConstruct(comp(r), comp(g), comp(b), comp(a));
};
class Descriptors {

View File

@ -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;
};
@ -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 {

View File

@ -20,6 +20,38 @@ enum class CompSwizzle : u32 {
Alpha = 7,
};
struct CompMapping {
CompSwizzle r : 3;
CompSwizzle g : 3;
CompSwizzle b : 3;
CompSwizzle a : 3;
auto operator<=>(const CompMapping& other) const = default;
};
inline DataFormat RemapDataFormat(const DataFormat format) {
if (format == DataFormat::Format11_11_10) {
return DataFormat::Format10_11_11;
}
return format;
}
inline NumberFormat RemapNumberFormat(const NumberFormat format) {
return format;
}
inline CompMapping RemapComponents(const DataFormat format, const CompMapping components) {
if (format == DataFormat::Format11_11_10) {
return {
.r = components.b,
.g = components.g,
.b = components.r,
.a = components.a,
};
}
return components;
}
// Table 8.5 Buffer Resource Descriptor [Sea Islands Series Instruction Set Architecture]
struct Buffer {
u64 base_address : 44;
@ -52,21 +84,22 @@ struct Buffer {
return std::memcmp(this, &other, sizeof(Buffer)) == 0;
}
u32 DstSelect() const {
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9);
}
CompSwizzle GetSwizzle(u32 comp) const noexcept {
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w};
return static_cast<CompSwizzle>(select[comp]);
CompMapping DstSelect() const {
const CompMapping dst_sel{
.r = CompSwizzle(dst_sel_x),
.g = CompSwizzle(dst_sel_y),
.b = CompSwizzle(dst_sel_z),
.a = CompSwizzle(dst_sel_w),
};
return RemapComponents(DataFormat(data_format), dst_sel);
}
NumberFormat GetNumberFmt() const noexcept {
return static_cast<NumberFormat>(num_format);
return RemapNumberFormat(NumberFormat(num_format));
}
DataFormat GetDataFmt() const noexcept {
return static_cast<DataFormat>(data_format);
return RemapDataFormat(DataFormat(data_format));
}
u32 GetStride() const noexcept {
@ -186,10 +219,11 @@ struct Image {
static constexpr Image Null() {
Image image{};
image.data_format = u64(DataFormat::Format8_8_8_8);
image.dst_sel_x = 4;
image.dst_sel_y = 5;
image.dst_sel_z = 6;
image.dst_sel_w = 7;
image.num_format = u64(NumberFormat::Unorm);
image.dst_sel_x = u64(CompSwizzle::Red);
image.dst_sel_y = u64(CompSwizzle::Green);
image.dst_sel_z = u64(CompSwizzle::Blue);
image.dst_sel_w = u64(CompSwizzle::Alpha);
image.tiling_index = u64(TilingMode::Texture_MicroTiled);
image.type = u64(ImageType::Color2D);
return image;
@ -207,43 +241,14 @@ struct Image {
return base_address != 0;
}
u32 DstSelect() const {
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9);
}
CompSwizzle GetSwizzle(u32 comp) const noexcept {
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w};
return static_cast<CompSwizzle>(select[comp]);
}
static char SelectComp(u32 sel) {
switch (sel) {
case 0:
return '0';
case 1:
return '1';
case 4:
return 'R';
case 5:
return 'G';
case 6:
return 'B';
case 7:
return 'A';
default:
UNREACHABLE();
}
}
std::string DstSelectName() const {
std::string result = "[";
u32 dst_sel = DstSelect();
for (u32 i = 0; i < 4; i++) {
result += SelectComp(dst_sel & 7);
dst_sel >>= 3;
}
result += ']';
return result;
CompMapping DstSelect() const {
const CompMapping dst_sel{
.r = CompSwizzle(dst_sel_x),
.g = CompSwizzle(dst_sel_y),
.b = CompSwizzle(dst_sel_z),
.a = CompSwizzle(dst_sel_w),
};
return RemapComponents(DataFormat(data_format), dst_sel);
}
u32 Pitch() const {
@ -285,11 +290,11 @@ struct Image {
}
DataFormat GetDataFmt() const noexcept {
return static_cast<DataFormat>(data_format);
return RemapDataFormat(DataFormat(data_format));
}
NumberFormat GetNumberFmt() const noexcept {
return static_cast<NumberFormat>(num_format);
return RemapNumberFormat(NumberFormat(num_format));
}
TilingMode GetTilingMode() const {

View File

@ -326,6 +326,34 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) {
}
}
vk::ComponentSwizzle ComponentSwizzle(AmdGpu::CompSwizzle comp_swizzle) {
switch (comp_swizzle) {
case AmdGpu::CompSwizzle::Zero:
return vk::ComponentSwizzle::eZero;
case AmdGpu::CompSwizzle::One:
return vk::ComponentSwizzle::eOne;
case AmdGpu::CompSwizzle::Red:
return vk::ComponentSwizzle::eR;
case AmdGpu::CompSwizzle::Green:
return vk::ComponentSwizzle::eG;
case AmdGpu::CompSwizzle::Blue:
return vk::ComponentSwizzle::eB;
case AmdGpu::CompSwizzle::Alpha:
return vk::ComponentSwizzle::eA;
default:
UNREACHABLE();
}
}
vk::ComponentMapping ComponentMapping(AmdGpu::CompMapping comp_mapping) {
return vk::ComponentMapping{
.r = ComponentSwizzle(comp_mapping.r),
.g = ComponentSwizzle(comp_mapping.g),
.b = ComponentSwizzle(comp_mapping.b),
.a = ComponentSwizzle(comp_mapping.a),
};
}
static constexpr vk::FormatFeatureFlags2 BufferRead =
vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer;
static constexpr vk::FormatFeatureFlags2 BufferWrite =

View File

@ -42,6 +42,10 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter);
vk::BorderColor BorderColor(AmdGpu::BorderColor color);
vk::ComponentSwizzle ComponentSwizzle(AmdGpu::CompSwizzle comp_swizzle);
vk::ComponentMapping ComponentMapping(AmdGpu::CompMapping comp_mapping);
struct SurfaceFormatInfo {
AmdGpu::DataFormat data_format;
AmdGpu::NumberFormat number_format;

View File

@ -31,25 +31,6 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) {
}
}
vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) {
switch (dst_sel) {
case 0:
return vk::ComponentSwizzle::eZero;
case 1:
return vk::ComponentSwizzle::eOne;
case 4:
return vk::ComponentSwizzle::eR;
case 5:
return vk::ComponentSwizzle::eG;
case 6:
return vk::ComponentSwizzle::eB;
case 7:
return vk::ComponentSwizzle::eA;
default:
UNREACHABLE();
}
}
ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept
: is_storage{desc.IsStorage(image)} {
const auto dfmt = image.GetDataFmt();
@ -87,10 +68,7 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
}
if (!is_storage) {
mapping.r = ConvertComponentSwizzle(image.dst_sel_x);
mapping.g = ConvertComponentSwizzle(image.dst_sel_y);
mapping.b = ConvertComponentSwizzle(image.dst_sel_z);
mapping.a = ConvertComponentSwizzle(image.dst_sel_w);
mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect());
}
}