diff options
| author | 2021-05-18 19:43:52 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:32 -0400 | |
| commit | 3d3ed53511dcd338806a97bfff2afa1644ddb424 (patch) | |
| tree | e92bb7bb829f41818909d20c5540b7f017f97739 /src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | |
| parent | glasm: Implement gl_FragDepth and gl_SampleMask stores (diff) | |
| download | yuzu-3d3ed53511dcd338806a97bfff2afa1644ddb424.tar.gz yuzu-3d3ed53511dcd338806a97bfff2afa1644ddb424.tar.xz yuzu-3d3ed53511dcd338806a97bfff2afa1644ddb424.zip | |
glasm: Implement textureGather instructions
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm_image.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 103 |
1 files changed, 92 insertions, 11 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 77da3400b..9da4da331 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <utility> | ||
| 6 | |||
| 5 | #include "shader_recompiler/backend/glasm/emit_context.h" | 7 | #include "shader_recompiler/backend/glasm/emit_context.h" |
| 6 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" | 8 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" |
| 7 | #include "shader_recompiler/frontend/ir/modifiers.h" | 9 | #include "shader_recompiler/frontend/ir/modifiers.h" |
| @@ -95,6 +97,33 @@ std::string Offset(EmitContext& ctx, const IR::Value& offset) { | |||
| 95 | return fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); | 97 | return fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 100 | std::pair<ScopedRegister, ScopedRegister> AllocOffsetsRegs(EmitContext& ctx, | ||
| 101 | const IR::Value& offset2) { | ||
| 102 | if (offset2.IsEmpty()) { | ||
| 103 | return {}; | ||
| 104 | } else { | ||
| 105 | return {ctx.reg_alloc, ctx.reg_alloc}; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | void SwizzleOffsets(EmitContext& ctx, Register off_x, Register off_y, const IR::Value& offset1, | ||
| 110 | const IR::Value& offset2) { | ||
| 111 | const Register offsets_a{ctx.reg_alloc.Consume(offset1)}; | ||
| 112 | const Register offsets_b{ctx.reg_alloc.Consume(offset2)}; | ||
| 113 | // Input swizzle: [XYXY] [XYXY] | ||
| 114 | // Output swizzle: [XXXX] [YYYY] | ||
| 115 | ctx.Add("MOV {}.x,{}.x;" | ||
| 116 | "MOV {}.y,{}.z;" | ||
| 117 | "MOV {}.z,{}.x;" | ||
| 118 | "MOV {}.w,{}.z;" | ||
| 119 | "MOV {}.x,{}.y;" | ||
| 120 | "MOV {}.y,{}.w;" | ||
| 121 | "MOV {}.z,{}.y;" | ||
| 122 | "MOV {}.w,{}.w;", | ||
| 123 | off_x, offsets_a, off_x, offsets_a, off_x, offsets_b, off_x, offsets_b, off_y, | ||
| 124 | offsets_a, off_y, offsets_a, off_y, offsets_b, off_y, offsets_b); | ||
| 125 | } | ||
| 126 | |||
| 98 | std::pair<std::string, ScopedRegister> Coord(EmitContext& ctx, const IR::Value& coord) { | 127 | std::pair<std::string, ScopedRegister> Coord(EmitContext& ctx, const IR::Value& coord) { |
| 99 | if (coord.IsImmediate()) { | 128 | if (coord.IsImmediate()) { |
| 100 | ScopedRegister scoped_reg(ctx.reg_alloc); | 129 | ScopedRegister scoped_reg(ctx.reg_alloc); |
| @@ -326,19 +355,71 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: | |||
| 326 | StoreSparse(ctx, sparse_inst); | 355 | StoreSparse(ctx, sparse_inst); |
| 327 | } | 356 | } |
| 328 | 357 | ||
| 329 | void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 358 | void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 330 | [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, | 359 | const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2) { |
| 331 | [[maybe_unused]] const IR::Value& offset, | 360 | // Allocate offsets early so they don't overwrite any consumed register |
| 332 | [[maybe_unused]] const IR::Value& offset2) { | 361 | const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; |
| 333 | throw NotImplementedException("GLASM instruction"); | 362 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 363 | const char comp{"xyzw"[info.gather_component]}; | ||
| 364 | const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; | ||
| 365 | const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; | ||
| 366 | const std::string_view type{TextureType(info)}; | ||
| 367 | const std::string texture{Texture(ctx, info, index)}; | ||
| 368 | const Register coord_vec{ctx.reg_alloc.Consume(coord)}; | ||
| 369 | const Register ret{ctx.reg_alloc.Define(inst)}; | ||
| 370 | if (offset2.IsEmpty()) { | ||
| 371 | const std::string offset_vec{Offset(ctx, offset)}; | ||
| 372 | ctx.Add("TXG.F{} {},{},{}.{},{}{};", sparse_mod, ret, coord_vec, texture, comp, type, | ||
| 373 | offset_vec); | ||
| 374 | } else { | ||
| 375 | SwizzleOffsets(ctx, off_x.reg, off_y.reg, offset, offset2); | ||
| 376 | ctx.Add("TXGO.F{} {},{},{},{},{}.{},{};", sparse_mod, ret, coord_vec, off_x.reg, off_y.reg, | ||
| 377 | texture, comp, type); | ||
| 378 | } | ||
| 379 | StoreSparse(ctx, sparse_inst); | ||
| 334 | } | 380 | } |
| 335 | 381 | ||
| 336 | void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 382 | void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 337 | [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, | 383 | const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2, |
| 338 | [[maybe_unused]] const IR::Value& offset, | 384 | const IR::Value& dref) { |
| 339 | [[maybe_unused]] const IR::Value& offset2, | 385 | // FIXME: This instruction is not working as expected |
| 340 | [[maybe_unused]] Register dref) { | 386 | |
| 341 | throw NotImplementedException("GLASM instruction"); | 387 | // Allocate offsets early so they don't overwrite any consumed register |
| 388 | const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; | ||
| 389 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | ||
| 390 | const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; | ||
| 391 | const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; | ||
| 392 | const std::string_view type{ShadowTextureType(info)}; | ||
| 393 | const std::string texture{Texture(ctx, info, index)}; | ||
| 394 | const Register coord_vec{ctx.reg_alloc.Consume(coord)}; | ||
| 395 | const ScalarF32 dref_value{ctx.reg_alloc.Consume(dref)}; | ||
| 396 | const Register ret{ctx.reg_alloc.Define(inst)}; | ||
| 397 | std::string args; | ||
| 398 | switch (info.type) { | ||
| 399 | case TextureType::Color2D: | ||
| 400 | ctx.Add("MOV.F {}.z,{};", coord_vec, dref_value); | ||
| 401 | args = fmt::to_string(coord_vec); | ||
| 402 | break; | ||
| 403 | case TextureType::ColorArray2D: | ||
| 404 | case TextureType::ColorCube: | ||
| 405 | ctx.Add("MOV.F {}.w,{};", coord_vec, dref_value); | ||
| 406 | args = fmt::to_string(coord_vec); | ||
| 407 | break; | ||
| 408 | case TextureType::ColorArrayCube: | ||
| 409 | args = fmt::format("{},{}", coord_vec, dref_value); | ||
| 410 | break; | ||
| 411 | default: | ||
| 412 | throw NotImplementedException("Invalid type {}", info.type.Value()); | ||
| 413 | } | ||
| 414 | if (offset2.IsEmpty()) { | ||
| 415 | const std::string offset_vec{Offset(ctx, offset)}; | ||
| 416 | ctx.Add("TXG.F{} {},{},{},{}{};", sparse_mod, ret, args, texture, type, offset_vec); | ||
| 417 | } else { | ||
| 418 | SwizzleOffsets(ctx, off_x.reg, off_y.reg, offset, offset2); | ||
| 419 | ctx.Add("TXGO.F{} {},{},{},{},{},{};", sparse_mod, ret, args, off_x.reg, off_y.reg, texture, | ||
| 420 | type); | ||
| 421 | } | ||
| 422 | StoreSparse(ctx, sparse_inst); | ||
| 342 | } | 423 | } |
| 343 | 424 | ||
| 344 | void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 425 | void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, |