From 4a22942f452dd1bba5e10d20217a0bfbf214dacb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 02:05:24 -0300 Subject: [PATCH] glasm: Implement ImageFetch --- .../backend/glasm/emit_context.cpp | 13 +++++--- .../backend/glasm/emit_context.h | 1 + .../backend/glasm/emit_glasm_image.cpp | 33 +++++++++++++++---- .../backend/glasm/emit_glasm_instructions.h | 4 +-- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index d1fe84a5f6..e2182400ca 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -80,11 +80,14 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings) : info{progra Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); } } - const size_t num_textures{program.info.texture_descriptors.size()}; - texture_bindings.resize(num_textures); - for (size_t index = 0; index < num_textures; ++index) { - const auto& desc{program.info.texture_descriptors[index]}; - texture_bindings[index] = bindings.texture; + texture_buffer_bindings.reserve(program.info.texture_buffer_descriptors.size()); + for (const auto& desc : program.info.texture_buffer_descriptors) { + texture_buffer_bindings.push_back(bindings.texture); + bindings.texture += desc.count; + } + texture_bindings.reserve(program.info.texture_descriptors.size()); + for (const auto& desc : program.info.texture_descriptors) { + texture_bindings.push_back(bindings.texture); bindings.texture += desc.count; } } diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 084635c77c..d6b0bf73c9 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -56,6 +56,7 @@ public: RegAlloc reg_alloc{*this}; const Info& info; + std::vector texture_buffer_bindings; std::vector texture_bindings; std::string_view stage_name = "invalid"; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 7b95505e25..333a003c9b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -43,7 +43,11 @@ struct ScopedRegister { std::string Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { // FIXME: indexed reads - return fmt::format("texture[{}]", ctx.texture_bindings.at(info.descriptor_index)); + if (info.type == TextureType::Buffer) { + return fmt::format("texture[{}]", ctx.texture_buffer_bindings.at(info.descriptor_index)); + } else { + return fmt::format("texture[{}]", ctx.texture_bindings.at(info.descriptor_index)); + } } std::string_view TextureType(IR::TextureInstInfo info) { @@ -421,11 +425,28 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde StoreSparse(ctx, sparse_inst); } -void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, - [[maybe_unused]] Register offset, [[maybe_unused]] Register lod, - [[maybe_unused]] Register ms) { - throw NotImplementedException("GLASM instruction"); +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms) { + const auto info{inst.Flags()}; + const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; + const std::string_view type{TextureType(info)}; + const std::string texture{Texture(ctx, info, index)}; + const std::string offset_vec{Offset(ctx, offset)}; + const auto [coord_vec, coord_alloc]{Coord(ctx, coord)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + if (info.type == TextureType::Buffer) { + ctx.Add("TXF.F{} {},{},{},{}{};", sparse_mod, ret, coord_vec, texture, type, offset_vec); + } else if (ms.type != Type::Void) { + ctx.Add("MOV.S {}.w,{};" + "TXFMS.F{} {},{},{},{}{};", + coord_vec, ms, sparse_mod, ret, coord_vec, texture, type, offset_vec); + } else { + ctx.Add("MOV.S {}.w,{};" + "TXF.F{} {},{},{},{}{};", + coord_vec, lod, sparse_mod, ret, coord_vec, texture, type, offset_vec); + } + StoreSparse(ctx, sparse_inst); } void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 8a707d924e..119b166afa 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -541,8 +541,8 @@ void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2, const IR::Value& dref); -void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, - Register offset, Register lod, Register ms); +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, ScalarF32 lod); void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord);