Skip to content

Commit 722a0e3

Browse files
graphics: Improve handling of color buffer and storage image swizzles (#1763)
* liverpool_to_vk: Remove wrong component swap formats * shader_recompiler: Handle storage and buffer format swizzles * shader_recompiler: Skip unsupported depth export * image_view: Remove image format swizzle * Platform support is not always guaranteed
1 parent 028be3b commit 722a0e3

File tree

6 files changed

+66
-49
lines changed

6 files changed

+66
-49
lines changed

src/shader_recompiler/frontend/translate/export.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ void Translator::EmitExport(const GcnInst& inst) {
1313

1414
const auto& exp = inst.control.exp;
1515
const IR::Attribute attrib{exp.target};
16+
if (attrib == IR::Attribute::Depth && exp.en != 1) {
17+
LOG_WARNING(Render_Vulkan, "Unsupported depth export");
18+
return;
19+
}
20+
1621
const std::array vsrc = {
1722
IR::VectorReg(inst.src[0].code),
1823
IR::VectorReg(inst.src[1].code),

src/shader_recompiler/ir/passes/resource_tracking_pass.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,35 @@ bool IsImageInstruction(const IR::Inst& inst) {
137137
}
138138
}
139139

140+
IR::Value SwizzleVector(IR::IREmitter& ir, auto sharp, IR::Value texel) {
141+
boost::container::static_vector<IR::Value, 4> comps;
142+
for (u32 i = 0; i < 4; i++) {
143+
switch (sharp.GetSwizzle(i)) {
144+
case AmdGpu::CompSwizzle::Zero:
145+
comps.emplace_back(ir.Imm32(0.f));
146+
break;
147+
case AmdGpu::CompSwizzle::One:
148+
comps.emplace_back(ir.Imm32(1.f));
149+
break;
150+
case AmdGpu::CompSwizzle::Red:
151+
comps.emplace_back(ir.CompositeExtract(texel, 0));
152+
break;
153+
case AmdGpu::CompSwizzle::Green:
154+
comps.emplace_back(ir.CompositeExtract(texel, 1));
155+
break;
156+
case AmdGpu::CompSwizzle::Blue:
157+
comps.emplace_back(ir.CompositeExtract(texel, 2));
158+
break;
159+
case AmdGpu::CompSwizzle::Alpha:
160+
comps.emplace_back(ir.CompositeExtract(texel, 3));
161+
break;
162+
default:
163+
UNREACHABLE();
164+
}
165+
}
166+
return ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]);
167+
};
168+
140169
class Descriptors {
141170
public:
142171
explicit Descriptors(Info& info_)
@@ -388,6 +417,15 @@ void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
388417
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
389418
inst.SetArg(0, ir.Imm32(binding));
390419
ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable);
420+
421+
// Apply dst_sel swizzle on formatted buffer instructions
422+
if (inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32) {
423+
inst.SetArg(2, SwizzleVector(ir, buffer, inst.Arg(2)));
424+
} else {
425+
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
426+
const auto texel = ir.LoadBufferFormat(inst.Arg(0), inst.Arg(1), inst_info);
427+
inst.ReplaceUsesWith(SwizzleVector(ir, buffer, texel));
428+
}
391429
}
392430

393431
IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t,
@@ -732,6 +770,10 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
732770
}();
733771
inst.SetArg(1, coords);
734772

773+
if (inst.GetOpcode() == IR::Opcode::ImageWrite) {
774+
inst.SetArg(2, SwizzleVector(ir, image, inst.Arg(2)));
775+
}
776+
735777
if (inst_info.has_lod) {
736778
ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch);
737779
ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa &&

src/shader_recompiler/specialization.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,20 @@ struct BufferSpecialization {
3131

3232
struct TextureBufferSpecialization {
3333
bool is_integer = false;
34+
u32 dst_select = 0;
3435

3536
auto operator<=>(const TextureBufferSpecialization&) const = default;
3637
};
3738

3839
struct ImageSpecialization {
3940
AmdGpu::ImageType type = AmdGpu::ImageType::Color2D;
4041
bool is_integer = false;
42+
u32 dst_select = 0;
4143

42-
auto operator<=>(const ImageSpecialization&) const = default;
44+
bool operator==(const ImageSpecialization& other) const {
45+
return type == other.type && is_integer == other.is_integer &&
46+
(dst_select != 0 ? dst_select == other.dst_select : true);
47+
}
4348
};
4449

4550
struct FMaskSpecialization {
@@ -103,11 +108,15 @@ struct StageSpecialization {
103108
ForEachSharp(binding, tex_buffers, info->texture_buffers,
104109
[](auto& spec, const auto& desc, AmdGpu::Buffer sharp) {
105110
spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt());
111+
spec.dst_select = sharp.DstSelect();
106112
});
107113
ForEachSharp(binding, images, info->images,
108114
[](auto& spec, const auto& desc, AmdGpu::Image sharp) {
109115
spec.type = sharp.GetBoundType();
110116
spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt());
117+
if (desc.is_storage) {
118+
spec.dst_select = sharp.DstSelect();
119+
}
111120
});
112121
ForEachSharp(binding, fmasks, info->fmasks,
113122
[](auto& spec, const auto& desc, AmdGpu::Image sharp) {

src/video_core/amdgpu/resource.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ struct Buffer {
5252
return std::memcmp(this, &other, sizeof(Buffer)) == 0;
5353
}
5454

55+
u32 DstSelect() const {
56+
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9);
57+
}
58+
5559
CompSwizzle GetSwizzle(u32 comp) const noexcept {
5660
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w};
5761
return static_cast<CompSwizzle>(select[comp]);
@@ -204,6 +208,11 @@ struct Image {
204208
return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9);
205209
}
206210

211+
CompSwizzle GetSwizzle(u32 comp) const noexcept {
212+
const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w};
213+
return static_cast<CompSwizzle>(select[comp]);
214+
}
215+
207216
static char SelectComp(u32 sel) {
208217
switch (sel) {
209218
case 0:

src/video_core/renderer_vulkan/liverpool_to_vk.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -699,15 +699,6 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format,
699699
default:
700700
break;
701701
}
702-
} else if (comp_swap_reverse) {
703-
switch (base_format) {
704-
case vk::Format::eR8G8B8A8Unorm:
705-
return vk::Format::eA8B8G8R8UnormPack32;
706-
case vk::Format::eR8G8B8A8Srgb:
707-
return vk::Format::eA8B8G8R8SrgbPack32;
708-
default:
709-
break;
710-
}
711702
}
712703
return base_format;
713704
}

src/video_core/texture_cache/image_view.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -50,34 +50,6 @@ vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) {
5050
}
5151
}
5252

53-
bool IsIdentityMapping(u32 dst_sel, u32 num_components) {
54-
return (num_components == 1 && dst_sel == 0b001'000'000'100) ||
55-
(num_components == 2 && dst_sel == 0b001'000'101'100) ||
56-
(num_components == 3 && dst_sel == 0b001'110'101'100) ||
57-
(num_components == 4 && dst_sel == 0b111'110'101'100);
58-
}
59-
60-
vk::Format TrySwizzleFormat(vk::Format format, u32 dst_sel) {
61-
// BGRA
62-
if (dst_sel == 0b111100101110) {
63-
switch (format) {
64-
case vk::Format::eR8G8B8A8Unorm:
65-
return vk::Format::eB8G8R8A8Unorm;
66-
case vk::Format::eR8G8B8A8Snorm:
67-
return vk::Format::eB8G8R8A8Snorm;
68-
case vk::Format::eR8G8B8A8Uint:
69-
return vk::Format::eB8G8R8A8Uint;
70-
case vk::Format::eR8G8B8A8Sint:
71-
return vk::Format::eB8G8R8A8Sint;
72-
case vk::Format::eR8G8B8A8Srgb:
73-
return vk::Format::eB8G8R8A8Srgb;
74-
default:
75-
break;
76-
}
77-
}
78-
return format;
79-
}
80-
8153
ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept
8254
: is_storage{desc.is_storage} {
8355
const auto dfmt = image.GetDataFmt();
@@ -120,17 +92,6 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
12092
mapping.b = ConvertComponentSwizzle(image.dst_sel_z);
12193
mapping.a = ConvertComponentSwizzle(image.dst_sel_w);
12294
}
123-
// Check for unfortunate case of storage images being swizzled
124-
const u32 num_comps = AmdGpu::NumComponents(image.GetDataFmt());
125-
const u32 dst_sel = image.DstSelect();
126-
if (is_storage && !IsIdentityMapping(dst_sel, num_comps)) {
127-
if (auto new_format = TrySwizzleFormat(format, dst_sel); new_format != format) {
128-
format = new_format;
129-
return;
130-
}
131-
LOG_ERROR(Render_Vulkan, "Storage image (num_comps = {}) requires swizzling {}", num_comps,
132-
image.DstSelectName());
133-
}
13495
}
13596

13697
ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) noexcept {

0 commit comments

Comments
 (0)