From c721767bccbcbd481c0e545b707754b270a7ea02 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 May 2021 20:17:05 -0300 Subject: [PATCH] glasm: Implement global memory fallbacks --- .../backend/glasm/emit_glasm_instructions.h | 22 ++-- .../backend/glasm/emit_glasm_memory.cpp | 117 ++++++++++++------ 2 files changed, 89 insertions(+), 50 deletions(-) diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 4dee9daf9..5e038b332 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -79,17 +79,17 @@ void EmitUndefU8(EmitContext& ctx); void EmitUndefU16(EmitContext& ctx); void EmitUndefU32(EmitContext& ctx); void EmitUndefU64(EmitContext& ctx); -void EmitLoadGlobalU8(EmitContext& ctx); -void EmitLoadGlobalS8(EmitContext& ctx); -void EmitLoadGlobalU16(EmitContext& ctx); -void EmitLoadGlobalS16(EmitContext& ctx); -void EmitLoadGlobal32(EmitContext& ctx, Register address); -void EmitLoadGlobal64(EmitContext& ctx, Register address); -void EmitLoadGlobal128(EmitContext& ctx, Register address); -void EmitWriteGlobalU8(EmitContext& ctx); -void EmitWriteGlobalS8(EmitContext& ctx); -void EmitWriteGlobalU16(EmitContext& ctx); -void EmitWriteGlobalS16(EmitContext& ctx); +void EmitLoadGlobalU8(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobalS8(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobalU16(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobalS16(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobal32(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobal64(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, Register address); +void EmitWriteGlobalU8(EmitContext& ctx, Register address, Register value); +void EmitWriteGlobalS8(EmitContext& ctx, Register address, Register value); +void EmitWriteGlobalU16(EmitContext& ctx, Register address, Register value); +void EmitWriteGlobalS16(EmitContext& ctx, Register address, Register value); void EmitWriteGlobal32(EmitContext& ctx, Register address, ScalarU32 value); void EmitWriteGlobal64(EmitContext& ctx, Register address, Register value); void EmitWriteGlobal128(EmitContext& ctx, Register address, Register value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index dd307a9a3..33af83212 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -29,8 +29,39 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, } } +void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_expr, + std::string_view else_expr = {}) { + const size_t num_buffers{ctx.info.storage_buffers_descriptors.size()}; + for (size_t index = 0; index < num_buffers; ++index) { + if (!ctx.info.nvn_buffer_used[index]) { + continue; + } + const auto& ssbo{ctx.info.storage_buffers_descriptors[index]}; + ctx.Add("LDC.U64 DC.x,c[{}];" // ssbo_addr + "LDC.U32 RC.x,c[{}];" // ssbo_size_u32 + "CVT.U64.U32 DC.y,RC.x;" // ssbo_size = ssbo_size_u32 + "ADD.U64 DC.y,DC.y,DC.x;" // ssbo_end = ssbo_addr + ssbo_size + "SGE.U64 RC.x,{}.x,DC.x;" // a = input_addr >= ssbo_addr ? -1 : 1 + "SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 1 + "AND.U.CC RC.x,RC.x,RC.y;" + "IF NE.x;" // a && b + "SUB.U64 DC.x,{}.x,DC.x;" // offset = input_addr - ssbo_addr + "PK64.U DC.y,c[{}];" // host_ssbo = cbuf + "ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset + "{}", + "ELSE;", index, index, ssbo.cbuf_offset, ssbo.cbuf_offset + 8, address, address, + address, index, then_expr); + } + if (!else_expr.empty()) { + ctx.Add("{}", else_expr); + } + for (size_t index = 0; index < num_buffers; ++index) { + ctx.Add("ENDIF;"); + } +} + template -void Store(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value, +void Write(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value, std::string_view size) { StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, value)); } @@ -41,65 +72,73 @@ void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 StorageOp(ctx, binding, offset, fmt::format("LOAD.{} {},DC.x;", size, ret), fmt::format("MOV.U {},{{0,0,0,0}};", ret)); } + +template +void GlobalWrite(EmitContext& ctx, Register address, ValueType value, std::string_view size) { + GlobalStorageOp(ctx, address, fmt::format("STORE.{} {},DC.x;", size, value)); +} + +void GlobalLoad(EmitContext& ctx, IR::Inst& inst, Register address, std::string_view size) { + const Register ret{ctx.reg_alloc.Define(inst)}; + GlobalStorageOp(ctx, address, fmt::format("LOAD.{} {},DC.x;", size, ret), + fmt::format("MOV.S {},0;", ret)); +} } // Anonymous namespace -void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobalU8(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "U8"); } -void EmitLoadGlobalS8([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobalS8(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "S8"); } -void EmitLoadGlobalU16([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobalU16(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "U16"); } -void EmitLoadGlobalS16([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobalS16(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "S16"); } -void EmitLoadGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobal32(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "U32"); } -void EmitLoadGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobal64(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "U32X2"); } -void EmitLoadGlobal128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, Register address) { + GlobalLoad(ctx, inst, address, "U32X4"); } -void EmitWriteGlobalU8([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobalU8(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "U8"); } -void EmitWriteGlobalS8([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobalS8(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "S8"); } -void EmitWriteGlobalU16([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobalU16(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "U16"); } -void EmitWriteGlobalS16([[maybe_unused]] EmitContext& ctx) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobalS16(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "S16"); } -void EmitWriteGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobal32(EmitContext& ctx, Register address, ScalarU32 value) { + GlobalWrite(ctx, address, value, "U32"); } -void EmitWriteGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, - [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobal64(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "U32X2"); } -void EmitWriteGlobal128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, - [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteGlobal128(EmitContext& ctx, Register address, Register value) { + GlobalWrite(ctx, address, value, "U32X4"); } void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, @@ -139,37 +178,37 @@ void EmitLoadStorage128(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindi void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ScalarU32 value) { - Store(ctx, binding, offset, value, "U8"); + Write(ctx, binding, offset, value, "U8"); } void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ScalarS32 value) { - Store(ctx, binding, offset, value, "S8"); + Write(ctx, binding, offset, value, "S8"); } void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ScalarU32 value) { - Store(ctx, binding, offset, value, "U16"); + Write(ctx, binding, offset, value, "U16"); } void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ScalarS32 value) { - Store(ctx, binding, offset, value, "S16"); + Write(ctx, binding, offset, value, "S16"); } void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ScalarU32 value) { - Store(ctx, binding, offset, value, "U32"); + Write(ctx, binding, offset, value, "U32"); } void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, Register value) { - Store(ctx, binding, offset, value, "U32X2"); + Write(ctx, binding, offset, value, "U32X2"); } void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, Register value) { - Store(ctx, binding, offset, value, "U32X4"); + Write(ctx, binding, offset, value, "U32X4"); } } // namespace Shader::Backend::GLASM