diff options
| author | 2021-04-22 16:17:59 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:28 -0400 | |
| commit | d10cf55353175b13bed4cf18791e080ecb7fd95b (patch) | |
| tree | 9e26b823d7b48f532914a0511a157c14806debf5 /src/shader_recompiler/ir_opt/texture_pass.cpp | |
| parent | shader: Refactor atomic_operations_global_memory (diff) | |
| download | yuzu-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.cpp | 89 |
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 | ||
| 33 | using TextureInstVector = boost::container::small_vector<TextureInst, 24>; | 36 | using TextureInstVector = boost::container::small_vector<TextureInst, 24>; |
| 34 | 37 | ||
| 38 | constexpr u32 DESCRIPTOR_SIZE = 8; | ||
| 39 | constexpr u32 DESCRIPTOR_SIZE_SHIFT = static_cast<u32>(std::countr_zero(DESCRIPTOR_SIZE)); | ||
| 40 | |||
| 35 | IR::Opcode IndexedInstruction(const IR::Inst& inst) { | 41 | IR::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 | ||