summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode/image.cpp360
-rw-r--r--src/video_core/shader/shader_ir.h4
-rw-r--r--src/video_core/texture_cache/surface_params.cpp6
3 files changed, 355 insertions, 15 deletions
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index d2fe4ec5d..0dd7a1196 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -13,13 +13,247 @@
13#include "video_core/engines/shader_bytecode.h" 13#include "video_core/engines/shader_bytecode.h"
14#include "video_core/shader/node_helper.h" 14#include "video_core/shader/node_helper.h"
15#include "video_core/shader/shader_ir.h" 15#include "video_core/shader/shader_ir.h"
16#include "video_core/textures/texture.h"
16 17
17namespace VideoCommon::Shader { 18namespace VideoCommon::Shader {
18 19
19using Tegra::Shader::Instruction; 20using Tegra::Shader::Instruction;
20using Tegra::Shader::OpCode; 21using Tegra::Shader::OpCode;
22using Tegra::Shader::PredCondition;
23using Tegra::Shader::StoreType;
24using Tegra::Texture::ComponentType;
25using Tegra::Texture::TextureFormat;
26using Tegra::Texture::TICEntry;
21 27
22namespace { 28namespace {
29
30ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
31 std::size_t component) {
32 const TextureFormat format{descriptor.format};
33 switch (format) {
34 case TextureFormat::R16_G16_B16_A16:
35 case TextureFormat::R32_G32_B32_A32:
36 case TextureFormat::R32_G32_B32:
37 case TextureFormat::R32_G32:
38 case TextureFormat::R16_G16:
39 case TextureFormat::R32:
40 case TextureFormat::R16:
41 case TextureFormat::R8:
42 case TextureFormat::R1:
43 if (component == 0) {
44 return descriptor.r_type;
45 }
46 if (component == 1) {
47 return descriptor.g_type;
48 }
49 if (component == 2) {
50 return descriptor.b_type;
51 }
52 if (component == 3) {
53 return descriptor.a_type;
54 }
55 break;
56 case TextureFormat::A8R8G8B8:
57 if (component == 0) {
58 return descriptor.a_type;
59 }
60 if (component == 1) {
61 return descriptor.r_type;
62 }
63 if (component == 2) {
64 return descriptor.g_type;
65 }
66 if (component == 3) {
67 return descriptor.b_type;
68 }
69 break;
70 case TextureFormat::A2B10G10R10:
71 case TextureFormat::A4B4G4R4:
72 case TextureFormat::A5B5G5R1:
73 case TextureFormat::A1B5G5R5:
74 if (component == 0) {
75 return descriptor.a_type;
76 }
77 if (component == 1) {
78 return descriptor.b_type;
79 }
80 if (component == 2) {
81 return descriptor.g_type;
82 }
83 if (component == 3) {
84 return descriptor.r_type;
85 }
86 break;
87 case TextureFormat::R32_B24G8:
88 if (component == 0) {
89 return descriptor.r_type;
90 }
91 if (component == 1) {
92 return descriptor.b_type;
93 }
94 if (component == 2) {
95 return descriptor.g_type;
96 }
97 break;
98 case TextureFormat::B5G6R5:
99 case TextureFormat::B6G5R5:
100 if (component == 0) {
101 return descriptor.b_type;
102 }
103 if (component == 1) {
104 return descriptor.g_type;
105 }
106 if (component == 2) {
107 return descriptor.r_type;
108 }
109 break;
110 case TextureFormat::G8R24:
111 case TextureFormat::G24R8:
112 case TextureFormat::G8R8:
113 case TextureFormat::G4R4:
114 if (component == 0) {
115 return descriptor.g_type;
116 }
117 if (component == 1) {
118 return descriptor.r_type;
119 }
120 break;
121 }
122 UNIMPLEMENTED_MSG("texture format not implement={}", format);
123 return ComponentType::FLOAT;
124}
125
126bool IsComponentEnabled(std::size_t component_mask, std::size_t component) {
127 constexpr u8 R = 0b0001;
128 constexpr u8 G = 0b0010;
129 constexpr u8 B = 0b0100;
130 constexpr u8 A = 0b1000;
131 constexpr std::array<u8, 16> mask = {
132 0, (R), (G), (R | G), (B), (R | B), (G | B), (R | G | B),
133 (A), (R | A), (G | A), (R | G | A), (B | A), (R | B | A), (G | B | A), (R | G | B | A)};
134 return std::bitset<4>{mask.at(component_mask)}.test(component);
135}
136
137u32 GetComponentSize(TextureFormat format, std::size_t component) {
138 switch (format) {
139 case TextureFormat::R32_G32_B32_A32:
140 return 32;
141 case TextureFormat::R16_G16_B16_A16:
142 return 16;
143 case TextureFormat::R32_G32_B32:
144 return component <= 2 ? 32 : 0;
145 case TextureFormat::R32_G32:
146 return component <= 1 ? 32 : 0;
147 case TextureFormat::R16_G16:
148 return component <= 1 ? 16 : 0;
149 case TextureFormat::R32:
150 return component == 0 ? 32 : 0;
151 case TextureFormat::R16:
152 return component == 0 ? 16 : 0;
153 case TextureFormat::R8:
154 return component == 0 ? 8 : 0;
155 case TextureFormat::R1:
156 return component == 0 ? 1 : 0;
157 case TextureFormat::A8R8G8B8:
158 return 8;
159 case TextureFormat::A2B10G10R10:
160 return (component == 3 || component == 2 || component == 1) ? 10 : 2;
161 case TextureFormat::A4B4G4R4:
162 return 4;
163 case TextureFormat::A5B5G5R1:
164 return (component == 0 || component == 1 || component == 2) ? 5 : 1;
165 case TextureFormat::A1B5G5R5:
166 return (component == 1 || component == 2 || component == 3) ? 5 : 1;
167 case TextureFormat::R32_B24G8:
168 if (component == 0) {
169 return 32;
170 }
171 if (component == 1) {
172 return 24;
173 }
174 if (component == 2) {
175 return 8;
176 }
177 return 0;
178 case TextureFormat::B5G6R5:
179 if (component == 0 || component == 2) {
180 return 5;
181 }
182 if (component == 1) {
183 return 6;
184 }
185 return 0;
186 case TextureFormat::B6G5R5:
187 if (component == 1 || component == 2) {
188 return 5;
189 }
190 if (component == 0) {
191 return 6;
192 }
193 return 0;
194 case TextureFormat::G8R24:
195 if (component == 0) {
196 return 8;
197 }
198 if (component == 1) {
199 return 24;
200 }
201 return 0;
202 case TextureFormat::G24R8:
203 if (component == 0) {
204 return 8;
205 }
206 if (component == 1) {
207 return 24;
208 }
209 return 0;
210 case TextureFormat::G8R8:
211 return (component == 0 || component == 1) ? 8 : 0;
212 case TextureFormat::G4R4:
213 return (component == 0 || component == 1) ? 4 : 0;
214 default:
215 UNIMPLEMENTED_MSG("texture format not implement={}", format);
216 return 0;
217 }
218}
219
220std::size_t GetImageComponentMask(TextureFormat format) {
221 constexpr u8 R = 0b0001;
222 constexpr u8 G = 0b0010;
223 constexpr u8 B = 0b0100;
224 constexpr u8 A = 0b1000;
225 switch (format) {
226 case TextureFormat::R32_G32_B32_A32:
227 case TextureFormat::R16_G16_B16_A16:
228 case TextureFormat::A8R8G8B8:
229 case TextureFormat::A2B10G10R10:
230 case TextureFormat::A4B4G4R4:
231 case TextureFormat::A5B5G5R1:
232 case TextureFormat::A1B5G5R5:
233 return std::size_t{R | G | B | A};
234 case TextureFormat::R32_G32_B32:
235 case TextureFormat::R32_B24G8:
236 case TextureFormat::B5G6R5:
237 case TextureFormat::B6G5R5:
238 return std::size_t{R | G | B};
239 case TextureFormat::R32_G32:
240 case TextureFormat::R16_G16:
241 case TextureFormat::G8R24:
242 case TextureFormat::G24R8:
243 case TextureFormat::G8R8:
244 case TextureFormat::G4R4:
245 return std::size_t{R | G};
246 case TextureFormat::R32:
247 case TextureFormat::R16:
248 case TextureFormat::R8:
249 case TextureFormat::R1:
250 return std::size_t{R};
251 default:
252 UNIMPLEMENTED_MSG("texture format not implement={}", format);
253 return std::size_t{R | G | B | A};
254 }
255}
256
23std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) { 257std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) {
24 switch (image_type) { 258 switch (image_type) {
25 case Tegra::Shader::ImageType::Texture1D: 259 case Tegra::Shader::ImageType::Texture1D:
@@ -37,6 +271,39 @@ std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) {
37} 271}
38} // Anonymous namespace 272} // Anonymous namespace
39 273
274std::pair<Node, bool> ShaderIR::GetComponentValue(ComponentType component_type, u32 component_size,
275 Node original_value) {
276 switch (component_type) {
277 case ComponentType::SNORM: {
278 // range [-1.0, 1.0]
279 auto cnv_value = Operation(OperationCode::FMul, original_value,
280 Immediate(static_cast<float>(1 << component_size) / 2.f - 1.f));
281 cnv_value = Operation(OperationCode::ICastFloat, std::move(cnv_value));
282 return {BitfieldExtract(std::move(cnv_value), 0, component_size), true};
283 }
284 case ComponentType::SINT:
285 case ComponentType::UNORM: {
286 bool is_signed = component_type == ComponentType::SINT;
287 // range [0.0, 1.0]
288 auto cnv_value = Operation(OperationCode::FMul, original_value,
289 Immediate(static_cast<float>(1 << component_size) - 1.f));
290 return {SignedOperation(OperationCode::ICastFloat, is_signed, std::move(cnv_value)),
291 is_signed};
292 }
293 case ComponentType::UINT: // range [0, (1 << component_size) - 1]
294 return {std::move(original_value), false};
295 case ComponentType::FLOAT:
296 if (component_size == 16) {
297 return {Operation(OperationCode::HCastFloat, original_value), true};
298 } else {
299 return {std::move(original_value), true};
300 }
301 default:
302 UNIMPLEMENTED_MSG("Unimplement component type={}", component_type);
303 return {std::move(original_value), true};
304 }
305}
306
40u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { 307u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
41 const Instruction instr = {program_code[pc]}; 308 const Instruction instr = {program_code[pc]};
42 const auto opcode = OpCode::Decode(instr); 309 const auto opcode = OpCode::Decode(instr);
@@ -53,7 +320,6 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
53 320
54 switch (opcode->get().GetId()) { 321 switch (opcode->get().GetId()) {
55 case OpCode::Id::SULD: { 322 case OpCode::Id::SULD: {
56 UNIMPLEMENTED_IF(instr.suldst.mode != Tegra::Shader::SurfaceDataMode::P);
57 UNIMPLEMENTED_IF(instr.suldst.out_of_bounds_store != 323 UNIMPLEMENTED_IF(instr.suldst.out_of_bounds_store !=
58 Tegra::Shader::OutOfBoundsStore::Ignore); 324 Tegra::Shader::OutOfBoundsStore::Ignore);
59 325
@@ -62,17 +328,89 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
62 : GetBindlessImage(instr.gpr39, type)}; 328 : GetBindlessImage(instr.gpr39, type)};
63 image.MarkRead(); 329 image.MarkRead();
64 330
65 u32 indexer = 0; 331 if (instr.suldst.mode == Tegra::Shader::SurfaceDataMode::P) {
66 for (u32 element = 0; element < 4; ++element) { 332 u32 indexer = 0;
67 if (!instr.suldst.IsComponentEnabled(element)) { 333 for (u32 element = 0; element < 4; ++element) {
68 continue; 334 if (!instr.suldst.IsComponentEnabled(element)) {
335 continue;
336 }
337 MetaImage meta{image, {}, element};
338 Node value = Operation(OperationCode::ImageLoad, meta, GetCoordinates(type));
339 SetTemporary(bb, indexer++, std::move(value));
340 }
341 for (u32 i = 0; i < indexer; ++i) {
342 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
343 }
344 } else if (instr.suldst.mode == Tegra::Shader::SurfaceDataMode::D_BA) {
345 UNIMPLEMENTED_IF(instr.suldst.GetStoreDataLayout() != StoreType::Bits32 &&
346 instr.suldst.GetStoreDataLayout() != StoreType::Bits64);
347
348 auto descriptor = [this, instr] {
349 std::optional<Tegra::Engines::SamplerDescriptor> descriptor;
350 if (instr.suldst.is_immediate) {
351 descriptor =
352 registry.ObtainBoundSampler(static_cast<u32>(instr.image.index.Value()));
353 } else {
354 const Node image_register = GetRegister(instr.gpr39);
355 const auto [base_image, buffer, offset] = TrackCbuf(
356 image_register, global_code, static_cast<s64>(global_code.size()));
357 descriptor = registry.ObtainBindlessSampler(buffer, offset);
358 }
359 if (!descriptor) {
360 UNREACHABLE_MSG("Failed to obtain image descriptor");
361 }
362 return *descriptor;
363 }();
364
365 const auto comp_mask = GetImageComponentMask(descriptor.format);
366
367 switch (instr.suldst.GetStoreDataLayout()) {
368 case StoreType::Bits32:
369 case StoreType::Bits64: {
370 u32 indexer = 0;
371 u32 shifted_counter = 0;
372 Node value = Immediate(0);
373 for (u32 element = 0; element < 4; ++element) {
374 if (!IsComponentEnabled(comp_mask, element)) {
375 continue;
376 }
377 const auto component_type = GetComponentType(descriptor, element);
378 const auto component_size = GetComponentSize(descriptor.format, element);
379 MetaImage meta{image, {}, element};
380
381 auto [converted_value, is_signed] = GetComponentValue(
382 component_type, component_size,
383 Operation(OperationCode::ImageLoad, meta, GetCoordinates(type)));
384
385 // shift element to correct position
386 const auto shifted = shifted_counter;
387 if (shifted > 0) {
388 converted_value =
389 SignedOperation(OperationCode::ILogicalShiftLeft, is_signed,
390 std::move(converted_value), Immediate(shifted));
391 }
392 shifted_counter += component_size;
393
394 // add value into result
395 value = Operation(OperationCode::UBitwiseOr, value, std::move(converted_value));
396
397 // if we shifted enough for 1 byte -> we save it into temp
398 if (shifted_counter >= 32) {
399 SetTemporary(bb, indexer++, std::move(value));
400 // reset counter and value to prepare pack next byte
401 value = Immediate(0);
402 shifted_counter = 0;
403 }
404 }
405 for (u32 i = 0; i < indexer; ++i) {
406 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
407 }
408 break;
409 }
410 default:
411 UNREACHABLE();
412 break;
69 } 413 }
70 MetaImage meta{image, {}, element};
71 Node value = Operation(OperationCode::ImageLoad, meta, GetCoordinates(type));
72 SetTemporary(bb, indexer++, std::move(value));
73 }
74 for (u32 i = 0; i < indexer; ++i) {
75 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
76 } 414 }
77 break; 415 break;
78 } 416 }
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 80fc9b82c..ca6c976c9 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -312,6 +312,10 @@ private:
312 /// Conditionally saturates a half float pair 312 /// Conditionally saturates a half float pair
313 Node GetSaturatedHalfFloat(Node value, bool saturate = true); 313 Node GetSaturatedHalfFloat(Node value, bool saturate = true);
314 314
315 /// Get image component value by type and size
316 std::pair<Node, bool> GetComponentValue(Tegra::Texture::ComponentType component_type,
317 u32 component_size, Node original_value);
318
315 /// Returns a predicate comparing two floats 319 /// Returns a predicate comparing two floats
316 Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b); 320 Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
317 /// Returns a predicate comparing two integers 321 /// Returns a predicate comparing two integers
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 47b2aafbd..6f3ef45be 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -113,10 +113,8 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
113 params.height = tic.Height(); 113 params.height = tic.Height();
114 params.depth = tic.Depth(); 114 params.depth = tic.Depth();
115 params.pitch = params.is_tiled ? 0 : tic.Pitch(); 115 params.pitch = params.is_tiled ? 0 : tic.Pitch();
116 if (params.target == SurfaceTarget::Texture2D && params.depth > 1) { 116 if (params.target == SurfaceTarget::TextureCubemap ||
117 params.depth = 1; 117 params.target == SurfaceTarget::TextureCubeArray) {
118 } else if (params.target == SurfaceTarget::TextureCubemap ||
119 params.target == SurfaceTarget::TextureCubeArray) {
120 params.depth *= 6; 118 params.depth *= 6;
121 } 119 }
122 params.num_levels = tic.max_mip_level + 1; 120 params.num_levels = tic.max_mip_level + 1;