summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/texture_pass.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-04-22 16:17:59 -0300
committerGravatar ameerj2021-07-22 21:51:28 -0400
commitd10cf55353175b13bed4cf18791e080ecb7fd95b (patch)
tree9e26b823d7b48f532914a0511a157c14806debf5 /src/shader_recompiler/ir_opt/texture_pass.cpp
parentshader: Refactor atomic_operations_global_memory (diff)
downloadyuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.tar.gz
yuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.tar.xz
yuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.zip
shader: Implement indexed textures
Diffstat (limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp89
1 files changed, 72 insertions, 17 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index 5ac485522..cfa6b34b9 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <bit>
6#include <optional> 7#include <optional>
7 8
8#include <boost/container/small_vector.hpp> 9#include <boost/container/small_vector.hpp>
@@ -21,6 +22,8 @@ struct ConstBufferAddr {
21 u32 offset; 22 u32 offset;
22 u32 secondary_index; 23 u32 secondary_index;
23 u32 secondary_offset; 24 u32 secondary_offset;
25 IR::U32 dynamic_offset;
26 u32 count;
24 bool has_secondary; 27 bool has_secondary;
25}; 28};
26 29
@@ -32,6 +35,9 @@ struct TextureInst {
32 35
33using TextureInstVector = boost::container::small_vector<TextureInst, 24>; 36using TextureInstVector = boost::container::small_vector<TextureInst, 24>;
34 37
38constexpr u32 DESCRIPTOR_SIZE = 8;
39constexpr u32 DESCRIPTOR_SIZE_SHIFT = static_cast<u32>(std::countr_zero(DESCRIPTOR_SIZE));
40
35IR::Opcode IndexedInstruction(const IR::Inst& inst) { 41IR::Opcode IndexedInstruction(const IR::Inst& inst) {
36 switch (inst.GetOpcode()) { 42 switch (inst.GetOpcode()) {
37 case IR::Opcode::BindlessImageSampleImplicitLod: 43 case IR::Opcode::BindlessImageSampleImplicitLod:
@@ -131,6 +137,9 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
131 if (lhs->has_secondary || rhs->has_secondary) { 137 if (lhs->has_secondary || rhs->has_secondary) {
132 return std::nullopt; 138 return std::nullopt;
133 } 139 }
140 if (lhs->count > 1 || rhs->count > 1) {
141 return std::nullopt;
142 }
134 if (lhs->index > rhs->index || lhs->offset > rhs->offset) { 143 if (lhs->index > rhs->index || lhs->offset > rhs->offset) {
135 std::swap(lhs, rhs); 144 std::swap(lhs, rhs);
136 } 145 }
@@ -139,9 +148,12 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
139 .offset = lhs->offset, 148 .offset = lhs->offset,
140 .secondary_index = rhs->index, 149 .secondary_index = rhs->index,
141 .secondary_offset = rhs->offset, 150 .secondary_offset = rhs->offset,
151 .dynamic_offset = {},
152 .count = 1,
142 .has_secondary = true, 153 .has_secondary = true,
143 }; 154 };
144 } 155 }
156 case IR::Opcode::GetCbufU32x2:
145 case IR::Opcode::GetCbufU32: 157 case IR::Opcode::GetCbufU32:
146 break; 158 break;
147 } 159 }
@@ -152,15 +164,39 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
152 // but not supported here at the moment 164 // but not supported here at the moment
153 return std::nullopt; 165 return std::nullopt;
154 } 166 }
155 if (!offset.IsImmediate()) { 167 if (offset.IsImmediate()) {
156 // TODO: Support arrays of textures 168 return ConstBufferAddr{
169 .index = index.U32(),
170 .offset = offset.U32(),
171 .secondary_index = 0,
172 .secondary_offset = 0,
173 .dynamic_offset = {},
174 .count = 1,
175 .has_secondary = false,
176 };
177 }
178 IR::Inst* const offset_inst{offset.InstRecursive()};
179 if (offset_inst->GetOpcode() != IR::Opcode::IAdd32) {
180 return std::nullopt;
181 }
182 u32 base_offset{};
183 IR::U32 dynamic_offset;
184 if (offset_inst->Arg(0).IsImmediate()) {
185 base_offset = offset_inst->Arg(0).U32();
186 dynamic_offset = IR::U32{offset_inst->Arg(1)};
187 } else if (offset_inst->Arg(1).IsImmediate()) {
188 base_offset = offset_inst->Arg(1).U32();
189 dynamic_offset = IR::U32{offset_inst->Arg(0)};
190 } else {
157 return std::nullopt; 191 return std::nullopt;
158 } 192 }
159 return ConstBufferAddr{ 193 return ConstBufferAddr{
160 .index{index.U32()}, 194 .index = index.U32(),
161 .offset{offset.U32()}, 195 .offset = base_offset,
162 .secondary_index = 0, 196 .secondary_index = 0,
163 .secondary_offset = 0, 197 .secondary_offset = 0,
198 .dynamic_offset = dynamic_offset,
199 .count = 8,
164 .has_secondary = false, 200 .has_secondary = false,
165 }; 201 };
166} 202}
@@ -179,11 +215,13 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
179 .offset = inst.Arg(0).U32(), 215 .offset = inst.Arg(0).U32(),
180 .secondary_index = 0, 216 .secondary_index = 0,
181 .secondary_offset = 0, 217 .secondary_offset = 0,
218 .dynamic_offset = {},
219 .count = 1,
182 .has_secondary = false, 220 .has_secondary = false,
183 }; 221 };
184 } 222 }
185 return TextureInst{ 223 return TextureInst{
186 .cbuf{addr}, 224 .cbuf = addr,
187 .inst = &inst, 225 .inst = &inst,
188 .block = block, 226 .block = block,
189 }; 227 };
@@ -209,18 +247,20 @@ public:
209 247
210 u32 Add(const TextureBufferDescriptor& desc) { 248 u32 Add(const TextureBufferDescriptor& desc) {
211 return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { 249 return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) {
212 return desc.has_secondary == existing.has_secondary && 250 return desc.cbuf_index == existing.cbuf_index &&
213 desc.cbuf_index == existing.cbuf_index &&
214 desc.cbuf_offset == existing.cbuf_offset && 251 desc.cbuf_offset == existing.cbuf_offset &&
215 desc.secondary_cbuf_index == existing.secondary_cbuf_index && 252 desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
216 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset; 253 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
254 desc.count == existing.count && desc.size_shift == existing.size_shift &&
255 desc.has_secondary == existing.has_secondary;
217 }); 256 });
218 } 257 }
219 258
220 u32 Add(const ImageBufferDescriptor& desc) { 259 u32 Add(const ImageBufferDescriptor& desc) {
221 return Add(image_buffer_descriptors, desc, [&desc](const auto& existing) { 260 return Add(image_buffer_descriptors, desc, [&desc](const auto& existing) {
222 return desc.format == existing.format && desc.cbuf_index == existing.cbuf_index && 261 return desc.format == existing.format && desc.cbuf_index == existing.cbuf_index &&
223 desc.cbuf_offset == existing.cbuf_offset; 262 desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count &&
263 desc.size_shift == existing.size_shift;
224 }); 264 });
225 } 265 }
226 266
@@ -231,7 +271,8 @@ public:
231 desc.cbuf_index == existing.cbuf_index && 271 desc.cbuf_index == existing.cbuf_index &&
232 desc.cbuf_offset == existing.cbuf_offset && 272 desc.cbuf_offset == existing.cbuf_offset &&
233 desc.secondary_cbuf_index == existing.secondary_cbuf_index && 273 desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
234 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset; 274 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
275 desc.count == existing.count && desc.size_shift == existing.size_shift;
235 }); 276 });
236 } 277 }
237 278
@@ -239,7 +280,8 @@ public:
239 const u32 index{Add(image_descriptors, desc, [&desc](const auto& existing) { 280 const u32 index{Add(image_descriptors, desc, [&desc](const auto& existing) {
240 return desc.type == existing.type && desc.format == existing.format && 281 return desc.type == existing.type && desc.format == existing.format &&
241 desc.cbuf_index == existing.cbuf_index && 282 desc.cbuf_index == existing.cbuf_index &&
242 desc.cbuf_offset == existing.cbuf_offset; 283 desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count &&
284 desc.size_shift == existing.size_shift;
243 })}; 285 })};
244 image_descriptors[index].is_written |= desc.is_written; 286 image_descriptors[index].is_written |= desc.is_written;
245 return index; 287 return index;
@@ -310,7 +352,6 @@ void TexturePass(Environment& env, IR::Program& program) {
310 // This happens on Fire Emblem: Three Houses 352 // This happens on Fire Emblem: Three Houses
311 flags.type.Assign(TextureType::Buffer); 353 flags.type.Assign(TextureType::Buffer);
312 } 354 }
313 inst->SetFlags(flags);
314 break; 355 break;
315 default: 356 default:
316 break; 357 break;
@@ -329,7 +370,8 @@ void TexturePass(Environment& env, IR::Program& program) {
329 .is_written = is_written, 370 .is_written = is_written,
330 .cbuf_index = cbuf.index, 371 .cbuf_index = cbuf.index,
331 .cbuf_offset = cbuf.offset, 372 .cbuf_offset = cbuf.offset,
332 .count = 1, 373 .count = cbuf.count,
374 .size_shift = DESCRIPTOR_SIZE_SHIFT,
333 }); 375 });
334 } else { 376 } else {
335 index = descriptors.Add(ImageDescriptor{ 377 index = descriptors.Add(ImageDescriptor{
@@ -338,7 +380,8 @@ void TexturePass(Environment& env, IR::Program& program) {
338 .is_written = is_written, 380 .is_written = is_written,
339 .cbuf_index = cbuf.index, 381 .cbuf_index = cbuf.index,
340 .cbuf_offset = cbuf.offset, 382 .cbuf_offset = cbuf.offset,
341 .count = 1, 383 .count = cbuf.count,
384 .size_shift = DESCRIPTOR_SIZE_SHIFT,
342 }); 385 });
343 } 386 }
344 break; 387 break;
@@ -351,7 +394,8 @@ void TexturePass(Environment& env, IR::Program& program) {
351 .cbuf_offset = cbuf.offset, 394 .cbuf_offset = cbuf.offset,
352 .secondary_cbuf_index = cbuf.secondary_index, 395 .secondary_cbuf_index = cbuf.secondary_index,
353 .secondary_cbuf_offset = cbuf.secondary_offset, 396 .secondary_cbuf_offset = cbuf.secondary_offset,
354 .count = 1, 397 .count = cbuf.count,
398 .size_shift = DESCRIPTOR_SIZE_SHIFT,
355 }); 399 });
356 } else { 400 } else {
357 index = descriptors.Add(TextureDescriptor{ 401 index = descriptors.Add(TextureDescriptor{
@@ -362,12 +406,23 @@ void TexturePass(Environment& env, IR::Program& program) {
362 .cbuf_offset = cbuf.offset, 406 .cbuf_offset = cbuf.offset,
363 .secondary_cbuf_index = cbuf.secondary_index, 407 .secondary_cbuf_index = cbuf.secondary_index,
364 .secondary_cbuf_offset = cbuf.secondary_offset, 408 .secondary_cbuf_offset = cbuf.secondary_offset,
365 .count = 1, 409 .count = cbuf.count,
410 .size_shift = DESCRIPTOR_SIZE_SHIFT,
366 }); 411 });
367 } 412 }
368 break; 413 break;
369 } 414 }
370 inst->SetArg(0, IR::Value{index}); 415 flags.descriptor_index.Assign(index);
416 inst->SetFlags(flags);
417
418 if (cbuf.count > 1) {
419 const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)};
420 IR::IREmitter ir{*texture_inst.block, insert_point};
421 const IR::U32 shift{ir.Imm32(std::countr_zero(DESCRIPTOR_SIZE))};
422 inst->SetArg(0, ir.ShiftRightArithmetic(cbuf.dynamic_offset, shift));
423 } else {
424 inst->SetArg(0, IR::Value{});
425 }
371 } 426 }
372} 427}
373 428