diff options
Diffstat (limited to 'src/shader_recompiler/backend')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 67 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 5 |
2 files changed, 65 insertions, 7 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 747af84fe..ab5a694fd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | |||
| @@ -127,6 +127,27 @@ void SwizzleOffsets(EmitContext& ctx, Register off_x, Register off_y, const IR:: | |||
| 127 | offsets_a, off_y, offsets_a, off_y, offsets_b, off_y, offsets_b); | 127 | offsets_a, off_y, offsets_a, off_y, offsets_b, off_y, offsets_b); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | std::string GradOffset(const IR::Value& offset) { | ||
| 131 | if (offset.IsImmediate()) { | ||
| 132 | // LOG_WARNING immediate | ||
| 133 | return ""; | ||
| 134 | } | ||
| 135 | IR::Inst* const vector{offset.InstRecursive()}; | ||
| 136 | if (!vector->AreAllArgsImmediates()) { | ||
| 137 | // LOG_WARNING elements not immediate | ||
| 138 | return ""; | ||
| 139 | } | ||
| 140 | switch (vector->NumArgs()) { | ||
| 141 | case 1: | ||
| 142 | return fmt::format(",({})", static_cast<s32>(vector->Arg(0).U32())); | ||
| 143 | case 2: | ||
| 144 | return fmt::format(",({},{})", static_cast<s32>(vector->Arg(0).U32()), | ||
| 145 | static_cast<s32>(vector->Arg(1).U32())); | ||
| 146 | default: | ||
| 147 | throw LogicError("Invalid number of gradient offsets {}", vector->NumArgs()); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 130 | std::pair<std::string, ScopedRegister> Coord(EmitContext& ctx, const IR::Value& coord) { | 151 | std::pair<std::string, ScopedRegister> Coord(EmitContext& ctx, const IR::Value& coord) { |
| 131 | if (coord.IsImmediate()) { | 152 | if (coord.IsImmediate()) { |
| 132 | ScopedRegister scoped_reg(ctx.reg_alloc); | 153 | ScopedRegister scoped_reg(ctx.reg_alloc); |
| @@ -464,11 +485,47 @@ void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | |||
| 464 | ctx.Add("LOD.F {},{},{},{};", inst, coord, texture, type); | 485 | ctx.Add("LOD.F {},{},{},{};", inst, coord, texture, type); |
| 465 | } | 486 | } |
| 466 | 487 | ||
| 467 | void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 488 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 468 | [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, | 489 | const IR::Value& coord, const IR::Value& derivatives, |
| 469 | [[maybe_unused]] Register derivates, [[maybe_unused]] Register offset, | 490 | const IR::Value& offset, const IR::Value& lod_clamp) { |
| 470 | [[maybe_unused]] Register lod_clamp) { | 491 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 471 | throw NotImplementedException("GLASM instruction"); | 492 | ScopedRegister dpdx, dpdy; |
| 493 | const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; | ||
| 494 | if (multi_component) { | ||
| 495 | // Allocate this early to avoid aliasing other registers | ||
| 496 | dpdx = ScopedRegister{ctx.reg_alloc}; | ||
| 497 | dpdy = ScopedRegister{ctx.reg_alloc}; | ||
| 498 | } | ||
| 499 | const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; | ||
| 500 | const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; | ||
| 501 | const std::string_view type{TextureType(info)}; | ||
| 502 | const std::string texture{Texture(ctx, info, index)}; | ||
| 503 | const std::string offset_vec{GradOffset(offset)}; | ||
| 504 | const Register coord_vec{ctx.reg_alloc.Consume(coord)}; | ||
| 505 | const Register derivatives_vec{ctx.reg_alloc.Consume(derivatives)}; | ||
| 506 | const Register ret{ctx.reg_alloc.Define(inst)}; | ||
| 507 | if (multi_component) { | ||
| 508 | ctx.Add("MOV.F {}.x,{}.x;" | ||
| 509 | "MOV.F {}.y,{}.z;" | ||
| 510 | "MOV.F {}.x,{}.y;" | ||
| 511 | "MOV.F {}.y,{}.w;", | ||
| 512 | dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec, | ||
| 513 | dpdy.reg, derivatives_vec); | ||
| 514 | if (info.has_lod_clamp) { | ||
| 515 | const ScalarF32 lod_clamp_value{ctx.reg_alloc.Consume(lod_clamp)}; | ||
| 516 | ctx.Add("MOV.F {}.w,{};" | ||
| 517 | "TXD.F.LODCLAMP{} {},{},{},{},{},{}{};", | ||
| 518 | dpdy.reg, lod_clamp_value, sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg, | ||
| 519 | texture, type, offset_vec); | ||
| 520 | } else { | ||
| 521 | ctx.Add("TXD.F{} {},{},{},{},{},{}{};", sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg, | ||
| 522 | texture, type, offset_vec); | ||
| 523 | } | ||
| 524 | } else { | ||
| 525 | ctx.Add("TXD.F{} {},{},{}.x,{}.y,{},{}{};", sparse_mod, ret, coord_vec, derivatives_vec, | ||
| 526 | derivatives_vec, texture, type, offset_vec); | ||
| 527 | } | ||
| 528 | StoreSparse(ctx, sparse_inst); | ||
| 472 | } | 529 | } |
| 473 | 530 | ||
| 474 | void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 531 | void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 94e545ad4..7ccba4c6f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | |||
| @@ -548,8 +548,9 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | |||
| 548 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 548 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 549 | ScalarF32 lod); | 549 | ScalarF32 lod); |
| 550 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); | 550 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); |
| 551 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, | 551 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 552 | Register derivates, Register offset, Register lod_clamp); | 552 | const IR::Value& coord, const IR::Value& derivatives, |
| 553 | const IR::Value& offset, const IR::Value& lod_clamp); | ||
| 553 | void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); | 554 | void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); |
| 554 | void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, | 555 | void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, |
| 555 | Register color); | 556 | Register color); |