mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-05 08:52:36 +00:00
shader_recompiler: Add swizzle support for unsupported formats.
This commit is contained in:
parent
a89c29c2ca
commit
8a006a2bc6
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user