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. // 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); const auto buffer = info.ReadUdReg<AmdGpu::Buffer>(attrib.sgpr_base, attrib.dword_offset);
for (u32 i = 0; i < 4; i++) { const auto comp = [&](AmdGpu::CompSwizzle swizzle) -> IR::F32 {
const IR::F32 comp = [&] { switch (swizzle) {
switch (buffer.GetSwizzle(i)) { case AmdGpu::CompSwizzle::One:
case AmdGpu::CompSwizzle::One: return ir.Imm32(1.f);
return ir.Imm32(1.f); case AmdGpu::CompSwizzle::Zero:
case AmdGpu::CompSwizzle::Zero: return ir.Imm32(0.f);
return ir.Imm32(0.f); case AmdGpu::CompSwizzle::Red:
case AmdGpu::CompSwizzle::Red: return ir.GetAttribute(attr, 0);
return ir.GetAttribute(attr, 0); case AmdGpu::CompSwizzle::Green:
case AmdGpu::CompSwizzle::Green: return ir.GetAttribute(attr, 1);
return ir.GetAttribute(attr, 1); case AmdGpu::CompSwizzle::Blue:
case AmdGpu::CompSwizzle::Blue: return ir.GetAttribute(attr, 2);
return ir.GetAttribute(attr, 2); case AmdGpu::CompSwizzle::Alpha:
case AmdGpu::CompSwizzle::Alpha: return ir.GetAttribute(attr, 3);
return ir.GetAttribute(attr, 3); default:
default: UNREACHABLE();
UNREACHABLE(); }
} };
}(); const auto [r, g, b, a] = buffer.DstSelect();
ir.SetVectorReg(dst_reg++, comp); 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 // 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 // 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) { IR::Value SwizzleVector(IR::IREmitter& ir, auto sharp, IR::Value texel) {
boost::container::static_vector<IR::Value, 4> comps; const auto comp = [&](AmdGpu::CompSwizzle swizzle) -> IR::Value {
for (u32 i = 0; i < 4; i++) { switch (swizzle) {
switch (sharp.GetSwizzle(i)) {
case AmdGpu::CompSwizzle::Zero: case AmdGpu::CompSwizzle::Zero:
comps.emplace_back(ir.Imm32(0.f)); return ir.Imm32(0.f);
break;
case AmdGpu::CompSwizzle::One: case AmdGpu::CompSwizzle::One:
comps.emplace_back(ir.Imm32(1.f)); return ir.Imm32(1.f);
break;
case AmdGpu::CompSwizzle::Red: case AmdGpu::CompSwizzle::Red:
comps.emplace_back(ir.CompositeExtract(texel, 0)); return ir.CompositeExtract(texel, 0);
break;
case AmdGpu::CompSwizzle::Green: case AmdGpu::CompSwizzle::Green:
comps.emplace_back(ir.CompositeExtract(texel, 1)); return ir.CompositeExtract(texel, 1);
break;
case AmdGpu::CompSwizzle::Blue: case AmdGpu::CompSwizzle::Blue:
comps.emplace_back(ir.CompositeExtract(texel, 2)); return ir.CompositeExtract(texel, 2);
break;
case AmdGpu::CompSwizzle::Alpha: case AmdGpu::CompSwizzle::Alpha:
comps.emplace_back(ir.CompositeExtract(texel, 3)); return ir.CompositeExtract(texel, 3);
break;
default: default:
UNREACHABLE(); 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 { class Descriptors {

View File

@ -31,7 +31,7 @@ struct BufferSpecialization {
struct TextureBufferSpecialization { struct TextureBufferSpecialization {
bool is_integer = false; bool is_integer = false;
u32 dst_select = 0; AmdGpu::CompMapping dst_select{};
auto operator<=>(const TextureBufferSpecialization&) const = default; auto operator<=>(const TextureBufferSpecialization&) const = default;
}; };
@ -40,13 +40,9 @@ struct ImageSpecialization {
AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; AmdGpu::ImageType type = AmdGpu::ImageType::Color2D;
bool is_integer = false; bool is_integer = false;
bool is_storage = false; bool is_storage = false;
u32 dst_select = 0; AmdGpu::CompMapping dst_select{};
bool operator==(const ImageSpecialization& other) const { auto operator<=>(const ImageSpecialization&) const = default;
return type == other.type && is_integer == other.is_integer &&
is_storage == other.is_storage &&
(dst_select != 0 ? dst_select == other.dst_select : true);
}
}; };
struct FMaskSpecialization { struct FMaskSpecialization {

View File

@ -20,6 +20,38 @@ enum class CompSwizzle : u32 {
Alpha = 7, 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] // Table 8.5 Buffer Resource Descriptor [Sea Islands Series Instruction Set Architecture]
struct Buffer { struct Buffer {
u64 base_address : 44; u64 base_address : 44;
@ -52,21 +84,22 @@ struct Buffer {
return std::memcmp(this, &other, sizeof(Buffer)) == 0; return std::memcmp(this, &other, sizeof(Buffer)) == 0;
} }
u32 DstSelect() const { CompMapping DstSelect() const {
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); const CompMapping dst_sel{
} .r = CompSwizzle(dst_sel_x),
.g = CompSwizzle(dst_sel_y),
CompSwizzle GetSwizzle(u32 comp) const noexcept { .b = CompSwizzle(dst_sel_z),
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w}; .a = CompSwizzle(dst_sel_w),
return static_cast<CompSwizzle>(select[comp]); };
return RemapComponents(DataFormat(data_format), dst_sel);
} }
NumberFormat GetNumberFmt() const noexcept { NumberFormat GetNumberFmt() const noexcept {
return static_cast<NumberFormat>(num_format); return RemapNumberFormat(NumberFormat(num_format));
} }
DataFormat GetDataFmt() const noexcept { DataFormat GetDataFmt() const noexcept {
return static_cast<DataFormat>(data_format); return RemapDataFormat(DataFormat(data_format));
} }
u32 GetStride() const noexcept { u32 GetStride() const noexcept {
@ -186,10 +219,11 @@ struct Image {
static constexpr Image Null() { static constexpr Image Null() {
Image image{}; Image image{};
image.data_format = u64(DataFormat::Format8_8_8_8); image.data_format = u64(DataFormat::Format8_8_8_8);
image.dst_sel_x = 4; image.num_format = u64(NumberFormat::Unorm);
image.dst_sel_y = 5; image.dst_sel_x = u64(CompSwizzle::Red);
image.dst_sel_z = 6; image.dst_sel_y = u64(CompSwizzle::Green);
image.dst_sel_w = 7; image.dst_sel_z = u64(CompSwizzle::Blue);
image.dst_sel_w = u64(CompSwizzle::Alpha);
image.tiling_index = u64(TilingMode::Texture_MicroTiled); image.tiling_index = u64(TilingMode::Texture_MicroTiled);
image.type = u64(ImageType::Color2D); image.type = u64(ImageType::Color2D);
return image; return image;
@ -207,43 +241,14 @@ struct Image {
return base_address != 0; return base_address != 0;
} }
u32 DstSelect() const { CompMapping DstSelect() const {
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); const CompMapping dst_sel{
} .r = CompSwizzle(dst_sel_x),
.g = CompSwizzle(dst_sel_y),
CompSwizzle GetSwizzle(u32 comp) const noexcept { .b = CompSwizzle(dst_sel_z),
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w}; .a = CompSwizzle(dst_sel_w),
return static_cast<CompSwizzle>(select[comp]); };
} return RemapComponents(DataFormat(data_format), dst_sel);
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;
} }
u32 Pitch() const { u32 Pitch() const {
@ -285,11 +290,11 @@ struct Image {
} }
DataFormat GetDataFmt() const noexcept { DataFormat GetDataFmt() const noexcept {
return static_cast<DataFormat>(data_format); return RemapDataFormat(DataFormat(data_format));
} }
NumberFormat GetNumberFmt() const noexcept { NumberFormat GetNumberFmt() const noexcept {
return static_cast<NumberFormat>(num_format); return RemapNumberFormat(NumberFormat(num_format));
} }
TilingMode GetTilingMode() const { 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 = static constexpr vk::FormatFeatureFlags2 BufferRead =
vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer; vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer;
static constexpr vk::FormatFeatureFlags2 BufferWrite = static constexpr vk::FormatFeatureFlags2 BufferWrite =

View File

@ -42,6 +42,10 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter);
vk::BorderColor BorderColor(AmdGpu::BorderColor color); vk::BorderColor BorderColor(AmdGpu::BorderColor color);
vk::ComponentSwizzle ComponentSwizzle(AmdGpu::CompSwizzle comp_swizzle);
vk::ComponentMapping ComponentMapping(AmdGpu::CompMapping comp_mapping);
struct SurfaceFormatInfo { struct SurfaceFormatInfo {
AmdGpu::DataFormat data_format; AmdGpu::DataFormat data_format;
AmdGpu::NumberFormat number_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 ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept
: is_storage{desc.IsStorage(image)} { : is_storage{desc.IsStorage(image)} {
const auto dfmt = image.GetDataFmt(); const auto dfmt = image.GetDataFmt();
@ -87,10 +68,7 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
} }
if (!is_storage) { if (!is_storage) {
mapping.r = ConvertComponentSwizzle(image.dst_sel_x); mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect());
mapping.g = ConvertComponentSwizzle(image.dst_sel_y);
mapping.b = ConvertComponentSwizzle(image.dst_sel_z);
mapping.a = ConvertComponentSwizzle(image.dst_sel_w);
} }
} }