7
7
8
8
namespace Shader ::Gcn {
9
9
10
+ u32 SwizzleMrtComponent (const FragmentRuntimeInfo::PsColorBuffer& color_buffer, u32 comp) {
11
+ const auto [r, g, b, a] = color_buffer.swizzle ;
12
+ const std::array swizzle_array = {r, g, b, a};
13
+ const auto swizzled_comp_type = static_cast <u32 >(swizzle_array[comp]);
14
+ constexpr auto min_comp_type = static_cast <u32 >(AmdGpu::CompSwizzle::Red);
15
+ return swizzled_comp_type >= min_comp_type ? swizzled_comp_type - min_comp_type : comp;
16
+ }
17
+
18
+ void Translator::ExportMrtValue (IR::Attribute attribute, u32 comp, const IR::F32& value,
19
+ const FragmentRuntimeInfo::PsColorBuffer& color_buffer) {
20
+ const auto converted = ApplyWriteNumberConversion (ir, value, color_buffer.num_conversion );
21
+ ir.SetAttribute (attribute, converted, comp);
22
+ }
23
+
24
+ void Translator::ExportMrtCompressed (IR::Attribute attribute, u32 idx, const IR::U32& value) {
25
+ const u32 color_buffer_idx =
26
+ static_cast <u32 >(attribute) - static_cast <u32 >(IR::Attribute::RenderTarget0);
27
+ const auto color_buffer = runtime_info.fs_info .color_buffers [color_buffer_idx];
28
+
29
+ IR::Value unpacked_value;
30
+ bool is_integer = false ;
31
+ switch (color_buffer.export_format ) {
32
+ case AmdGpu::Liverpool::ShaderExportFormat::Zero:
33
+ // No export
34
+ return ;
35
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_FP16:
36
+ unpacked_value = ir.UnpackHalf2x16 (value);
37
+ break ;
38
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_UNORM16:
39
+ unpacked_value = ir.UnpackUnorm2x16 (value);
40
+ break ;
41
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_SNORM16:
42
+ unpacked_value = ir.UnpackSnorm2x16 (value);
43
+ break ;
44
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_UINT16:
45
+ unpacked_value = ir.UnpackUint2x16 (value);
46
+ is_integer = true ;
47
+ break ;
48
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_SINT16:
49
+ unpacked_value = ir.UnpackSint2x16 (value);
50
+ is_integer = true ;
51
+ break ;
52
+ default :
53
+ UNREACHABLE_MSG (" Unimplemented compressed MRT export format {}" ,
54
+ static_cast <u32 >(color_buffer.export_format ));
55
+ break ;
56
+ }
57
+
58
+ const auto r = ir.CompositeExtract (unpacked_value, 0 );
59
+ const auto g = ir.CompositeExtract (unpacked_value, 1 );
60
+ const IR::F32 float_r = is_integer ? ir.BitCast <IR::F32>(IR::U32{r}) : IR::F32{r};
61
+ const IR::F32 float_g = is_integer ? ir.BitCast <IR::F32>(IR::U32{g}) : IR::F32{g};
62
+
63
+ const auto swizzled_r = SwizzleMrtComponent (color_buffer, idx * 2 );
64
+ const auto swizzled_g = SwizzleMrtComponent (color_buffer, idx * 2 + 1 );
65
+
66
+ ExportMrtValue (attribute, swizzled_r, float_r, color_buffer);
67
+ ExportMrtValue (attribute, swizzled_g, float_g, color_buffer);
68
+ }
69
+
70
+ void Translator::ExportMrtUncompressed (IR::Attribute attribute, u32 comp, const IR::F32& value) {
71
+ const u32 color_buffer_idx =
72
+ static_cast <u32 >(attribute) - static_cast <u32 >(IR::Attribute::RenderTarget0);
73
+ const auto color_buffer = runtime_info.fs_info .color_buffers [color_buffer_idx];
74
+ const auto swizzled_comp = SwizzleMrtComponent (color_buffer, comp);
75
+
76
+ switch (color_buffer.export_format ) {
77
+ case AmdGpu::Liverpool::ShaderExportFormat::Zero:
78
+ // No export
79
+ return ;
80
+ case AmdGpu::Liverpool::ShaderExportFormat::R_32:
81
+ // Red only
82
+ if (swizzled_comp != 0 ) {
83
+ return ;
84
+ }
85
+ break ;
86
+ case AmdGpu::Liverpool::ShaderExportFormat::GR_32:
87
+ // Red and Green only
88
+ if (swizzled_comp != 0 && swizzled_comp != 1 ) {
89
+ return ;
90
+ }
91
+ break ;
92
+ case AmdGpu::Liverpool::ShaderExportFormat::AR_32:
93
+ // Red and Alpha only
94
+ if (swizzled_comp != 0 && swizzled_comp != 3 ) {
95
+ return ;
96
+ }
97
+ break ;
98
+ case AmdGpu::Liverpool::ShaderExportFormat::ABGR_32:
99
+ // All components
100
+ break ;
101
+ default :
102
+ UNREACHABLE_MSG (" Unimplemented uncompressed MRT export format {}" ,
103
+ static_cast <u32 >(color_buffer.export_format ));
104
+ break ;
105
+ }
106
+ ExportMrtValue (attribute, swizzled_comp, value, color_buffer);
107
+ }
108
+
109
+ void Translator::ExportCompressed (IR::Attribute attribute, u32 idx, const IR::U32& value) {
110
+ if (IsMrt (attribute)) {
111
+ ExportMrtCompressed (attribute, idx, value);
112
+ return ;
113
+ }
114
+ const IR::Value unpacked_value = ir.UnpackHalf2x16 (value);
115
+ const IR::F32 r = IR::F32{ir.CompositeExtract (unpacked_value, 0 )};
116
+ const IR::F32 g = IR::F32{ir.CompositeExtract (unpacked_value, 1 )};
117
+ ir.SetAttribute (attribute, r, idx * 2 );
118
+ ir.SetAttribute (attribute, g, idx * 2 + 1 );
119
+ }
120
+
121
+ void Translator::ExportUncompressed (IR::Attribute attribute, u32 comp, const IR::F32& value) {
122
+ if (IsMrt (attribute)) {
123
+ ExportMrtUncompressed (attribute, comp, value);
124
+ return ;
125
+ }
126
+ ir.SetAttribute (attribute, value, comp);
127
+ }
128
+
10
129
void Translator::EmitExport (const GcnInst& inst) {
11
130
if (ir.block ->has_multiple_predecessors && info.stage == Stage::Fragment) {
12
131
ir.Discard (ir.LogicalNot (ir.GetExec ()));
@@ -26,41 +145,15 @@ void Translator::EmitExport(const GcnInst& inst) {
26
145
IR::VectorReg (inst.src [3 ].code ),
27
146
};
28
147
29
- const auto set_attribute = [&](u32 comp, IR::F32 value) {
30
- if (!IR::IsMrt (attrib)) {
31
- ir.SetAttribute (attrib, value, comp);
32
- return ;
33
- }
34
- const u32 index = u32 (attrib) - u32 (IR::Attribute::RenderTarget0);
35
- const auto col_buf = runtime_info.fs_info .color_buffers [index];
36
- const auto converted = IR::ApplyWriteNumberConversion (ir, value, col_buf.num_conversion );
37
- const auto [r, g, b, a] = col_buf.swizzle ;
38
- const std::array swizzle_array = {r, g, b, a};
39
- const auto swizzled_comp = swizzle_array[comp];
40
- if (u32 (swizzled_comp) < u32 (AmdGpu::CompSwizzle::Red)) {
41
- ir.SetAttribute (attrib, converted, comp);
42
- return ;
43
- }
44
- ir.SetAttribute (attrib, converted, u32 (swizzled_comp) - u32 (AmdGpu::CompSwizzle::Red));
45
- };
46
-
47
- const auto unpack = [&](u32 idx) {
48
- const IR::Value value = ir.UnpackHalf2x16 (ir.GetVectorReg (vsrc[idx]));
49
- const IR::F32 r = IR::F32{ir.CompositeExtract (value, 0 )};
50
- const IR::F32 g = IR::F32{ir.CompositeExtract (value, 1 )};
51
- set_attribute (idx * 2 , r);
52
- set_attribute (idx * 2 + 1 , g);
53
- };
54
-
55
148
// Components are float16 packed into a VGPR
56
149
if (exp.compr ) {
57
150
// Export R, G
58
151
if (exp.en & 1 ) {
59
- unpack ( 0 );
152
+ ExportCompressed (attrib, 0 , ir. GetVectorReg <IR::U32>(vsrc[ 0 ]) );
60
153
}
61
154
// Export B, A
62
155
if ((exp.en >> 2 ) & 1 ) {
63
- unpack ( 1 );
156
+ ExportCompressed (attrib, 1 , ir. GetVectorReg <IR::U32>(vsrc[ 1 ]) );
64
157
}
65
158
} else {
66
159
// Components are float32 into separate VGPRS
@@ -69,8 +162,7 @@ void Translator::EmitExport(const GcnInst& inst) {
69
162
if ((mask & 1 ) == 0 ) {
70
163
continue ;
71
164
}
72
- const IR::F32 comp = ir.GetVectorReg <IR::F32>(vsrc[i]);
73
- set_attribute (i, comp);
165
+ ExportUncompressed (attrib, i, ir.GetVectorReg <IR::F32>(vsrc[i]));
74
166
}
75
167
}
76
168
if (IR::IsMrt (attrib)) {
0 commit comments