From b10cf64c486d8730fcfeb53a333814915b3b5fbe Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 5 May 2021 02:19:08 -0300 Subject: glasm: Add GLASM backend infrastructure --- .../backend/glasm/emit_context.cpp | 7 + src/shader_recompiler/backend/glasm/emit_context.h | 21 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 95 + src/shader_recompiler/backend/glasm/emit_glasm.h | 23 + .../backend/glasm/emit_glasm_atomic.cpp | 0 .../backend/glasm/emit_glasm_barriers.cpp | 0 .../glasm/emit_glasm_bitwise_conversion.cpp | 0 .../backend/glasm/emit_glasm_composite.cpp | 0 .../backend/glasm/emit_glasm_context_get_set.cpp | 0 .../backend/glasm/emit_glasm_control_flow.cpp | 0 .../backend/glasm/emit_glasm_convert.cpp | 0 .../backend/glasm/emit_glasm_floating_point.cpp | 0 .../backend/glasm/emit_glasm_image.cpp | 0 .../backend/glasm/emit_glasm_image_atomic.cpp | 0 .../backend/glasm/emit_glasm_instructions.h | 650 ++++++ .../backend/glasm/emit_glasm_integer.cpp | 0 .../backend/glasm/emit_glasm_logical.cpp | 0 .../backend/glasm/emit_glasm_memory.cpp | 0 .../backend/glasm/emit_glasm_not_implemented.cpp | 2155 ++++++++++++++++++++ .../backend/glasm/emit_glasm_select.cpp | 0 .../backend/glasm/emit_glasm_shared_memory.cpp | 0 .../backend/glasm/emit_glasm_special.cpp | 0 .../backend/glasm/emit_glasm_undefined.cpp | 0 .../backend/glasm/emit_glasm_warp.cpp | 0 src/shader_recompiler/backend/glasm/reg_alloc.cpp | 82 + src/shader_recompiler/backend/glasm/reg_alloc.h | 46 + 26 files changed, 3079 insertions(+) create mode 100644 src/shader_recompiler/backend/glasm/emit_context.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_context.h create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm.h create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_image.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_instructions.h create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_select.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_special.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp create mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp create mode 100644 src/shader_recompiler/backend/glasm/reg_alloc.cpp create mode 100644 src/shader_recompiler/backend/glasm/reg_alloc.h (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp new file mode 100644 index 000000000..02c4d8a5d --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -0,0 +1,7 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "shader_recompiler/backend/glasm/emit_context.h" \ No newline at end of file diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h new file mode 100644 index 000000000..ae91069c8 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -0,0 +1,21 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "shader_recompiler/backend/glasm/reg_alloc.h" + +namespace Shader::Backend::GLASM { + +class EmitContext { +public: + std::string code; + RegAlloc reg_alloc; + +private: +}; + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp new file mode 100644 index 000000000..59d7c0f96 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -0,0 +1,95 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/profile.h" + +namespace Shader::Backend::GLASM { +namespace { +template +struct FuncTraits {}; + +template +struct FuncTraits { + using ReturnType = ReturnType_; + + static constexpr size_t NUM_ARGS = sizeof...(Args); + + template + using ArgType = std::tuple_element_t>; +}; + +template +auto Arg(EmitContext& ctx, const IR::Value& arg) { + if constexpr (std::is_same_v) { + return ctx.reg_alloc.Consume(arg); + } else if constexpr (std::is_same_v) { + return arg; + } else if constexpr (std::is_same_v) { + return arg.U32(); + } else if constexpr (std::is_same_v) { + return arg.Label(); + } else if constexpr (std::is_same_v) { + return arg.Attribute(); + } else if constexpr (std::is_same_v) { + return arg.Patch(); + } else if constexpr (std::is_same_v) { + return arg.Reg(); + } +} + +template +void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence) { + using Traits = FuncTraits; + if constexpr (is_first_arg_inst) { + func(ctx, inst, Arg>(ctx, inst->Arg(I))...); + } else { + func(ctx, Arg>(ctx, inst->Arg(I))...); + } +} + +template +void Invoke(EmitContext& ctx, IR::Inst* inst) { + using Traits = FuncTraits; + static_assert(Traits::NUM_ARGS >= 1, "Insufficient arguments"); + if constexpr (Traits::NUM_ARGS == 1) { + Invoke(ctx, inst, std::make_index_sequence<0>{}); + } else { + using FirstArgType = typename Traits::template ArgType<1>; + static constexpr bool is_first_arg_inst = std::is_same_v; + using Indices = std::make_index_sequence; + Invoke(ctx, inst, Indices{}); + } +} + +void EmitInst(EmitContext& ctx, IR::Inst* inst) { + switch (inst->GetOpcode()) { +#define OPCODE(name, result_type, ...) \ + case IR::Opcode::name: \ + return Invoke<&Emit##name>(ctx, inst); +#include "shader_recompiler/frontend/ir/opcodes.inc" +#undef OPCODE + } + throw LogicError("Invalid opcode {}", inst->GetOpcode()); +} +} // Anonymous namespace + +std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { + EmitContext ctx; + for (IR::Block* const block : program.blocks) { + for (IR::Inst& inst : block->Instructions()) { + EmitInst(ctx, &inst); + } + } + return ctx.code; +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h new file mode 100644 index 000000000..a0dfdd818 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_glasm.h @@ -0,0 +1,23 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/profile.h" + +namespace Shader::Backend::GLASM { + +[[nodiscard]] std::string EmitGLASM(const Profile& profile, IR::Program& program, + Bindings& binding); + +[[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { + Bindings binding; + return EmitGLASM(profile, program, binding); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h new file mode 100644 index 000000000..21d6af914 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -0,0 +1,650 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Shader::IR { +enum class Attribute : u64; +enum class Patch : u64; +class Inst; +class Value; +} // namespace Shader::IR + +namespace Shader::Backend::GLASM { + +class EmitContext; + +// Microinstruction emitters +void EmitPhi(EmitContext& ctx, IR::Inst* inst); +void EmitVoid(EmitContext& ctx); +void EmitIdentity(EmitContext& ctx, const IR::Value& value); +void EmitBranch(EmitContext& ctx, std::string_view label); +void EmitBranchConditional(EmitContext& ctx, std::string_view condition, + std::string_view true_label, std::string_view false_label); +void EmitLoopMerge(EmitContext& ctx, std::string_view merge_label, std::string_view continue_label); +void EmitSelectionMerge(EmitContext& ctx, std::string_view merge_label); +void EmitReturn(EmitContext& ctx); +void EmitJoin(EmitContext& ctx); +void EmitUnreachable(EmitContext& ctx); +void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label); +void EmitBarrier(EmitContext& ctx); +void EmitWorkgroupMemoryBarrier(EmitContext& ctx); +void EmitDeviceMemoryBarrier(EmitContext& ctx); +void EmitPrologue(EmitContext& ctx); +void EmitEpilogue(EmitContext& ctx); +void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream); +void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream); +void EmitGetRegister(EmitContext& ctx); +void EmitSetRegister(EmitContext& ctx); +void EmitGetPred(EmitContext& ctx); +void EmitSetPred(EmitContext& ctx); +void EmitSetGotoVariable(EmitContext& ctx); +void EmitGetGotoVariable(EmitContext& ctx); +void EmitSetIndirectBranchVariable(EmitContext& ctx); +void EmitGetIndirectBranchVariable(EmitContext& ctx); +void EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex); +void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, + std::string_view vertex); +void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); +void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, + std::string_view vertex); +void EmitGetPatch(EmitContext& ctx, IR::Patch patch); +void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value); +void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value); +void EmitSetSampleMask(EmitContext& ctx, std::string_view value); +void EmitSetFragDepth(EmitContext& ctx, std::string_view value); +void EmitGetZFlag(EmitContext& ctx); +void EmitGetSFlag(EmitContext& ctx); +void EmitGetCFlag(EmitContext& ctx); +void EmitGetOFlag(EmitContext& ctx); +void EmitSetZFlag(EmitContext& ctx); +void EmitSetSFlag(EmitContext& ctx); +void EmitSetCFlag(EmitContext& ctx); +void EmitSetOFlag(EmitContext& ctx); +void EmitWorkgroupId(EmitContext& ctx); +void EmitLocalInvocationId(EmitContext& ctx); +void EmitInvocationId(EmitContext& ctx); +void EmitSampleId(EmitContext& ctx); +void EmitIsHelperInvocation(EmitContext& ctx); +void EmitYDirection(EmitContext& ctx); +void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset); +void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value); +void EmitUndefU1(EmitContext& ctx); +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, std::string_view address); +void EmitLoadGlobal64(EmitContext& ctx, std::string_view address); +void EmitLoadGlobal128(EmitContext& ctx, std::string_view address); +void EmitWriteGlobalU8(EmitContext& ctx); +void EmitWriteGlobalS8(EmitContext& ctx); +void EmitWriteGlobalU16(EmitContext& ctx); +void EmitWriteGlobalS16(EmitContext& ctx); +void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value); +void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value); +void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value); +void EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedS8(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedU16(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedS16(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedU32(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedU64(EmitContext& ctx, std::string_view offset); +void EmitLoadSharedU128(EmitContext& ctx, std::string_view offset); +void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value); +void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value); +void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value); +void EmitWriteSharedU64(EmitContext& ctx, std::string_view offset, std::string_view value); +void EmitWriteSharedU128(EmitContext& ctx, std::string_view offset, std::string_view value); +void EmitCompositeConstructU32x2(EmitContext& ctx, std::string_view e1, std::string_view e2); +void EmitCompositeConstructU32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3); +void EmitCompositeConstructU32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4); +void EmitCompositeExtractU32x2(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractU32x3(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractU32x4(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2); +void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3); +void EmitCompositeConstructF16x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4); +void EmitCompositeExtractF16x2(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractF16x3(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractF16x4(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeInsertF16x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF16x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF16x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeConstructF32x2(EmitContext& ctx, std::string_view e1, std::string_view e2); +void EmitCompositeConstructF32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3); +void EmitCompositeConstructF32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4); +void EmitCompositeExtractF32x2(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractF32x3(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeExtractF32x4(EmitContext& ctx, std::string_view composite, u32 index); +void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeConstructF64x2(EmitContext& ctx); +void EmitCompositeConstructF64x3(EmitContext& ctx); +void EmitCompositeConstructF64x4(EmitContext& ctx); +void EmitCompositeExtractF64x2(EmitContext& ctx); +void EmitCompositeExtractF64x3(EmitContext& ctx); +void EmitCompositeExtractF64x4(EmitContext& ctx); +void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index); +void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectU32(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectF32(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value); +void EmitBitCastU16F16(EmitContext& ctx); +void EmitBitCastU32F32(EmitContext& ctx, std::string_view value); +void EmitBitCastU64F64(EmitContext& ctx); +void EmitBitCastF16U16(EmitContext& ctx); +void EmitBitCastF32U32(EmitContext& ctx, std::string_view value); +void EmitBitCastF64U64(EmitContext& ctx); +void EmitPackUint2x32(EmitContext& ctx, std::string_view value); +void EmitUnpackUint2x32(EmitContext& ctx, std::string_view value); +void EmitPackFloat2x16(EmitContext& ctx, std::string_view value); +void EmitUnpackFloat2x16(EmitContext& ctx, std::string_view value); +void EmitPackHalf2x16(EmitContext& ctx, std::string_view value); +void EmitUnpackHalf2x16(EmitContext& ctx, std::string_view value); +void EmitPackDouble2x32(EmitContext& ctx, std::string_view value); +void EmitUnpackDouble2x32(EmitContext& ctx, std::string_view value); +void EmitGetZeroFromOp(EmitContext& ctx); +void EmitGetSignFromOp(EmitContext& ctx); +void EmitGetCarryFromOp(EmitContext& ctx); +void EmitGetOverflowFromOp(EmitContext& ctx); +void EmitGetSparseFromOp(EmitContext& ctx); +void EmitGetInBoundsFromOp(EmitContext& ctx); +void EmitFPAbs16(EmitContext& ctx, std::string_view value); +void EmitFPAbs32(EmitContext& ctx, std::string_view value); +void EmitFPAbs64(EmitContext& ctx, std::string_view value); +void EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPFma16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c); +void EmitFPFma32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c); +void EmitFPFma64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c); +void EmitFPMax32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitFPMax64(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitFPMin32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitFPMin64(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitFPMul16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPMul32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPMul64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPNeg16(EmitContext& ctx, std::string_view value); +void EmitFPNeg32(EmitContext& ctx, std::string_view value); +void EmitFPNeg64(EmitContext& ctx, std::string_view value); +void EmitFPSin(EmitContext& ctx, std::string_view value); +void EmitFPCos(EmitContext& ctx, std::string_view value); +void EmitFPExp2(EmitContext& ctx, std::string_view value); +void EmitFPLog2(EmitContext& ctx, std::string_view value); +void EmitFPRecip32(EmitContext& ctx, std::string_view value); +void EmitFPRecip64(EmitContext& ctx, std::string_view value); +void EmitFPRecipSqrt32(EmitContext& ctx, std::string_view value); +void EmitFPRecipSqrt64(EmitContext& ctx, std::string_view value); +void EmitFPSqrt(EmitContext& ctx, std::string_view value); +void EmitFPSaturate16(EmitContext& ctx, std::string_view value); +void EmitFPSaturate32(EmitContext& ctx, std::string_view value); +void EmitFPSaturate64(EmitContext& ctx, std::string_view value); +void EmitFPClamp16(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value); +void EmitFPClamp32(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value); +void EmitFPClamp64(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value); +void EmitFPRoundEven16(EmitContext& ctx, std::string_view value); +void EmitFPRoundEven32(EmitContext& ctx, std::string_view value); +void EmitFPRoundEven64(EmitContext& ctx, std::string_view value); +void EmitFPFloor16(EmitContext& ctx, std::string_view value); +void EmitFPFloor32(EmitContext& ctx, std::string_view value); +void EmitFPFloor64(EmitContext& ctx, std::string_view value); +void EmitFPCeil16(EmitContext& ctx, std::string_view value); +void EmitFPCeil32(EmitContext& ctx, std::string_view value); +void EmitFPCeil64(EmitContext& ctx, std::string_view value); +void EmitFPTrunc16(EmitContext& ctx, std::string_view value); +void EmitFPTrunc32(EmitContext& ctx, std::string_view value); +void EmitFPTrunc64(EmitContext& ctx, std::string_view value); +void EmitFPOrdEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPIsNan16(EmitContext& ctx, std::string_view value); +void EmitFPIsNan32(EmitContext& ctx, std::string_view value); +void EmitFPIsNan64(EmitContext& ctx, std::string_view value); +void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitIAdd64(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitISub32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitISub64(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitIMul32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitINeg32(EmitContext& ctx, std::string_view value); +void EmitINeg64(EmitContext& ctx, std::string_view value); +void EmitIAbs32(EmitContext& ctx, std::string_view value); +void EmitIAbs64(EmitContext& ctx, std::string_view value); +void EmitShiftLeftLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitShiftLeftLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitShiftRightLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitShiftRightArithmetic32(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::string_view shift); +void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitBitFieldInsert(EmitContext& ctx, std::string_view base, std::string_view insert, + std::string_view offset, std::string_view count); +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, + std::string_view offset, std::string_view count); +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, + std::string_view offset, std::string_view count); +void EmitBitReverse32(EmitContext& ctx, std::string_view value); +void EmitBitCount32(EmitContext& ctx, std::string_view value); +void EmitBitwiseNot32(EmitContext& ctx, std::string_view value); +void EmitFindSMsb32(EmitContext& ctx, std::string_view value); +void EmitFindUMsb32(EmitContext& ctx, std::string_view value); +void EmitSMin32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitUMin32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitSMax32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitUMax32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, + std::string_view max); +void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, + std::string_view max); +void EmitSLessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitULessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitIEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitSLessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitULessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitSGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitUGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitINotEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitSGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitUGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicSMin32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicUMin32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicSMax32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicUMax32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicInc32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicDec32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicAnd32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicOr32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicXor32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicExchange32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitSharedAtomicExchange64(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value); +void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, + const IR::Value& offset, std::string_view value); +void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, + const IR::Value& offset, std::string_view value); +void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value); +void EmitGlobalAtomicIAdd32(EmitContext& ctx); +void EmitGlobalAtomicSMin32(EmitContext& ctx); +void EmitGlobalAtomicUMin32(EmitContext& ctx); +void EmitGlobalAtomicSMax32(EmitContext& ctx); +void EmitGlobalAtomicUMax32(EmitContext& ctx); +void EmitGlobalAtomicInc32(EmitContext& ctx); +void EmitGlobalAtomicDec32(EmitContext& ctx); +void EmitGlobalAtomicAnd32(EmitContext& ctx); +void EmitGlobalAtomicOr32(EmitContext& ctx); +void EmitGlobalAtomicXor32(EmitContext& ctx); +void EmitGlobalAtomicExchange32(EmitContext& ctx); +void EmitGlobalAtomicIAdd64(EmitContext& ctx); +void EmitGlobalAtomicSMin64(EmitContext& ctx); +void EmitGlobalAtomicUMin64(EmitContext& ctx); +void EmitGlobalAtomicSMax64(EmitContext& ctx); +void EmitGlobalAtomicUMax64(EmitContext& ctx); +void EmitGlobalAtomicInc64(EmitContext& ctx); +void EmitGlobalAtomicDec64(EmitContext& ctx); +void EmitGlobalAtomicAnd64(EmitContext& ctx); +void EmitGlobalAtomicOr64(EmitContext& ctx); +void EmitGlobalAtomicXor64(EmitContext& ctx); +void EmitGlobalAtomicExchange64(EmitContext& ctx); +void EmitGlobalAtomicAddF32(EmitContext& ctx); +void EmitGlobalAtomicAddF16x2(EmitContext& ctx); +void EmitGlobalAtomicAddF32x2(EmitContext& ctx); +void EmitGlobalAtomicMinF16x2(EmitContext& ctx); +void EmitGlobalAtomicMinF32x2(EmitContext& ctx); +void EmitGlobalAtomicMaxF16x2(EmitContext& ctx); +void EmitGlobalAtomicMaxF32x2(EmitContext& ctx); +void EmitLogicalOr(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitLogicalAnd(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitLogicalXor(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitLogicalNot(EmitContext& ctx, std::string_view value); +void EmitConvertS16F16(EmitContext& ctx, std::string_view value); +void EmitConvertS16F32(EmitContext& ctx, std::string_view value); +void EmitConvertS16F64(EmitContext& ctx, std::string_view value); +void EmitConvertS32F16(EmitContext& ctx, std::string_view value); +void EmitConvertS32F32(EmitContext& ctx, std::string_view value); +void EmitConvertS32F64(EmitContext& ctx, std::string_view value); +void EmitConvertS64F16(EmitContext& ctx, std::string_view value); +void EmitConvertS64F32(EmitContext& ctx, std::string_view value); +void EmitConvertS64F64(EmitContext& ctx, std::string_view value); +void EmitConvertU16F16(EmitContext& ctx, std::string_view value); +void EmitConvertU16F32(EmitContext& ctx, std::string_view value); +void EmitConvertU16F64(EmitContext& ctx, std::string_view value); +void EmitConvertU32F16(EmitContext& ctx, std::string_view value); +void EmitConvertU32F32(EmitContext& ctx, std::string_view value); +void EmitConvertU32F64(EmitContext& ctx, std::string_view value); +void EmitConvertU64F16(EmitContext& ctx, std::string_view value); +void EmitConvertU64F32(EmitContext& ctx, std::string_view value); +void EmitConvertU64F64(EmitContext& ctx, std::string_view value); +void EmitConvertU64U32(EmitContext& ctx, std::string_view value); +void EmitConvertU32U64(EmitContext& ctx, std::string_view value); +void EmitConvertF16F32(EmitContext& ctx, std::string_view value); +void EmitConvertF32F16(EmitContext& ctx, std::string_view value); +void EmitConvertF32F64(EmitContext& ctx, std::string_view value); +void EmitConvertF64F32(EmitContext& ctx, std::string_view value); +void EmitConvertF16S8(EmitContext& ctx, std::string_view value); +void EmitConvertF16S16(EmitContext& ctx, std::string_view value); +void EmitConvertF16S32(EmitContext& ctx, std::string_view value); +void EmitConvertF16S64(EmitContext& ctx, std::string_view value); +void EmitConvertF16U8(EmitContext& ctx, std::string_view value); +void EmitConvertF16U16(EmitContext& ctx, std::string_view value); +void EmitConvertF16U32(EmitContext& ctx, std::string_view value); +void EmitConvertF16U64(EmitContext& ctx, std::string_view value); +void EmitConvertF32S8(EmitContext& ctx, std::string_view value); +void EmitConvertF32S16(EmitContext& ctx, std::string_view value); +void EmitConvertF32S32(EmitContext& ctx, std::string_view value); +void EmitConvertF32S64(EmitContext& ctx, std::string_view value); +void EmitConvertF32U8(EmitContext& ctx, std::string_view value); +void EmitConvertF32U16(EmitContext& ctx, std::string_view value); +void EmitConvertF32U32(EmitContext& ctx, std::string_view value); +void EmitConvertF32U64(EmitContext& ctx, std::string_view value); +void EmitConvertF64S8(EmitContext& ctx, std::string_view value); +void EmitConvertF64S16(EmitContext& ctx, std::string_view value); +void EmitConvertF64S32(EmitContext& ctx, std::string_view value); +void EmitConvertF64S64(EmitContext& ctx, std::string_view value); +void EmitConvertF64U8(EmitContext& ctx, std::string_view value); +void EmitConvertF64U16(EmitContext& ctx, std::string_view value); +void EmitConvertF64U32(EmitContext& ctx, std::string_view value); +void EmitConvertF64U64(EmitContext& ctx, std::string_view value); +void EmitBindlessImageSampleImplicitLod(EmitContext&); +void EmitBindlessImageSampleExplicitLod(EmitContext&); +void EmitBindlessImageSampleDrefImplicitLod(EmitContext&); +void EmitBindlessImageSampleDrefExplicitLod(EmitContext&); +void EmitBindlessImageGather(EmitContext&); +void EmitBindlessImageGatherDref(EmitContext&); +void EmitBindlessImageFetch(EmitContext&); +void EmitBindlessImageQueryDimensions(EmitContext&); +void EmitBindlessImageQueryLod(EmitContext&); +void EmitBindlessImageGradient(EmitContext&); +void EmitBindlessImageRead(EmitContext&); +void EmitBindlessImageWrite(EmitContext&); +void EmitBoundImageSampleImplicitLod(EmitContext&); +void EmitBoundImageSampleExplicitLod(EmitContext&); +void EmitBoundImageSampleDrefImplicitLod(EmitContext&); +void EmitBoundImageSampleDrefExplicitLod(EmitContext&); +void EmitBoundImageGather(EmitContext&); +void EmitBoundImageGatherDref(EmitContext&); +void EmitBoundImageFetch(EmitContext&); +void EmitBoundImageQueryDimensions(EmitContext&); +void EmitBoundImageQueryLod(EmitContext&); +void EmitBoundImageGradient(EmitContext&); +void EmitBoundImageRead(EmitContext&); +void EmitBoundImageWrite(EmitContext&); +void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view bias_lc, + const IR::Value& offset); +void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view lod_lc, + const IR::Value& offset); +void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view dref, + std::string_view bias_lc, const IR::Value& offset); +void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view dref, + std::string_view lod_lc, const IR::Value& offset); +void EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, const IR::Value& offset, const IR::Value& offset2); +void EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, const IR::Value& offset, const IR::Value& offset2, + std::string_view dref); +void EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view offset, std::string_view lod, + std::string_view ms); +void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view lod); +void EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords); +void EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view derivates, std::string_view offset, + std::string_view lod_clamp); +void EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords); +void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view color); +void EmitBindlessImageAtomicIAdd32(EmitContext&); +void EmitBindlessImageAtomicSMin32(EmitContext&); +void EmitBindlessImageAtomicUMin32(EmitContext&); +void EmitBindlessImageAtomicSMax32(EmitContext&); +void EmitBindlessImageAtomicUMax32(EmitContext&); +void EmitBindlessImageAtomicInc32(EmitContext&); +void EmitBindlessImageAtomicDec32(EmitContext&); +void EmitBindlessImageAtomicAnd32(EmitContext&); +void EmitBindlessImageAtomicOr32(EmitContext&); +void EmitBindlessImageAtomicXor32(EmitContext&); +void EmitBindlessImageAtomicExchange32(EmitContext&); +void EmitBoundImageAtomicIAdd32(EmitContext&); +void EmitBoundImageAtomicSMin32(EmitContext&); +void EmitBoundImageAtomicUMin32(EmitContext&); +void EmitBoundImageAtomicSMax32(EmitContext&); +void EmitBoundImageAtomicUMax32(EmitContext&); +void EmitBoundImageAtomicInc32(EmitContext&); +void EmitBoundImageAtomicDec32(EmitContext&); +void EmitBoundImageAtomicAnd32(EmitContext&); +void EmitBoundImageAtomicOr32(EmitContext&); +void EmitBoundImageAtomicXor32(EmitContext&); +void EmitBoundImageAtomicExchange32(EmitContext&); +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value); +void EmitLaneId(EmitContext& ctx); +void EmitVoteAll(EmitContext& ctx, std::string_view pred); +void EmitVoteAny(EmitContext& ctx, std::string_view pred); +void EmitVoteEqual(EmitContext& ctx, std::string_view pred); +void EmitSubgroupBallot(EmitContext& ctx, std::string_view pred); +void EmitSubgroupEqMask(EmitContext& ctx); +void EmitSubgroupLtMask(EmitContext& ctx); +void EmitSubgroupLeMask(EmitContext& ctx); +void EmitSubgroupGtMask(EmitContext& ctx); +void EmitSubgroupGeMask(EmitContext& ctx); +void EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask); +void EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view index, + std::string_view clamp, std::string_view segmentation_mask); +void EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask); +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask); +void EmitFSwizzleAdd(EmitContext& ctx, std::string_view op_a, std::string_view op_b, + std::string_view swizzle); +void EmitDPdxFine(EmitContext& ctx, std::string_view op_a); +void EmitDPdyFine(EmitContext& ctx, std::string_view op_a); +void EmitDPdxCoarse(EmitContext& ctx, std::string_view op_a); +void EmitDPdyCoarse(EmitContext& ctx, std::string_view op_a); + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp new file mode 100644 index 000000000..e90224e15 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -0,0 +1,2155 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/frontend/ir/value.h" + +#ifdef _MSC_VER +#pragma warning(disable : 4100) +#endif + +namespace Shader::Backend::GLASM { + +static void NotImplemented() { + throw NotImplementedException("GLASM instruction"); +} + +void EmitPhi(EmitContext& ctx, IR::Inst* inst) { + NotImplemented(); +} + +void EmitVoid(EmitContext& ctx) { + NotImplemented(); +} + +void EmitIdentity(EmitContext& ctx, const IR::Value& value) { + NotImplemented(); +} + +void EmitBranch(EmitContext& ctx, std::string_view label) { + NotImplemented(); +} + +void EmitBranchConditional(EmitContext& ctx, std::string_view condition, + std::string_view true_label, std::string_view false_label) { + NotImplemented(); +} + +void EmitLoopMerge(EmitContext& ctx, std::string_view merge_label, + std::string_view continue_label) { + NotImplemented(); +} + +void EmitSelectionMerge(EmitContext& ctx, std::string_view merge_label) { + NotImplemented(); +} + +void EmitReturn(EmitContext& ctx) { + NotImplemented(); +} + +void EmitJoin(EmitContext& ctx) { + NotImplemented(); +} + +void EmitUnreachable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label) { + NotImplemented(); +} + +void EmitBarrier(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWorkgroupMemoryBarrier(EmitContext& ctx) { + NotImplemented(); +} + +void EmitDeviceMemoryBarrier(EmitContext& ctx) { + NotImplemented(); +} + +void EmitPrologue(EmitContext& ctx) { + NotImplemented(); +} + +void EmitEpilogue(EmitContext& ctx) { + NotImplemented(); +} + +void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { + NotImplemented(); +} + +void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { + NotImplemented(); +} + +void EmitGetRegister(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetRegister(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetPred(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetPred(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetGotoVariable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetGotoVariable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetIndirectBranchVariable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetIndirectBranchVariable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex) { + NotImplemented(); +} + +void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, + std::string_view vertex) { + NotImplemented(); +} + +void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex) { + NotImplemented(); +} + +void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, + std::string_view vertex) { + NotImplemented(); +} + +void EmitGetPatch(EmitContext& ctx, IR::Patch patch) { + NotImplemented(); +} + +void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) { + NotImplemented(); +} + +void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) { + NotImplemented(); +} + +void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitSetFragDepth(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitGetZFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetSFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetCFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetOFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetZFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetSFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetCFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSetOFlag(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWorkgroupId(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLocalInvocationId(EmitContext& ctx) { + NotImplemented(); +} + +void EmitInvocationId(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSampleId(EmitContext& ctx) { + NotImplemented(); +} + +void EmitIsHelperInvocation(EmitContext& ctx) { + NotImplemented(); +} + +void EmitYDirection(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset) { + NotImplemented(); +} + +void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value) { + NotImplemented(); +} + +void EmitUndefU1(EmitContext& ctx) { + NotImplemented(); +} + +void EmitUndefU8(EmitContext& ctx) { + NotImplemented(); +} + +void EmitUndefU16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitUndefU32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitUndefU64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadGlobalU8(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadGlobalS8(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadGlobalU16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadGlobalS16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLoadGlobal32(EmitContext& ctx, std::string_view address) { + NotImplemented(); +} + +void EmitLoadGlobal64(EmitContext& ctx, std::string_view address) { + NotImplemented(); +} + +void EmitLoadGlobal128(EmitContext& ctx, std::string_view address) { + NotImplemented(); +} + +void EmitWriteGlobalU8(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWriteGlobalS8(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWriteGlobalU16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWriteGlobalS16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value) { + NotImplemented(); +} + +void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value) { + NotImplemented(); +} + +void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value) { + NotImplemented(); +} + +void EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { + NotImplemented(); +} + +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedS8(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedU16(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedS16(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedU32(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedU64(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitLoadSharedU128(EmitContext& ctx, std::string_view offset) { + NotImplemented(); +} + +void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value) { + NotImplemented(); +} + +void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value) { + NotImplemented(); +} + +void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value) { + NotImplemented(); +} + +void EmitWriteSharedU64(EmitContext& ctx, std::string_view offset, std::string_view value) { + NotImplemented(); +} + +void EmitWriteSharedU128(EmitContext& ctx, std::string_view offset, std::string_view value) { + NotImplemented(); +} + +void EmitCompositeConstructU32x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { + NotImplemented(); +} + +void EmitCompositeConstructU32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3) { + NotImplemented(); +} + +void EmitCompositeConstructU32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4) { + NotImplemented(); +} + +void EmitCompositeExtractU32x2(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractU32x3(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractU32x4(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { + NotImplemented(); +} + +void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3) { + NotImplemented(); +} + +void EmitCompositeConstructF16x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4) { + NotImplemented(); +} + +void EmitCompositeExtractF16x2(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractF16x3(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractF16x4(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF16x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF16x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF16x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeConstructF32x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { + NotImplemented(); +} + +void EmitCompositeConstructF32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3) { + NotImplemented(); +} + +void EmitCompositeConstructF32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, + std::string_view e3, std::string_view e4) { + NotImplemented(); +} + +void EmitCompositeExtractF32x2(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractF32x3(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeExtractF32x4(EmitContext& ctx, std::string_view composite, u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeConstructF64x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeConstructF64x3(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeConstructF64x4(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeExtractF64x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeExtractF64x3(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeExtractF64x4(EmitContext& ctx) { + NotImplemented(); +} + +void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object, + u32 index) { + NotImplemented(); +} + +void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectU32(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectF32(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, + std::string_view false_value) { + NotImplemented(); +} + +void EmitBitCastU16F16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitBitCastU32F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitBitCastU64F64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitBitCastF16U16(EmitContext& ctx) { + NotImplemented(); +} + +void EmitBitCastF32U32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitBitCastF64U64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitPackUint2x32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitUnpackUint2x32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitPackFloat2x16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitUnpackFloat2x16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitPackHalf2x16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitUnpackHalf2x16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitPackDouble2x32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitUnpackDouble2x32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitGetZeroFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetSignFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetCarryFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetOverflowFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetSparseFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetInBoundsFromOp(EmitContext& ctx) { + NotImplemented(); +} + +void EmitFPAbs16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPAbs32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPAbs64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPFma16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c) { + NotImplemented(); +} + +void EmitFPFma32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c) { + NotImplemented(); +} + +void EmitFPFma64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, + std::string_view c) { + NotImplemented(); +} + +void EmitFPMax32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMax64(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMin32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMin64(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMul16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMul32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPMul64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitFPNeg16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPNeg32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPNeg64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPSin(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPCos(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPExp2(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPLog2(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRecip32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRecip64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRecipSqrt32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRecipSqrt64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPSqrt(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPSaturate16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPSaturate32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPSaturate64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPClamp16(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value) { + NotImplemented(); +} + +void EmitFPClamp32(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value) { + NotImplemented(); +} + +void EmitFPClamp64(EmitContext& ctx, std::string_view value, std::string_view min_value, + std::string_view max_value) { + NotImplemented(); +} + +void EmitFPRoundEven16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRoundEven32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPRoundEven64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPFloor16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPFloor32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPFloor64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPCeil16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPCeil32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPCeil64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPTrunc16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPTrunc32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPTrunc64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPOrdEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitFPIsNan16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPIsNan32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFPIsNan64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitIAdd64(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitISub32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitISub64(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitIMul32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitINeg32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitINeg64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitIAbs32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitIAbs64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitShiftLeftLogical32(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitShiftLeftLogical64(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitShiftRightLogical64(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitShiftRightArithmetic32(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::string_view shift) { + NotImplemented(); +} + +void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitBitFieldInsert(EmitContext& ctx, std::string_view base, std::string_view insert, + std::string_view offset, std::string_view count) { + NotImplemented(); +} + +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, + std::string_view offset, std::string_view count) { + NotImplemented(); +} + +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, + std::string_view offset, std::string_view count) { + NotImplemented(); +} + +void EmitBitReverse32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitBitCount32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitBitwiseNot32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFindSMsb32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitFindUMsb32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitSMin32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitUMin32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitSMax32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitUMax32(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, + std::string_view max) { + NotImplemented(); +} + +void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, + std::string_view max) { + NotImplemented(); +} + +void EmitSLessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitULessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitIEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitSLessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitULessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitSGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitUGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitINotEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitSGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitUGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { + NotImplemented(); +} + +void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicSMin32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicUMin32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicSMax32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicUMax32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicInc32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicDec32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicAnd32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicOr32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicXor32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicExchange32(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitSharedAtomicExchange64(EmitContext& ctx, std::string_view pointer_offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, + const IR::Value& offset, std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, + const IR::Value& offset, std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, + std::string_view value) { + NotImplemented(); +} + +void EmitGlobalAtomicIAdd32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicSMin32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicUMin32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicSMax32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicUMax32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicInc32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicDec32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicAnd32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicOr32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicXor32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicExchange32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicIAdd64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicSMin64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicUMin64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicSMax64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicUMax64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicInc64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicDec64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicAnd64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicOr64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicXor64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicExchange64(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicAddF32(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicAddF16x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicAddF32x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicMinF16x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicMinF32x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicMaxF16x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGlobalAtomicMaxF32x2(EmitContext& ctx) { + NotImplemented(); +} + +void EmitLogicalOr(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitLogicalAnd(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitLogicalXor(EmitContext& ctx, std::string_view a, std::string_view b) { + NotImplemented(); +} + +void EmitLogicalNot(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS16F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS16F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS16F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS32F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS32F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS32F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS64F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS64F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertS64F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU16F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU16F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU16F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU64F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU64F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU64F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU64U32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32U64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32F16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32F64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64F32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16S8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16S16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16S32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16S64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16U8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16U16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16U32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF16U64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32S8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32S16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32S32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32S64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32U8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32U16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32U32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF32U64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64S8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64S16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64S32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64S64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64U8(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64U16(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64U32(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitConvertF64U64(EmitContext& ctx, std::string_view value) { + NotImplemented(); +} + +void EmitBindlessImageSampleImplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageSampleExplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageGather(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageGatherDref(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageFetch(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageQueryDimensions(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageQueryLod(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageGradient(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageRead(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageWrite(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageSampleImplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageSampleExplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageSampleDrefImplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageSampleDrefExplicitLod(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageGather(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageGatherDref(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageFetch(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageQueryDimensions(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageQueryLod(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageGradient(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageRead(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageWrite(EmitContext&) { + NotImplemented(); +} + +void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view bias_lc, + const IR::Value& offset) { + NotImplemented(); +} + +void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view lod_lc, + const IR::Value& offset) { + NotImplemented(); +} + +void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view dref, + std::string_view bias_lc, const IR::Value& offset) { + NotImplemented(); +} + +void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view dref, + std::string_view lod_lc, const IR::Value& offset) { + NotImplemented(); +} + +void EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, const IR::Value& offset, const IR::Value& offset2) { + NotImplemented(); +} + +void EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, const IR::Value& offset, const IR::Value& offset2, + std::string_view dref) { + NotImplemented(); +} + +void EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view offset, std::string_view lod, + std::string_view ms) { + NotImplemented(); +} + +void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view lod) { + NotImplemented(); +} + +void EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords) { + NotImplemented(); +} + +void EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view derivates, std::string_view offset, + std::string_view lod_clamp) { + NotImplemented(); +} + +void EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords) { + NotImplemented(); +} + +void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view color) { + NotImplemented(); +} + +void EmitBindlessImageAtomicIAdd32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicSMin32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicUMin32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicSMax32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicUMax32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicInc32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicDec32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicAnd32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicOr32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicXor32(EmitContext&) { + NotImplemented(); +} + +void EmitBindlessImageAtomicExchange32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicIAdd32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicSMin32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicUMin32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicSMax32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicUMax32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicInc32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicDec32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicAnd32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicOr32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicXor32(EmitContext&) { + NotImplemented(); +} + +void EmitBoundImageAtomicExchange32(EmitContext&) { + NotImplemented(); +} + +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, + std::string_view coords, std::string_view value) { + NotImplemented(); +} + +void EmitLaneId(EmitContext& ctx) { + NotImplemented(); +} + +void EmitVoteAll(EmitContext& ctx, std::string_view pred) { + NotImplemented(); +} + +void EmitVoteAny(EmitContext& ctx, std::string_view pred) { + NotImplemented(); +} + +void EmitVoteEqual(EmitContext& ctx, std::string_view pred) { + NotImplemented(); +} + +void EmitSubgroupBallot(EmitContext& ctx, std::string_view pred) { + NotImplemented(); +} + +void EmitSubgroupEqMask(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSubgroupLtMask(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSubgroupLeMask(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSubgroupGtMask(EmitContext& ctx) { + NotImplemented(); +} + +void EmitSubgroupGeMask(EmitContext& ctx) { + NotImplemented(); +} + +void EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask) { + NotImplemented(); +} + +void EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view index, + std::string_view clamp, std::string_view segmentation_mask) { + NotImplemented(); +} + +void EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask) { + NotImplemented(); +} + +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, std::string_view value, + std::string_view index, std::string_view clamp, + std::string_view segmentation_mask) { + NotImplemented(); +} + +void EmitFSwizzleAdd(EmitContext& ctx, std::string_view op_a, std::string_view op_b, + std::string_view swizzle) { + NotImplemented(); +} + +void EmitDPdxFine(EmitContext& ctx, std::string_view op_a) { + NotImplemented(); +} + +void EmitDPdyFine(EmitContext& ctx, std::string_view op_a) { + NotImplemented(); +} + +void EmitDPdxCoarse(EmitContext& ctx, std::string_view op_a) { + NotImplemented(); +} + +void EmitDPdyCoarse(EmitContext& ctx, std::string_view op_a) { + NotImplemented(); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp new file mode 100644 index 000000000..0460a394b --- /dev/null +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -0,0 +1,82 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +#include + +#include "shader_recompiler/backend/glasm/reg_alloc.h" +#include "shader_recompiler/exception.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +constexpr std::string_view SWIZZLE = "xyzw"; + +std::string Representation(Id id) { + if (id.is_condition_code != 0) { + throw NotImplementedException("Condition code"); + } + if (id.is_spill != 0) { + throw NotImplementedException("Spilling"); + } + const u32 num_elements{id.num_elements_minus_one + 1}; + const u32 index{static_cast(id.index)}; + if (num_elements == 4) { + return fmt::format("R{}", index); + } else { + return fmt::format("R{}.{}", index, SWIZZLE.substr(id.base_element, num_elements)); + } +} +} // Anonymous namespace + +std::string RegAlloc::Define(IR::Inst& inst, u32 num_elements, u32 alignment) { + const Id id{Alloc(num_elements, alignment)}; + inst.SetDefinition(id); + return Representation(id); +} + +std::string RegAlloc::Consume(const IR::Value& value) { + if (!value.IsImmediate()) { + return Consume(*value.Inst()); + } + throw NotImplementedException("Immediate loading"); +} + +std::string RegAlloc::Consume(IR::Inst& inst) { + const Id id{inst.Definition()}; + inst.DestructiveRemoveUsage(); + if (!inst.HasUses()) { + Free(id); + } + return Representation(inst.Definition()); +} + +Id RegAlloc::Alloc(u32 num_elements, [[maybe_unused]] u32 alignment) { + for (size_t reg = 0; reg < NUM_REGS; ++reg) { + if (register_use[reg]) { + continue; + } + num_used_registers = std::max(num_used_registers, reg + 1); + register_use[reg] = true; + return Id{ + .base_element = 0, + .num_elements_minus_one = num_elements - 1, + .index = static_cast(reg), + .is_spill = 0, + .is_condition_code = 0, + }; + } + throw NotImplementedException("Register spilling"); +} + +void RegAlloc::Free(Id id) { + if (id.is_spill != 0) { + throw NotImplementedException("Free spill"); + } + register_use[id.index] = false; +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h new file mode 100644 index 000000000..46018b0c2 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -0,0 +1,46 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Shader::IR { +class Inst; +class Value; +} // namespace Shader::IR + +namespace Shader::Backend::GLASM { + +struct Id { + u32 base_element : 2; + u32 num_elements_minus_one : 2; + u32 index : 26; + u32 is_spill : 1; + u32 is_condition_code : 1; +}; + +class RegAlloc { +public: + std::string Define(IR::Inst& inst, u32 num_elements = 1, u32 alignment = 1); + + std::string Consume(const IR::Value& value); + +private: + static constexpr size_t NUM_REGS = 4096; + static constexpr size_t NUM_ELEMENTS = 4; + + std::string Consume(IR::Inst& inst); + + Id Alloc(u32 num_elements, u32 alignment); + + void Free(Id id); + + size_t num_used_registers{}; + std::bitset register_use{}; +}; + +} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From c1ba685d9c9b9ca9e8c479c52097adf943e804eb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 7 May 2021 06:31:30 -0300 Subject: glasm: Changes to GLASM register allocator and emit context --- .../backend/glasm/emit_context.cpp | 8 +++-- src/shader_recompiler/backend/glasm/emit_context.h | 27 ++++++++++++++-- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 37 ++++++++++++---------- src/shader_recompiler/backend/glasm/reg_alloc.h | 18 ++++++++--- 4 files changed, 64 insertions(+), 26 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 02c4d8a5d..b4db4ff8f 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -2,6 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#pragma once +#include "shader_recompiler/backend/glasm/emit_context.h" -#include "shader_recompiler/backend/glasm/emit_context.h" \ No newline at end of file +namespace Shader::Backend::GLASM { + +EmitContext::EmitContext() = default; + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index ae91069c8..cf66619de 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -5,17 +5,38 @@ #pragma once #include +#include + +#include #include "shader_recompiler/backend/glasm/reg_alloc.h" +namespace Shader::IR { +class Inst; +} + namespace Shader::Backend::GLASM { class EmitContext { public: - std::string code; - RegAlloc reg_alloc; + explicit EmitContext(); -private: + template + void Add(const char* fmt, IR::Inst& inst, Args&&... args) { + code += fmt::format(fmt, reg_alloc.Define(inst), std::forward(args)...); + // TODO: Remove this + code += '\n'; + } + + template + void Add(const char* fmt, Args&&... args) { + code += fmt::format(fmt, std::forward(args)...); + // TODO: Remove this + code += '\n'; + } + + std::string code; + RegAlloc reg_alloc{*this}; }; } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 0460a394b..55e8107e9 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -3,18 +3,16 @@ // Refer to the license.txt file included. #include -#include #include +#include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/reg_alloc.h" #include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { namespace { -constexpr std::string_view SWIZZLE = "xyzw"; - std::string Representation(Id id) { if (id.is_condition_code != 0) { throw NotImplementedException("Condition code"); @@ -22,27 +20,36 @@ std::string Representation(Id id) { if (id.is_spill != 0) { throw NotImplementedException("Spilling"); } - const u32 num_elements{id.num_elements_minus_one + 1}; const u32 index{static_cast(id.index)}; - if (num_elements == 4) { - return fmt::format("R{}", index); - } else { - return fmt::format("R{}.{}", index, SWIZZLE.substr(id.base_element, num_elements)); + return fmt::format("R{}.x", index); +} + +std::string ImmValue(const IR::Value& value) { + switch (value.Type()) { + case IR::Type::U1: + return value.U1() ? "-1" : "0"; + case IR::Type::U32: + return fmt::format("{}", value.U32()); + case IR::Type::F32: + return fmt::format("{}", value.F32()); + default: + throw NotImplementedException("Immediate type", value.Type()); } } } // Anonymous namespace -std::string RegAlloc::Define(IR::Inst& inst, u32 num_elements, u32 alignment) { - const Id id{Alloc(num_elements, alignment)}; +std::string RegAlloc::Define(IR::Inst& inst) { + const Id id{Alloc()}; inst.SetDefinition(id); return Representation(id); } std::string RegAlloc::Consume(const IR::Value& value) { - if (!value.IsImmediate()) { - return Consume(*value.Inst()); + if (value.IsImmediate()) { + return ImmValue(value); + } else { + return Consume(*value.InstRecursive()); } - throw NotImplementedException("Immediate loading"); } std::string RegAlloc::Consume(IR::Inst& inst) { @@ -54,7 +61,7 @@ std::string RegAlloc::Consume(IR::Inst& inst) { return Representation(inst.Definition()); } -Id RegAlloc::Alloc(u32 num_elements, [[maybe_unused]] u32 alignment) { +Id RegAlloc::Alloc() { for (size_t reg = 0; reg < NUM_REGS; ++reg) { if (register_use[reg]) { continue; @@ -62,8 +69,6 @@ Id RegAlloc::Alloc(u32 num_elements, [[maybe_unused]] u32 alignment) { num_used_registers = std::max(num_used_registers, reg + 1); register_use[reg] = true; return Id{ - .base_element = 0, - .num_elements_minus_one = num_elements - 1, .index = static_cast(reg), .is_spill = 0, .is_condition_code = 0, diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 46018b0c2..83d728d20 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -15,27 +15,35 @@ class Value; namespace Shader::Backend::GLASM { +class EmitContext; + struct Id { - u32 base_element : 2; - u32 num_elements_minus_one : 2; - u32 index : 26; + u32 index : 30; u32 is_spill : 1; u32 is_condition_code : 1; }; class RegAlloc { public: - std::string Define(IR::Inst& inst, u32 num_elements = 1, u32 alignment = 1); + RegAlloc(EmitContext& ctx_) : ctx{ctx_} {} + + std::string Define(IR::Inst& inst); std::string Consume(const IR::Value& value); + [[nodiscard]] size_t NumUsedRegisters() const noexcept { + return num_used_registers; + } + private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; + EmitContext& ctx; + std::string Consume(IR::Inst& inst); - Id Alloc(u32 num_elements, u32 alignment); + Id Alloc(); void Free(Id id); -- cgit v1.2.3 From 6fd190d1ae4275a06ed2e488401e1d63912954be Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 8 May 2021 16:28:52 -0300 Subject: glasm: Implement basic GLASM instructions --- .../backend/glasm/emit_context.cpp | 21 +- src/shader_recompiler/backend/glasm/emit_context.h | 5 +- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 66 +- .../backend/glasm/emit_glasm_context_get_set.cpp | 125 ++++ .../backend/glasm/emit_glasm_floating_point.cpp | 421 +++++++++++ .../backend/glasm/emit_glasm_instructions.h | 177 ++--- .../backend/glasm/emit_glasm_integer.cpp | 228 ++++++ .../backend/glasm/emit_glasm_memory.cpp | 178 +++++ .../backend/glasm/emit_glasm_not_implemented.cpp | 790 +-------------------- 9 files changed, 1169 insertions(+), 842 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index b4db4ff8f..9f839f3bf 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -3,9 +3,28 @@ // Refer to the license.txt file included. #include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/frontend/ir/program.h" namespace Shader::Backend::GLASM { -EmitContext::EmitContext() = default; +EmitContext::EmitContext(IR::Program& program) { + // FIXME: Temporary partial implementation + u32 cbuf_index{}; + for (const auto& desc : program.info.constant_buffer_descriptors) { + if (desc.count != 1) { + throw NotImplementedException("Constant buffer descriptor array"); + } + Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); + ++cbuf_index; + } + for (const auto& desc : program.info.storage_buffers_descriptors) { + if (desc.count != 1) { + throw NotImplementedException("Storage buffer descriptor array"); + } + } + if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { + Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); + } +} } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index cf66619de..4f98a9816 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -13,13 +13,14 @@ namespace Shader::IR { class Inst; -} +struct Program; +} // namespace Shader::IR namespace Shader::Backend::GLASM { class EmitContext { public: - explicit EmitContext(); + explicit EmitContext(IR::Program& program); template void Add(const char* fmt, IR::Inst& inst, Args&&... args) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 59d7c0f96..65600f58c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -50,7 +50,7 @@ template void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence) { using Traits = FuncTraits; if constexpr (is_first_arg_inst) { - func(ctx, inst, Arg>(ctx, inst->Arg(I))...); + func(ctx, *inst, Arg>(ctx, inst->Arg(I))...); } else { func(ctx, Arg>(ctx, inst->Arg(I))...); } @@ -64,7 +64,7 @@ void Invoke(EmitContext& ctx, IR::Inst* inst) { Invoke(ctx, inst, std::make_index_sequence<0>{}); } else { using FirstArgType = typename Traits::template ArgType<1>; - static constexpr bool is_first_arg_inst = std::is_same_v; + static constexpr bool is_first_arg_inst = std::is_same_v; using Indices = std::make_index_sequence; Invoke(ctx, inst, Indices{}); } @@ -80,16 +80,76 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { } throw LogicError("Invalid opcode {}", inst->GetOpcode()); } + +void Identity(IR::Inst& inst, const IR::Value& value) { + if (value.IsImmediate()) { + return; + } + IR::Inst* const value_inst{value.InstRecursive()}; + if (inst.GetOpcode() == IR::Opcode::Identity) { + value_inst->DestructiveAddUsage(inst.UseCount()); + value_inst->DestructiveRemoveUsage(); + } + inst.SetDefinition(value_inst->Definition()); +} } // Anonymous namespace std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { - EmitContext ctx; + EmitContext ctx{program}; for (IR::Block* const block : program.blocks) { for (IR::Inst& inst : block->Instructions()) { EmitInst(ctx, &inst); } } + std::string header = "!!NVcp5.0\n" + "OPTION NV_internal;"; + switch (program.stage) { + case Stage::Compute: + header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], + program.workgroup_size[1], program.workgroup_size[2]); + break; + default: + break; + } + header += "TEMP "; + for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) { + header += fmt::format("R{},", index); + } + header += "RC;"; + if (!program.info.storage_buffers_descriptors.empty()) { + header += "LONG TEMP LC;"; + } + ctx.code.insert(0, header); + ctx.code += "END"; return ctx.code; } +void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + +void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + Identity(inst, value); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index e69de29bb..72733d1cf 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -0,0 +1,125 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset, + std::string_view size) { + if (!binding.IsImmediate()) { + throw NotImplementedException("Indirect constant buffer loading"); + } + const std::string ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), ctx.reg_alloc.Consume(offset)); +} +} // Anonymous namespace + +void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "U8"); +} + +void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "S8"); +} + +void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "U16"); +} + +void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "S16"); +} + +void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "U32"); +} + +void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "F32"); +} + +void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset) { + GetCbuf(ctx, inst, binding, offset, "U32X2"); +} + +void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, + [[maybe_unused]] std::string_view vertex) { + if (IR::IsGeneric(attr)) { + const u32 index{IR::GenericAttributeIndex(attr)}; + const u32 element{IR::GenericAttributeElement(attr)}; + ctx.Add("MOV.F {},in_attr{}.{};", inst, index, "xyzw"[element]); + return; + } + throw NotImplementedException("Get attribute {}", attr); +} + +void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, + [[maybe_unused]] std::string_view vertex) { + const u32 element{static_cast(attr) % 4}; + const char swizzle{"xyzw"[element]}; + if (IR::IsGeneric(attr)) { + const u32 index{IR::GenericAttributeIndex(attr)}; + ctx.Add("MOV.F out_attr{}.{},{};", index, swizzle, value); + return; + } + switch (attr) { + case IR::Attribute::PositionX: + case IR::Attribute::PositionY: + case IR::Attribute::PositionZ: + case IR::Attribute::PositionW: + ctx.Add("MOV.F result.position.{},{};", swizzle, value); + break; + default: + throw NotImplementedException("Set attribute {}", attr); + } +} + +void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view offset, + [[maybe_unused]] std::string_view vertex) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view offset, + [[maybe_unused]] std::string_view value, + [[maybe_unused]] std::string_view vertex) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch, + [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSetFragColor([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] u32 index, + [[maybe_unused]] u32 component, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSetSampleMask([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSetFragDepth([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index e69de29bb..db9dda261 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -0,0 +1,421 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { + ctx.Add("MOV.F {},|{}|;", inst, value); +} + +void EmitFPAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { + ctx.Add("ADD.F {},{},{};", inst, a, b); +} + +void EmitFPAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b, + [[maybe_unused]] std::string_view c) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, + std::string_view c) { + ctx.Add("MAD.F {},{},{},{};", inst, a, b, c); +} + +void EmitFPFma64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b, + [[maybe_unused]] std::string_view c) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMax64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMin64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { + ctx.Add("MUL.F {},{},{};", inst, a, b); +} + +void EmitFPMul64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { + if (value[0] == '-') { + // Guard against negating a negative immediate + ctx.Add("MOV.F {},{};", inst, value.substr(1)); + } else { + ctx.Add("MOV.F {},-{};", inst, value); + } +} + +void EmitFPNeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPSin([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPCos([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPExp2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPLog2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRecip32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRecip64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPSqrt([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { + ctx.Add("MOV.F.SAT {},{};", inst, value); +} + +void EmitFPSaturate64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, + [[maybe_unused]] std::string_view min_value, + [[maybe_unused]] std::string_view max_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, + [[maybe_unused]] std::string_view min_value, + [[maybe_unused]] std::string_view max_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPClamp64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, + [[maybe_unused]] std::string_view min_value, + [[maybe_unused]] std::string_view max_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRoundEven32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPRoundEven64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPFloor16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPFloor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPFloor64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPCeil16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPCeil32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPCeil64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPTrunc16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPTrunc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPTrunc64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs) { + const std::string ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SEQ.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +} + +void EmitFPOrdEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs) { + const std::string ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SLT.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +} + +void EmitFPOrdLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThan32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThan64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThan32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThan64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs) { + const std::string ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SLE.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +} + +void EmitFPOrdLessThanEqual64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThanEqual32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordLessThanEqual64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPOrdGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFPUnordGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 21d6af914..30cc6c2eb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -20,9 +20,9 @@ namespace Shader::Backend::GLASM { class EmitContext; // Microinstruction emitters -void EmitPhi(EmitContext& ctx, IR::Inst* inst); +void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); -void EmitIdentity(EmitContext& ctx, const IR::Value& value); +void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBranch(EmitContext& ctx, std::string_view label); void EmitBranchConditional(EmitContext& ctx, std::string_view condition, std::string_view true_label, std::string_view false_label); @@ -47,14 +47,22 @@ void EmitSetGotoVariable(EmitContext& ctx); void EmitGetGotoVariable(EmitContext& ctx); void EmitSetIndirectBranchVariable(EmitContext& ctx); void EmitGetIndirectBranchVariable(EmitContext& ctx); -void EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex); +void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + const IR::Value& offset); +void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, + std::string_view vertex); void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, std::string_view vertex); void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); @@ -100,26 +108,33 @@ void EmitWriteGlobalS16(EmitContext& ctx); void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value); void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value); void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value); -void EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); -void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorageS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorageU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorageS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorage32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorage64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitLoadStorage128(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset); +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); -void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, std::string_view offset, std::string_view value); void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset); void EmitLoadSharedS8(EmitContext& ctx, std::string_view offset); @@ -203,12 +218,12 @@ void EmitSelectF32(EmitContext& ctx, std::string_view cond, std::string_view tru std::string_view false_value); void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, std::string_view false_value); -void EmitBitCastU16F16(EmitContext& ctx); -void EmitBitCastU32F32(EmitContext& ctx, std::string_view value); -void EmitBitCastU64F64(EmitContext& ctx); -void EmitBitCastF16U16(EmitContext& ctx); -void EmitBitCastF32U32(EmitContext& ctx, std::string_view value); -void EmitBitCastF64U64(EmitContext& ctx); +void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitPackUint2x32(EmitContext& ctx, std::string_view value); void EmitUnpackUint2x32(EmitContext& ctx, std::string_view value); void EmitPackFloat2x16(EmitContext& ctx, std::string_view value); @@ -224,26 +239,26 @@ void EmitGetOverflowFromOp(EmitContext& ctx); void EmitGetSparseFromOp(EmitContext& ctx); void EmitGetInBoundsFromOp(EmitContext& ctx); void EmitFPAbs16(EmitContext& ctx, std::string_view value); -void EmitFPAbs32(EmitContext& ctx, std::string_view value); +void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitFPAbs64(EmitContext& ctx, std::string_view value); -void EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitFPFma16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, +void EmitFPAdd16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, std::string_view c); -void EmitFPFma32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, +void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, std::string_view c); -void EmitFPFma64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, +void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, std::string_view c); void EmitFPMax32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitFPMax64(EmitContext& ctx, std::string_view a, std::string_view b); void EmitFPMin32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitFPMin64(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitFPMul16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitFPMul32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitFPMul64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitFPMul16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitFPNeg16(EmitContext& ctx, std::string_view value); -void EmitFPNeg32(EmitContext& ctx, std::string_view value); +void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitFPNeg64(EmitContext& ctx, std::string_view value); void EmitFPSin(EmitContext& ctx, std::string_view value); void EmitFPCos(EmitContext& ctx, std::string_view value); @@ -255,7 +270,7 @@ void EmitFPRecipSqrt32(EmitContext& ctx, std::string_view value); void EmitFPRecipSqrt64(EmitContext& ctx, std::string_view value); void EmitFPSqrt(EmitContext& ctx, std::string_view value); void EmitFPSaturate16(EmitContext& ctx, std::string_view value); -void EmitFPSaturate32(EmitContext& ctx, std::string_view value); +void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitFPSaturate64(EmitContext& ctx, std::string_view value); void EmitFPClamp16(EmitContext& ctx, std::string_view value, std::string_view min_value, std::string_view max_value); @@ -276,7 +291,7 @@ void EmitFPTrunc16(EmitContext& ctx, std::string_view value); void EmitFPTrunc32(EmitContext& ctx, std::string_view value); void EmitFPTrunc64(EmitContext& ctx, std::string_view value); void EmitFPOrdEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); void EmitFPOrdEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); @@ -288,7 +303,8 @@ void EmitFPUnordNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_v void EmitFPUnordNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPOrdLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); void EmitFPOrdLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); @@ -300,7 +316,8 @@ void EmitFPUnordGreaterThan16(EmitContext& ctx, std::string_view lhs, std::strin void EmitFPUnordGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPOrdLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); void EmitFPOrdLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitFPUnordLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); @@ -314,7 +331,7 @@ void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std:: void EmitFPIsNan16(EmitContext& ctx, std::string_view value); void EmitFPIsNan32(EmitContext& ctx, std::string_view value); void EmitFPIsNan64(EmitContext& ctx, std::string_view value); -void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitIAdd64(EmitContext& ctx, std::string_view a, std::string_view b); void EmitISub32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitISub64(EmitContext& ctx, std::string_view a, std::string_view b); @@ -329,14 +346,14 @@ void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::strin void EmitShiftRightLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); void EmitShiftRightArithmetic32(EmitContext& ctx, std::string_view base, std::string_view shift); void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); -void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b); +void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitBitFieldInsert(EmitContext& ctx, std::string_view base, std::string_view insert, std::string_view offset, std::string_view count); -void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, std::string_view offset, std::string_view count); -void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, std::string_view offset, std::string_view count); void EmitBitReverse32(EmitContext& ctx, std::string_view value); void EmitBitCount32(EmitContext& ctx, std::string_view value); @@ -347,9 +364,9 @@ void EmitSMin32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitUMin32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitSMax32(EmitContext& ctx, std::string_view a, std::string_view b); void EmitUMax32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, +void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, std::string_view max); -void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, +void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, std::string_view max); void EmitSLessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); void EmitULessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); @@ -544,36 +561,36 @@ void EmitBoundImageQueryLod(EmitContext&); void EmitBoundImageGradient(EmitContext&); void EmitBoundImageRead(EmitContext&); void EmitBoundImageWrite(EmitContext&); -void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view bias_lc, const IR::Value& offset); -void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view lod_lc, const IR::Value& offset); -void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view dref, std::string_view bias_lc, const IR::Value& offset); -void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view dref, std::string_view lod_lc, const IR::Value& offset); -void EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, const IR::Value& offset, const IR::Value& offset2); -void EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, const IR::Value& offset, const IR::Value& offset2, std::string_view dref); -void EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view offset, std::string_view lod, std::string_view ms); -void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view lod); -void EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords); -void EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view derivates, std::string_view offset, std::string_view lod_clamp); -void EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords); -void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view color); void EmitBindlessImageAtomicIAdd32(EmitContext&); void EmitBindlessImageAtomicSMin32(EmitContext&); @@ -597,27 +614,27 @@ void EmitBoundImageAtomicAnd32(EmitContext&); void EmitBoundImageAtomicOr32(EmitContext&); void EmitBoundImageAtomicXor32(EmitContext&); void EmitBoundImageAtomicExchange32(EmitContext&); -void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); -void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value); void EmitLaneId(EmitContext& ctx); void EmitVoteAll(EmitContext& ctx, std::string_view pred); @@ -629,15 +646,15 @@ void EmitSubgroupLtMask(EmitContext& ctx); void EmitSubgroupLeMask(EmitContext& ctx); void EmitSubgroupGtMask(EmitContext& ctx); void EmitSubgroupGeMask(EmitContext& ctx); -void EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask); -void EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view index, +void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask); -void EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask); -void EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask); void EmitFSwizzleAdd(EmitContext& ctx, std::string_view op_a, std::string_view op_b, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index e69de29bb..e228fa072 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -0,0 +1,228 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftLeftLogical32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view shift) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view insert, + [[maybe_unused]] std::string_view offset, + [[maybe_unused]] std::string_view count) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view offset, + [[maybe_unused]] std::string_view count) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view base, + [[maybe_unused]] std::string_view offset, + [[maybe_unused]] std::string_view count) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, + [[maybe_unused]] std::string_view b) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value, [[maybe_unused]] std::string_view min, + [[maybe_unused]] std::string_view max) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value, [[maybe_unused]] std::string_view min, + [[maybe_unused]] std::string_view max) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, + [[maybe_unused]] std::string_view rhs) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index e69de29bb..9e38a1bdf 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -0,0 +1,178 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +void StorageOp(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view then_expr, std::string_view else_expr = {}) { + // Operate on bindless SSBO, call the expression with bounds checking + // address = c[binding].xy + // length = c[binding].z + const u32 sb_binding{binding.U32()}; + ctx.Add("PK64.U LC,c[{}];" // pointer = address + "CVT.U64.U32 LC.z,{};" // offset = uint64_t(offset) + "ADD.U64 LC.x,LC.x,LC.z;" // pointer += offset + "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length + sb_binding, offset, offset, sb_binding); + if (else_expr.empty()) { + ctx.Add("{}", then_expr); + } else { + ctx.Add("IF NE.x;{}ELSE;{}ENDIF;", then_expr, else_expr); + } +} + +void Store(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value, std::string_view size) { + StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, value)); +} + +void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, std::string_view offset, + std::string_view size) { + const std::string ret{ctx.reg_alloc.Define(inst)}; + StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, ret), + fmt::format("MOV.U {},{{0,0,0,0}};", ret)); +} +} // Anonymous namespace + +void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobalS8([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobalU16([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobalS16([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobal32([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view address) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobal64([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view address) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadGlobal128([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view address) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobalU8([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobalS8([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobalU16([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobalS16([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view address, + [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view address, + [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteGlobal128([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] std::string_view address, + [[maybe_unused]] std::string_view value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "U8"); +} + +void EmitLoadStorageS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "S8"); +} + +void EmitLoadStorageU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "U16"); +} + +void EmitLoadStorageS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "S16"); +} + +void EmitLoadStorage32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "U32"); +} + +void EmitLoadStorage64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "U32X2"); +} + +void EmitLoadStorage128(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + std::string_view offset) { + Load(ctx, inst, binding, offset, "U32X4"); +} + +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "U8"); +} + +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "S8"); +} + +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "U16"); +} + +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "S16"); +} + +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "U32"); +} + +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "U32X2"); +} + +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, std::string_view offset, + std::string_view value) { + Store(ctx, binding, offset, value, "U32X4"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index e90224e15..1337f4ae8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -15,11 +15,9 @@ namespace Shader::Backend::GLASM { -static void NotImplemented() { - throw NotImplementedException("GLASM instruction"); -} +#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) -void EmitPhi(EmitContext& ctx, IR::Inst* inst) { +void EmitPhi(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } @@ -27,10 +25,6 @@ void EmitVoid(EmitContext& ctx) { NotImplemented(); } -void EmitIdentity(EmitContext& ctx, const IR::Value& value) { - NotImplemented(); -} - void EmitBranch(EmitContext& ctx, std::string_view label) { NotImplemented(); } @@ -50,7 +44,7 @@ void EmitSelectionMerge(EmitContext& ctx, std::string_view merge_label) { } void EmitReturn(EmitContext& ctx) { - NotImplemented(); + ctx.Add("RET;"); } void EmitJoin(EmitContext& ctx) { @@ -78,11 +72,11 @@ void EmitDeviceMemoryBarrier(EmitContext& ctx) { } void EmitPrologue(EmitContext& ctx) { - NotImplemented(); + // TODO } void EmitEpilogue(EmitContext& ctx) { - NotImplemented(); + // TODO } void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { @@ -125,72 +119,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { NotImplemented(); } -void EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex) { - NotImplemented(); -} - -void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, - std::string_view vertex) { - NotImplemented(); -} - -void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex) { - NotImplemented(); -} - -void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, - std::string_view vertex) { - NotImplemented(); -} - -void EmitGetPatch(EmitContext& ctx, IR::Patch patch) { - NotImplemented(); -} - -void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) { - NotImplemented(); -} - -void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) { - NotImplemented(); -} - -void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitSetFragDepth(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - void EmitGetZFlag(EmitContext& ctx) { NotImplemented(); } @@ -275,125 +203,6 @@ void EmitUndefU64(EmitContext& ctx) { NotImplemented(); } -void EmitLoadGlobalU8(EmitContext& ctx) { - NotImplemented(); -} - -void EmitLoadGlobalS8(EmitContext& ctx) { - NotImplemented(); -} - -void EmitLoadGlobalU16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitLoadGlobalS16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitLoadGlobal32(EmitContext& ctx, std::string_view address) { - NotImplemented(); -} - -void EmitLoadGlobal64(EmitContext& ctx, std::string_view address) { - NotImplemented(); -} - -void EmitLoadGlobal128(EmitContext& ctx, std::string_view address) { - NotImplemented(); -} - -void EmitWriteGlobalU8(EmitContext& ctx) { - NotImplemented(); -} - -void EmitWriteGlobalS8(EmitContext& ctx) { - NotImplemented(); -} - -void EmitWriteGlobalU16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitWriteGlobalS16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value) { - NotImplemented(); -} - -void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value) { - NotImplemented(); -} - -void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value) { - NotImplemented(); -} - -void EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - NotImplemented(); -} - -void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - -void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { - NotImplemented(); -} - void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset) { NotImplemented(); } @@ -644,30 +453,6 @@ void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view tru NotImplemented(); } -void EmitBitCastU16F16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitBitCastU32F32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitBitCastU64F64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitBitCastF16U16(EmitContext& ctx) { - NotImplemented(); -} - -void EmitBitCastF32U32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitBitCastF64U64(EmitContext& ctx) { - NotImplemented(); -} - void EmitPackUint2x32(EmitContext& ctx, std::string_view value) { NotImplemented(); } @@ -724,345 +509,11 @@ void EmitGetInBoundsFromOp(EmitContext& ctx) { NotImplemented(); } -void EmitFPAbs16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPAbs32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPAbs64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPFma16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, - std::string_view c) { - NotImplemented(); -} - -void EmitFPFma32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, - std::string_view c) { - NotImplemented(); -} - -void EmitFPFma64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b, - std::string_view c) { - NotImplemented(); -} - -void EmitFPMax32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMax64(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMin32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMin64(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMul16(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMul32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPMul64(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitFPNeg16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPNeg32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPNeg64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPSin(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPCos(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPExp2(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPLog2(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRecip32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRecip64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRecipSqrt32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRecipSqrt64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPSqrt(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPSaturate16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPSaturate32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPSaturate64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPClamp16(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value) { - NotImplemented(); -} - -void EmitFPClamp32(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value) { +void EmitFPIsNan16(EmitContext& ctx, std::string_view value) { NotImplemented(); } -void EmitFPClamp64(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value) { - NotImplemented(); -} - -void EmitFPRoundEven16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRoundEven32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPRoundEven64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPFloor16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPFloor32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPFloor64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPCeil16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPCeil32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPCeil64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPTrunc16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPTrunc32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPTrunc64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPOrdEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitFPIsNan16(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFPIsNan32(EmitContext& ctx, std::string_view value) { +void EmitFPIsNan32(EmitContext& ctx, std::string_view value) { NotImplemented(); } @@ -1070,179 +521,6 @@ void EmitFPIsNan64(EmitContext& ctx, std::string_view value) { NotImplemented(); } -void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitIAdd64(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitISub32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitISub64(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitIMul32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitINeg32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitINeg64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitIAbs32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitIAbs64(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitShiftLeftLogical32(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitShiftLeftLogical64(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitShiftRightLogical64(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitShiftRightArithmetic32(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::string_view shift) { - NotImplemented(); -} - -void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitBitFieldInsert(EmitContext& ctx, std::string_view base, std::string_view insert, - std::string_view offset, std::string_view count) { - NotImplemented(); -} - -void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, - std::string_view offset, std::string_view count) { - NotImplemented(); -} - -void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string_view base, - std::string_view offset, std::string_view count) { - NotImplemented(); -} - -void EmitBitReverse32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitBitCount32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitBitwiseNot32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFindSMsb32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitFindUMsb32(EmitContext& ctx, std::string_view value) { - NotImplemented(); -} - -void EmitSMin32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitUMin32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitSMax32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitUMax32(EmitContext& ctx, std::string_view a, std::string_view b) { - NotImplemented(); -} - -void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, - std::string_view max) { - NotImplemented(); -} - -void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view min, - std::string_view max) { - NotImplemented(); -} - -void EmitSLessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitULessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitIEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitSLessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitULessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitSGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitUGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitINotEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitSGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - -void EmitUGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs) { - NotImplemented(); -} - void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, std::string_view value) { NotImplemented(); @@ -1858,69 +1136,69 @@ void EmitBoundImageWrite(EmitContext&) { NotImplemented(); } -void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view bias_lc, const IR::Value& offset) { NotImplemented(); } -void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view lod_lc, const IR::Value& offset) { NotImplemented(); } -void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view dref, std::string_view bias_lc, const IR::Value& offset) { NotImplemented(); } -void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view dref, std::string_view lod_lc, const IR::Value& offset) { NotImplemented(); } -void EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, const IR::Value& offset, const IR::Value& offset2) { NotImplemented(); } -void EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, const IR::Value& offset, const IR::Value& offset2, std::string_view dref) { NotImplemented(); } -void EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view offset, std::string_view lod, std::string_view ms) { NotImplemented(); } -void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view lod) { NotImplemented(); } -void EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords) { NotImplemented(); } -void EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view derivates, std::string_view offset, std::string_view lod_clamp) { NotImplemented(); } -void EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords) { NotImplemented(); } -void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view color) { NotImplemented(); } @@ -2013,57 +1291,57 @@ void EmitBoundImageAtomicExchange32(EmitContext&) { NotImplemented(); } -void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } -void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, +void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view value) { NotImplemented(); } @@ -2108,24 +1386,24 @@ void EmitSubgroupGeMask(EmitContext& ctx) { NotImplemented(); } -void EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask) { NotImplemented(); } -void EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, std::string_view value, std::string_view index, +void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask) { NotImplemented(); } -void EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask) { NotImplemented(); } -void EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, std::string_view value, +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, std::string_view segmentation_mask) { NotImplemented(); -- cgit v1.2.3 From 2b04b4d27fc38d9865cef5bf8eabb335bc29eb83 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 8 May 2021 16:43:26 -0300 Subject: glasm: Remove unused argument in identity instructions on GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 65600f58c..7ec880c81 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -124,31 +124,31 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { return ctx.code; } -void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastU32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastF32U32(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { +void EmitBitCastF64U64(EmitContext&, IR::Inst& inst, const IR::Value& value) { Identity(inst, value); } -- cgit v1.2.3 From 3e841f6441903c6e97307dd49a2543ce82654044 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 8 May 2021 16:46:32 -0300 Subject: glasm: Use BitField instead of C bitfields --- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 10 +++++----- src/shader_recompiler/backend/glasm/reg_alloc.h | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 55e8107e9..010ad0275 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -68,11 +68,11 @@ Id RegAlloc::Alloc() { } num_used_registers = std::max(num_used_registers, reg + 1); register_use[reg] = true; - return Id{ - .index = static_cast(reg), - .is_spill = 0, - .is_condition_code = 0, - }; + Id ret{}; + ret.index.Assign(static_cast(reg)); + ret.is_spill.Assign(0); + ret.is_condition_code.Assign(0); + return ret; } throw NotImplementedException("Register spilling"); } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 83d728d20..f73aa3348 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -6,6 +6,7 @@ #include +#include "common/bit_field.h" #include "common/common_types.h" namespace Shader::IR { @@ -18,9 +19,12 @@ namespace Shader::Backend::GLASM { class EmitContext; struct Id { - u32 index : 30; - u32 is_spill : 1; - u32 is_condition_code : 1; + union { + u32 raw; + BitField<0, 30, u32> index; + BitField<30, 1, u32> is_spill; + BitField<31, 1, u32> is_condition_code; + }; }; class RegAlloc { -- cgit v1.2.3 From 941c6dc740ed368edbbc00913ace73dddecd43ba Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 8 May 2021 18:50:10 -0400 Subject: glasm: Implement BFI, BFE Along with implementations of common instructions along the way --- .../backend/glasm/emit_glasm_instructions.h | 66 +++++----- .../backend/glasm/emit_glasm_integer.cpp | 146 +++++++++++---------- .../backend/glasm/emit_glasm_not_implemented.cpp | 40 ------ .../backend/glasm/emit_glasm_select.cpp | 50 +++++++ 4 files changed, 164 insertions(+), 138 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 30cc6c2eb..13f47b253 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -208,8 +208,8 @@ void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true std::string_view false_value); void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value, std::string_view false_value); -void EmitSelectU32(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); +void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, + std::string_view true_value, std::string_view false_value); void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view true_value, std::string_view false_value); void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, @@ -332,14 +332,14 @@ void EmitFPIsNan16(EmitContext& ctx, std::string_view value); void EmitFPIsNan32(EmitContext& ctx, std::string_view value); void EmitFPIsNan64(EmitContext& ctx, std::string_view value); void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitIAdd64(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitISub32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitISub64(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitIMul32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitINeg32(EmitContext& ctx, std::string_view value); -void EmitINeg64(EmitContext& ctx, std::string_view value); -void EmitIAbs32(EmitContext& ctx, std::string_view value); -void EmitIAbs64(EmitContext& ctx, std::string_view value); +void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitISub32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitISub64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitShiftLeftLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); void EmitShiftLeftLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); @@ -349,35 +349,39 @@ void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::st void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitBitFieldInsert(EmitContext& ctx, std::string_view base, std::string_view insert, - std::string_view offset, std::string_view count); +void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, + std::string_view insert, std::string_view offset, std::string_view count); void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, std::string_view offset, std::string_view count); void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, std::string_view offset, std::string_view count); -void EmitBitReverse32(EmitContext& ctx, std::string_view value); -void EmitBitCount32(EmitContext& ctx, std::string_view value); -void EmitBitwiseNot32(EmitContext& ctx, std::string_view value); -void EmitFindSMsb32(EmitContext& ctx, std::string_view value); -void EmitFindUMsb32(EmitContext& ctx, std::string_view value); -void EmitSMin32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitUMin32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitSMax32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitUMax32(EmitContext& ctx, std::string_view a, std::string_view b); +void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitBitCount32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitFindSMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitFindUMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitSMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitUMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitSMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); +void EmitUMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, std::string_view max); void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, std::string_view max); -void EmitSLessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitULessThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitIEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitSLessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitULessThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitSGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitUGreaterThan(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitINotEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitSGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitUGreaterThanEqual(EmitContext& ctx, std::string_view lhs, std::string_view rhs); +void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitULessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitIEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); +void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); +void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); +void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); +void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, + std::string_view rhs); void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, std::string_view value); void EmitSharedAtomicSMin32(EmitContext& ctx, std::string_view pointer_offset, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index e228fa072..d4e519a2a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -12,42 +12,46 @@ namespace Shader::Backend::GLASM { void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("ADD {},{},{};", inst, a, b); } -void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); +void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + ctx.Add("SUB {},{},{};", inst, a, b); } -void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } @@ -94,7 +98,7 @@ void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::In void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("OR {},{},{};", inst, a, b); } void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -102,64 +106,66 @@ void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::In throw NotImplementedException("GLASM instruction"); } -void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view insert, - [[maybe_unused]] std::string_view offset, - [[maybe_unused]] std::string_view count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, + std::string_view insert, std::string_view offset, std::string_view count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFI.U {},RC,{},{};", inst, insert, base); } -void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view offset, - [[maybe_unused]] std::string_view count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, + std::string_view offset, std::string_view count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFE.S {},RC,{};", inst, base); } -void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view offset, - [[maybe_unused]] std::string_view count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, + std::string_view offset, std::string_view count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFE.U {},RC,{};", inst, base); } -void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { - throw NotImplementedException("GLASM instruction"); +void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + ctx.Add("BFR {},{};", inst, value); } -void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { throw NotImplementedException("GLASM instruction"); } -void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } -void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { throw NotImplementedException("GLASM instruction"); } @@ -175,54 +181,60 @@ void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& throw NotImplementedException("GLASM instruction"); } -void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { + ctx.Add("SLT.S {},{},{};", inst, lhs, rhs); } -void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { + ctx.Add("SLT.U {},{},{};", inst, lhs, rhs); } -void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { + ctx.Add("SEQ {},{},{};", inst, lhs, rhs); } -void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SLE.S {},{},{};", inst, lhs, rhs); } -void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SLE.U {},{},{};", inst, lhs, rhs); } -void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SGT.S {},{},{};", inst, lhs, rhs); } -void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SGT.U {},{},{};", inst, lhs, rhs); } -void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SGE.S {},{},{};", inst, lhs, rhs); } -void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, +void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SGE.U {},{},{};", inst, lhs, rhs); } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 1337f4ae8..32eb87837 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -413,46 +413,6 @@ void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std: NotImplemented(); } -void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectU32(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectF32(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - -void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value) { - NotImplemented(); -} - void EmitPackUint2x32(EmitContext& ctx, std::string_view value) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index e69de29bb..636cbe8a0 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitSelectU1(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU8(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU16(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, + std::string_view true_value, std::string_view false_value) { + ctx.Add("MOV.U.CC RC,{};", cond); + ctx.Add("IF NE.x;"); + ctx.Add("MOV.U {},{};", inst, true_value); + ctx.Add("ELSE;"); + ctx.Add("MOV.U {},{};", inst, false_value); + ctx.Add("ENDIF;"); +} + +void EmitSelectU64(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectF16(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectF32(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectF64(EmitContext&, std::string_view, std::string_view, std::string_view) { + throw NotImplementedException("GLASM instruction"); +} +} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 68cc445b8ef7c7057087e2b6c7015d888a80bac2 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 8 May 2021 18:59:05 -0400 Subject: glasm: Implement more logical ops --- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 8 ++++---- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index d4e519a2a..1289d950f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -93,7 +93,7 @@ void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("AND {},{},{};", inst, a, b); } void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -103,7 +103,7 @@ void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Ins void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("XOR {},{},{};", inst, a, b); } void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, @@ -136,7 +136,7 @@ void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view value) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("NOT {},{};", inst, value); } void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -222,7 +222,7 @@ void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::In void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - throw NotImplementedException("GLASM instruction"); + ctx.Add("SNE.U {},{},{};", inst, lhs, rhs); } void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 010ad0275..e198dd522 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -33,7 +33,7 @@ std::string ImmValue(const IR::Value& value) { case IR::Type::F32: return fmt::format("{}", value.F32()); default: - throw NotImplementedException("Immediate type", value.Type()); + throw NotImplementedException("Immediate type {}", value.Type()); } } } // Anonymous namespace -- cgit v1.2.3 From 934d3002462e27bcc289c1edb4959896cb23beb0 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 8 May 2021 19:21:32 -0400 Subject: glasm: Use CMP.S for Select32 also fixes ADD and SUB to use U modifier --- .../backend/glasm/emit_glasm_instructions.h | 4 ++-- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 4 ++-- src/shader_recompiler/backend/glasm/emit_glasm_select.cpp | 12 ++++-------- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 13f47b253..222285021 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -214,8 +214,8 @@ void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view tru std::string_view false_value); void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, std::string_view false_value); -void EmitSelectF32(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); +void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, + std::string_view true_value, std::string_view false_value); void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, std::string_view false_value); void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 1289d950f..579806c38 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -12,7 +12,7 @@ namespace Shader::Backend::GLASM { void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("ADD {},{},{};", inst, a, b); + ctx.Add("ADD.U {},{},{};", inst, a, b); } void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -22,7 +22,7 @@ void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& in void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("SUB {},{},{};", inst, a, b); + ctx.Add("SUB.U {},{},{};", inst, a, b); } void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index 636cbe8a0..16f6c33f3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -24,12 +24,7 @@ void EmitSelectU16(EmitContext&, std::string_view, std::string_view, std::string void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, std::string_view true_value, std::string_view false_value) { - ctx.Add("MOV.U.CC RC,{};", cond); - ctx.Add("IF NE.x;"); - ctx.Add("MOV.U {},{};", inst, true_value); - ctx.Add("ELSE;"); - ctx.Add("MOV.U {},{};", inst, false_value); - ctx.Add("ENDIF;"); + ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); } void EmitSelectU64(EmitContext&, std::string_view, std::string_view, std::string_view) { @@ -40,8 +35,9 @@ void EmitSelectF16(EmitContext&, std::string_view, std::string_view, std::string throw NotImplementedException("GLASM instruction"); } -void EmitSelectF32(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); +void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, + std::string_view true_value, std::string_view false_value) { + ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); } void EmitSelectF64(EmitContext&, std::string_view, std::string_view, std::string_view) { -- cgit v1.2.3 From 1c9307969c4e3f6206947f1360acae33f95a4a86 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 03:11:34 -0300 Subject: glasm: Make GLASM aware of types --- src/shader_recompiler/backend/glasm/emit_context.h | 8 +- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 95 ++- .../backend/glasm/emit_glasm_composite.cpp | 225 ++++++ .../backend/glasm/emit_glasm_context_get_set.cpp | 53 +- .../backend/glasm/emit_glasm_floating_point.cpp | 299 ++++---- .../backend/glasm/emit_glasm_instructions.h | 844 ++++++++++----------- .../backend/glasm/emit_glasm_integer.cpp | 216 +++--- .../backend/glasm/emit_glasm_memory.cpp | 77 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 515 +++++-------- .../backend/glasm/emit_glasm_select.cpp | 46 -- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 62 +- src/shader_recompiler/backend/glasm/reg_alloc.h | 184 ++++- 12 files changed, 1380 insertions(+), 1244 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 4f98a9816..a59acbf6c 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -23,15 +23,15 @@ public: explicit EmitContext(IR::Program& program); template - void Add(const char* fmt, IR::Inst& inst, Args&&... args) { - code += fmt::format(fmt, reg_alloc.Define(inst), std::forward(args)...); + void Add(const char* format_str, IR::Inst& inst, Args&&... args) { + code += fmt::format(format_str, reg_alloc.Define(inst), std::forward(args)...); // TODO: Remove this code += '\n'; } template - void Add(const char* fmt, Args&&... args) { - code += fmt::format(fmt, std::forward(args)...); + void Add(const char* format_str, Args&&... args) { + code += fmt::format(format_str, std::forward(args)...); // TODO: Remove this code += '\n'; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 7ec880c81..8981cf300 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -27,22 +27,80 @@ struct FuncTraits { using ArgType = std::tuple_element_t>; }; +template +struct Identity { + Identity(const T& data_) : data{data_} {} + + const T& Extract() { + return data; + } + + T data; +}; + +template +struct RegWrapper { + RegWrapper(EmitContext& ctx, Value value) + : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { + reg = allocated ? reg_alloc.AllocReg() : Register{value}; + switch (value.type) { + case Type::Register: + break; + case Type::U32: + ctx.Add("MOV.U {}.x,{};", reg, value.imm_u32); + break; + case Type::S32: + ctx.Add("MOV.S {}.x,{};", reg, value.imm_s32); + break; + case Type::F32: + ctx.Add("MOV.F {}.x,{};", reg, value.imm_f32); + break; + } + } + ~RegWrapper() { + if (allocated) { + reg_alloc.FreeReg(reg); + } + } + + auto Extract() { + return std::conditional_t{Value{reg}}; + } + + RegAlloc& reg_alloc; + Register reg{}; + bool allocated{}; +}; + template auto Arg(EmitContext& ctx, const IR::Value& arg) { - if constexpr (std::is_same_v) { - return ctx.reg_alloc.Consume(arg); + if constexpr (std::is_same_v) { + return RegWrapper{ctx, ctx.reg_alloc.Consume(arg)}; + } else if constexpr (std::is_same_v) { + return RegWrapper{ctx, ctx.reg_alloc.Consume(arg)}; + } else if constexpr (std::is_base_of_v) { + return Identity{ArgType{ctx.reg_alloc.Consume(arg)}}; } else if constexpr (std::is_same_v) { - return arg; + return Identity{arg}; } else if constexpr (std::is_same_v) { - return arg.U32(); + return Identity{arg.U32()}; } else if constexpr (std::is_same_v) { - return arg.Label(); + return Identity{arg.Label()}; } else if constexpr (std::is_same_v) { - return arg.Attribute(); + return Identity{arg.Attribute()}; } else if constexpr (std::is_same_v) { - return arg.Patch(); + return Identity{arg.Patch()}; } else if constexpr (std::is_same_v) { - return arg.Reg(); + return Identity{arg.Reg()}; + } +} + +template +void InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) { + if constexpr (is_first_arg_inst) { + func(ctx, *inst, std::forward(args.Extract())...); + } else { + func(ctx, std::forward(args.Extract())...); } } @@ -50,9 +108,10 @@ template void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence) { using Traits = FuncTraits; if constexpr (is_first_arg_inst) { - func(ctx, *inst, Arg>(ctx, inst->Arg(I))...); + func(ctx, *inst, + Arg>(ctx, inst->Arg(I)).Extract()...); } else { - func(ctx, Arg>(ctx, inst->Arg(I))...); + func(ctx, Arg>(ctx, inst->Arg(I)).Extract()...); } } @@ -81,7 +140,7 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { throw LogicError("Invalid opcode {}", inst->GetOpcode()); } -void Identity(IR::Inst& inst, const IR::Value& value) { +void Alias(IR::Inst& inst, const IR::Value& value) { if (value.IsImmediate()) { return; } @@ -125,31 +184,31 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { } void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastU32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastF32U32(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } void EmitBitCastF64U64(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Identity(inst, value); + Alias(inst, value); } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index e69de29bb..063dcaf13 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp @@ -0,0 +1,225 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +template +void CompositeConstructU32(EmitContext& ctx, IR::Inst& inst, Values&&... elements) { + const Register ret{ctx.reg_alloc.Define(inst)}; + if (std::ranges::any_of(std::array{elements...}, + [](const IR::Value& value) { return value.IsImmediate(); })) { + const std::array values{(elements.IsImmediate() ? elements.U32() : 0)...}; + ctx.Add("MOV.U {},{{{},{},{},{}}};", ret, fmt::to_string(values[0]), + fmt::to_string(values[1]), fmt::to_string(values[2]), fmt::to_string(values[3])); + } + size_t index{}; + for (const IR::Value& element : {elements...}) { + if (!element.IsImmediate()) { + const ScalarU32 value{ctx.reg_alloc.Consume(element)}; + ctx.Add("MOV.U {}.{},{};", ret, "xyzw"[index], value); + } + ++index; + } +} + +void CompositeExtractU32(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + const Register ret{ctx.reg_alloc.Define(inst)}; + if (ret == composite && index == 0) { + // No need to do anything here, the source and destination are the same register + return; + } + ctx.Add("MOV.U {}.x,{}.{};", ret, composite, "xyzw"[index]); +} +} // Anonymous namespace + +void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2) { + CompositeConstructU32(ctx, inst, e1, e2); +} + +void EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3) { + CompositeConstructU32(ctx, inst, e1, e2, e3); +} + +void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) { + CompositeConstructU32(ctx, inst, e1, e2, e3, e4); +} + +void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtractU32(ctx, inst, composite, index); +} + +void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtractU32(ctx, inst, composite, index); +} + +void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtractU32(ctx, inst, composite, index); +} + +void EmitCompositeInsertU32x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertU32x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertU32x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF16x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, + [[maybe_unused]] Register e2) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF16x3([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, + [[maybe_unused]] Register e2, [[maybe_unused]] Register e3) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF16x4([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, + [[maybe_unused]] Register e2, [[maybe_unused]] Register e3, + [[maybe_unused]] Register e4) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF16x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF16x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF16x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF16x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF16x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF16x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, + [[maybe_unused]] ScalarF32 e2) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF32x3([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, + [[maybe_unused]] ScalarF32 e2, [[maybe_unused]] ScalarF32 e3) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF32x4([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, + [[maybe_unused]] ScalarF32 e2, [[maybe_unused]] ScalarF32 e3, + [[maybe_unused]] ScalarF32 e4) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF32x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF32x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF32x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF32x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF32x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF32x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, + [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF64x3([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeConstructF64x4([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF64x2([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF64x3([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeExtractF64x4([[maybe_unused]] EmitContext& ctx) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF64x2([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF64x3([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitCompositeInsertF64x4([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] Register composite, [[maybe_unused]] Register object, + [[maybe_unused]] u32 index) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 72733d1cf..fed79e381 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -10,64 +10,58 @@ namespace Shader::Backend::GLASM { namespace { -void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset, +void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, std::string_view size) { if (!binding.IsImmediate()) { throw NotImplementedException("Indirect constant buffer loading"); } - const std::string ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), ctx.reg_alloc.Consume(offset)); + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset); } } // Anonymous namespace -void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "U8"); } -void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "S8"); } -void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "U16"); } -void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "S16"); } -void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "U32"); } -void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { +void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "F32"); } void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset) { + ScalarU32 offset) { GetCbuf(ctx, inst, binding, offset, "U32X2"); } void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, - [[maybe_unused]] std::string_view vertex) { + [[maybe_unused]] ScalarU32 vertex) { if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; const u32 element{IR::GenericAttributeElement(attr)}; - ctx.Add("MOV.F {},in_attr{}.{};", inst, index, "xyzw"[element]); + ctx.Add("MOV.F {}.x,in_attr{}.{};", inst, index, "xyzw"[element]); return; } throw NotImplementedException("Get attribute {}", attr); } -void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, - [[maybe_unused]] std::string_view vertex) { +void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, + [[maybe_unused]] ScalarU32 vertex) { const u32 element{static_cast(attr) % 4}; const char swizzle{"xyzw"[element]}; if (IR::IsGeneric(attr)) { @@ -87,16 +81,13 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val } } -void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view offset, - [[maybe_unused]] std::string_view vertex) { +void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarU32 vertex) { throw NotImplementedException("GLASM instruction"); } -void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view offset, - [[maybe_unused]] std::string_view value, - [[maybe_unused]] std::string_view vertex) { +void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarF32 value, [[maybe_unused]] ScalarU32 vertex) { throw NotImplementedException("GLASM instruction"); } @@ -105,20 +96,20 @@ void EmitGetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch } void EmitSetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch, - [[maybe_unused]] std::string_view value) { + [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } void EmitSetFragColor([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] u32 index, - [[maybe_unused]] u32 component, [[maybe_unused]] std::string_view value) { + [[maybe_unused]] u32 component, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitSetSampleMask([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitSetSampleMask([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitSetFragDepth([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitSetFragDepth([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index db9dda261..fed6503c6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -10,411 +10,382 @@ namespace Shader::Backend::GLASM { -void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { - ctx.Add("MOV.F {},|{}|;", inst, value); +void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("MOV.F {}.x,|{}|;", inst, value); } -void EmitFPAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { - ctx.Add("ADD.F {},{},{};", inst, a, b); +void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { + ctx.Add("ADD.F {}.x,{},{};", inst, a, b); } void EmitFPAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b, - [[maybe_unused]] std::string_view c) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b, + [[maybe_unused]] Register c) { throw NotImplementedException("GLASM instruction"); } -void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, - std::string_view c) { - ctx.Add("MAD.F {},{},{},{};", inst, a, b, c); +void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c) { + ctx.Add("MAD.F {}.x,{},{},{};", inst, a, b, c); } void EmitFPFma64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b, - [[maybe_unused]] std::string_view c) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b, + [[maybe_unused]] Register c) { throw NotImplementedException("GLASM instruction"); } -void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, + [[maybe_unused]] ScalarF32 b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPMax64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitFPMax64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, + [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, + [[maybe_unused]] ScalarF32 b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPMin64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view a, - [[maybe_unused]] std::string_view b) { +void EmitFPMin64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, + [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { - ctx.Add("MUL.F {},{},{};", inst, a, b); +void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { + ctx.Add("MUL.F {}.x,{},{};", inst, a, b); } void EmitFPMul64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { + [[maybe_unused]] Register a, [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { - if (value[0] == '-') { - // Guard against negating a negative immediate - ctx.Add("MOV.F {},{};", inst, value.substr(1)); - } else { - ctx.Add("MOV.F {},-{};", inst, value); - } +void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value) { + ctx.Add("MOV.F {}.x,-{};", inst, value); } -void EmitFPNeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPNeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPSin([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPSin([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPCos([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPCos([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPExp2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPExp2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPLog2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPLog2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRecip32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRecip32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRecip64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRecip64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPSqrt([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPSqrt([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { - ctx.Add("MOV.F.SAT {},{};", inst, value); +void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("MOV.F.SAT {}.x,{};", inst, value); } -void EmitFPSaturate64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPSaturate64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, - [[maybe_unused]] std::string_view min_value, - [[maybe_unused]] std::string_view max_value) { +void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value, + [[maybe_unused]] Register min_value, [[maybe_unused]] Register max_value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, - [[maybe_unused]] std::string_view min_value, - [[maybe_unused]] std::string_view max_value) { +void EmitFPClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value, + [[maybe_unused]] ScalarF32 min_value, [[maybe_unused]] ScalarF32 max_value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPClamp64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value, - [[maybe_unused]] std::string_view min_value, - [[maybe_unused]] std::string_view max_value) { +void EmitFPClamp64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value, + [[maybe_unused]] Register min_value, [[maybe_unused]] Register max_value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRoundEven32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRoundEven32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRoundEven64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPRoundEven64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPFloor16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPFloor16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPFloor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPFloor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPFloor64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPFloor64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPCeil16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPCeil16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPCeil32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPCeil32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPCeil64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPCeil64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPTrunc16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPTrunc16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPTrunc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPTrunc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPTrunc64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view value) { +void EmitFPTrunc64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs) { - const std::string ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SEQ.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SEQ.F {}.x,{},{};SNE.S {}.x,{},0;", ret, lhs, rhs, ret, ret); } -void EmitFPOrdEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs) { - const std::string ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SLT.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SLT.F {}.x,{},{};SNE.S {}.x,{}.x,0;", ret, lhs, rhs, ret, ret); } -void EmitFPOrdLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThan32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThan64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThan32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordGreaterThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThan64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordGreaterThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs) { - const std::string ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SLE.F {},{},{};SNE.S {},{},0;", ret, lhs, rhs, ret, ret); +void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("SLE.F {}.x,{},{};SNE.S {}.x,{}.x,0;", ret, lhs, rhs, ret, ret); } -void EmitFPOrdLessThanEqual64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdLessThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThanEqual32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThanEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThanEqual64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordLessThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, + [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPOrdGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } void EmitFPUnordGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { + [[maybe_unused]] ScalarF32 lhs, [[maybe_unused]] ScalarF32 rhs) { throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { +void EmitFPUnordGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, + [[maybe_unused]] Register rhs) { throw NotImplementedException("GLASM instruction"); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 222285021..6db76bf46 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -4,9 +4,8 @@ #pragma once -#include - #include "common/common_types.h" +#include "shader_recompiler/backend/glasm/reg_alloc.h" namespace Shader::IR { enum class Attribute : u64; @@ -23,15 +22,14 @@ class EmitContext; void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitBranch(EmitContext& ctx, std::string_view label); -void EmitBranchConditional(EmitContext& ctx, std::string_view condition, - std::string_view true_label, std::string_view false_label); -void EmitLoopMerge(EmitContext& ctx, std::string_view merge_label, std::string_view continue_label); -void EmitSelectionMerge(EmitContext& ctx, std::string_view merge_label); +void EmitBranch(EmitContext& ctx); +void EmitBranchConditional(EmitContext& ctx); +void EmitLoopMerge(EmitContext& ctx); +void EmitSelectionMerge(EmitContext& ctx); void EmitReturn(EmitContext& ctx); void EmitJoin(EmitContext& ctx); void EmitUnreachable(EmitContext& ctx); -void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label); +void EmitDemoteToHelperInvocation(EmitContext& ctx); void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); @@ -47,32 +45,22 @@ void EmitSetGotoVariable(EmitContext& ctx); void EmitGetGotoVariable(EmitContext& ctx); void EmitSetIndirectBranchVariable(EmitContext& ctx); void EmitGetIndirectBranchVariable(EmitContext& ctx); -void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - const IR::Value& offset); -void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, - std::string_view vertex); -void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, - std::string_view vertex); -void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); -void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, - std::string_view vertex); +void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); +void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); +void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); +void EmitGetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarU32 vertex); +void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); void EmitGetPatch(EmitContext& ctx, IR::Patch patch); -void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value); -void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value); -void EmitSetSampleMask(EmitContext& ctx, std::string_view value); -void EmitSetFragDepth(EmitContext& ctx, std::string_view value); +void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value); +void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value); +void EmitSetSampleMask(EmitContext& ctx, ScalarF32 value); +void EmitSetFragDepth(EmitContext& ctx, ScalarF32 value); void EmitGetZFlag(EmitContext& ctx); void EmitGetSFlag(EmitContext& ctx); void EmitGetCFlag(EmitContext& ctx); @@ -82,13 +70,13 @@ void EmitSetSFlag(EmitContext& ctx); void EmitSetCFlag(EmitContext& ctx); void EmitSetOFlag(EmitContext& ctx); void EmitWorkgroupId(EmitContext& ctx); -void EmitLocalInvocationId(EmitContext& ctx); +void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitInvocationId(EmitContext& ctx); void EmitSampleId(EmitContext& ctx); void EmitIsHelperInvocation(EmitContext& ctx); void EmitYDirection(EmitContext& ctx); -void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset); -void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value); +void EmitLoadLocal(EmitContext& ctx, ScalarU32 word_offset); +void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value); void EmitUndefU1(EmitContext& ctx); void EmitUndefU8(EmitContext& ctx); void EmitUndefU16(EmitContext& ctx); @@ -98,368 +86,321 @@ void EmitLoadGlobalU8(EmitContext& ctx); void EmitLoadGlobalS8(EmitContext& ctx); void EmitLoadGlobalU16(EmitContext& ctx); void EmitLoadGlobalS16(EmitContext& ctx); -void EmitLoadGlobal32(EmitContext& ctx, std::string_view address); -void EmitLoadGlobal64(EmitContext& ctx, std::string_view address); -void EmitLoadGlobal128(EmitContext& ctx, std::string_view address); +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 EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value); -void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value); -void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view 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); void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorageS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorageU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorageS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorage32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorage64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); + ScalarU32 offset); void EmitLoadStorage128(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset); -void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value); -void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedS8(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedU16(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedS16(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedU32(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedU64(EmitContext& ctx, std::string_view offset); -void EmitLoadSharedU128(EmitContext& ctx, std::string_view offset); -void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value); -void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value); -void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value); -void EmitWriteSharedU64(EmitContext& ctx, std::string_view offset, std::string_view value); -void EmitWriteSharedU128(EmitContext& ctx, std::string_view offset, std::string_view value); -void EmitCompositeConstructU32x2(EmitContext& ctx, std::string_view e1, std::string_view e2); -void EmitCompositeConstructU32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3); -void EmitCompositeConstructU32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4); -void EmitCompositeExtractU32x2(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractU32x3(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractU32x4(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2); -void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3); -void EmitCompositeConstructF16x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4); -void EmitCompositeExtractF16x2(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractF16x3(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractF16x4(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeInsertF16x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF16x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF16x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeConstructF32x2(EmitContext& ctx, std::string_view e1, std::string_view e2); -void EmitCompositeConstructF32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3); -void EmitCompositeConstructF32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4); -void EmitCompositeExtractF32x2(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractF32x3(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeExtractF32x4(EmitContext& ctx, std::string_view composite, u32 index); -void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); + ScalarU32 offset); +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value); +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarS32 value); +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value); +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarS32 value); +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value); +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + Register value); +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + Register value); +void EmitLoadSharedU8(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedS8(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU16(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedS16(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU32(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU64(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU128(EmitContext& ctx, ScalarU32 offset); +void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); +void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); +void EmitWriteSharedU32(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); +void EmitWriteSharedU64(EmitContext& ctx, ScalarU32 offset, Register value); +void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value); +void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2); +void EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3); +void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3, const IR::Value& e4); +void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeInsertU32x2(EmitContext& ctx, Register composite, ScalarU32 object, u32 index); +void EmitCompositeInsertU32x3(EmitContext& ctx, Register composite, ScalarU32 object, u32 index); +void EmitCompositeInsertU32x4(EmitContext& ctx, Register composite, ScalarU32 object, u32 index); +void EmitCompositeConstructF16x2(EmitContext& ctx, Register e1, Register e2); +void EmitCompositeConstructF16x3(EmitContext& ctx, Register e1, Register e2, Register e3); +void EmitCompositeConstructF16x4(EmitContext& ctx, Register e1, Register e2, Register e3, + Register e4); +void EmitCompositeExtractF16x2(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeExtractF16x3(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeExtractF16x4(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeInsertF16x2(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitCompositeInsertF16x3(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitCompositeInsertF16x4(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitCompositeConstructF32x2(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2); +void EmitCompositeConstructF32x3(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2, ScalarF32 e3); +void EmitCompositeConstructF32x4(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2, ScalarF32 e3, + ScalarF32 e4); +void EmitCompositeExtractF32x2(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeExtractF32x3(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeExtractF32x4(EmitContext& ctx, Register composite, u32 index); +void EmitCompositeInsertF32x2(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); +void EmitCompositeInsertF32x3(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); +void EmitCompositeInsertF32x4(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); void EmitCompositeConstructF64x2(EmitContext& ctx); void EmitCompositeConstructF64x3(EmitContext& ctx); void EmitCompositeConstructF64x4(EmitContext& ctx); void EmitCompositeExtractF64x2(EmitContext& ctx); void EmitCompositeExtractF64x3(EmitContext& ctx); void EmitCompositeExtractF64x4(EmitContext& ctx); -void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index); -void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); -void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); -void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); -void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, - std::string_view true_value, std::string_view false_value); -void EmitSelectU64(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); -void EmitSelectF16(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); -void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, - std::string_view true_value, std::string_view false_value); -void EmitSelectF64(EmitContext& ctx, std::string_view cond, std::string_view true_value, - std::string_view false_value); +void EmitCompositeInsertF64x2(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitCompositeInsertF64x3(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitCompositeInsertF64x4(EmitContext& ctx, Register composite, Register object, u32 index); +void EmitSelectU1(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); +void EmitSelectF16(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); +void EmitSelectF32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitPackUint2x32(EmitContext& ctx, std::string_view value); -void EmitUnpackUint2x32(EmitContext& ctx, std::string_view value); -void EmitPackFloat2x16(EmitContext& ctx, std::string_view value); -void EmitUnpackFloat2x16(EmitContext& ctx, std::string_view value); -void EmitPackHalf2x16(EmitContext& ctx, std::string_view value); -void EmitUnpackHalf2x16(EmitContext& ctx, std::string_view value); -void EmitPackDouble2x32(EmitContext& ctx, std::string_view value); -void EmitUnpackDouble2x32(EmitContext& ctx, std::string_view value); +void EmitPackUint2x32(EmitContext& ctx, Register value); +void EmitUnpackUint2x32(EmitContext& ctx, Register value); +void EmitPackFloat2x16(EmitContext& ctx, Register value); +void EmitUnpackFloat2x16(EmitContext& ctx, Register value); +void EmitPackHalf2x16(EmitContext& ctx, Register value); +void EmitUnpackHalf2x16(EmitContext& ctx, Register value); +void EmitPackDouble2x32(EmitContext& ctx, Register value); +void EmitUnpackDouble2x32(EmitContext& ctx, Register value); void EmitGetZeroFromOp(EmitContext& ctx); void EmitGetSignFromOp(EmitContext& ctx); void EmitGetCarryFromOp(EmitContext& ctx); void EmitGetOverflowFromOp(EmitContext& ctx); void EmitGetSparseFromOp(EmitContext& ctx); void EmitGetInBoundsFromOp(EmitContext& ctx); -void EmitFPAbs16(EmitContext& ctx, std::string_view value); -void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitFPAbs64(EmitContext& ctx, std::string_view value); -void EmitFPAdd16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, - std::string_view c); -void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, - std::string_view c); -void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, - std::string_view c); -void EmitFPMax32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitFPMax64(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitFPMin32(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitFPMin64(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitFPMul16(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitFPNeg16(EmitContext& ctx, std::string_view value); -void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitFPNeg64(EmitContext& ctx, std::string_view value); -void EmitFPSin(EmitContext& ctx, std::string_view value); -void EmitFPCos(EmitContext& ctx, std::string_view value); -void EmitFPExp2(EmitContext& ctx, std::string_view value); -void EmitFPLog2(EmitContext& ctx, std::string_view value); -void EmitFPRecip32(EmitContext& ctx, std::string_view value); -void EmitFPRecip64(EmitContext& ctx, std::string_view value); -void EmitFPRecipSqrt32(EmitContext& ctx, std::string_view value); -void EmitFPRecipSqrt64(EmitContext& ctx, std::string_view value); -void EmitFPSqrt(EmitContext& ctx, std::string_view value); -void EmitFPSaturate16(EmitContext& ctx, std::string_view value); -void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitFPSaturate64(EmitContext& ctx, std::string_view value); -void EmitFPClamp16(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value); -void EmitFPClamp32(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value); -void EmitFPClamp64(EmitContext& ctx, std::string_view value, std::string_view min_value, - std::string_view max_value); -void EmitFPRoundEven16(EmitContext& ctx, std::string_view value); -void EmitFPRoundEven32(EmitContext& ctx, std::string_view value); -void EmitFPRoundEven64(EmitContext& ctx, std::string_view value); -void EmitFPFloor16(EmitContext& ctx, std::string_view value); -void EmitFPFloor32(EmitContext& ctx, std::string_view value); -void EmitFPFloor64(EmitContext& ctx, std::string_view value); -void EmitFPCeil16(EmitContext& ctx, std::string_view value); -void EmitFPCeil32(EmitContext& ctx, std::string_view value); -void EmitFPCeil64(EmitContext& ctx, std::string_view value); -void EmitFPTrunc16(EmitContext& ctx, std::string_view value); -void EmitFPTrunc32(EmitContext& ctx, std::string_view value); -void EmitFPTrunc64(EmitContext& ctx, std::string_view value); -void EmitFPOrdEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitFPOrdEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordNotEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordNotEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordNotEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitFPOrdLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThan16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThan32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThan64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitFPOrdLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordLessThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, std::string_view lhs, std::string_view rhs); -void EmitFPIsNan16(EmitContext& ctx, std::string_view value); -void EmitFPIsNan32(EmitContext& ctx, std::string_view value); -void EmitFPIsNan64(EmitContext& ctx, std::string_view value); -void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitISub32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitISub64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitShiftLeftLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitShiftLeftLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitShiftRightLogical32(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitShiftRightLogical64(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitShiftRightArithmetic32(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitShiftRightArithmetic64(EmitContext& ctx, std::string_view base, std::string_view shift); -void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view insert, std::string_view offset, std::string_view count); -void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view offset, std::string_view count); -void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view offset, std::string_view count); -void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitBitCount32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitFindSMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitFindUMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value); -void EmitSMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitUMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitSMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitUMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b); -void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, - std::string_view max); -void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min, - std::string_view max); -void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitULessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitIEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs); -void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, - std::string_view rhs); -void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicSMin32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicUMin32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicSMax32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicUMax32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicInc32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicDec32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicAnd32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicOr32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicXor32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicExchange32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); -void EmitSharedAtomicExchange64(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value); +void EmitFPAbs16(EmitContext& ctx, Register value); +void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPAbs64(EmitContext& ctx, Register value); +void EmitFPAdd16(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); +void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); +void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c); +void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); +void EmitFPMax32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); +void EmitFPMax64(EmitContext& ctx, Register a, Register b); +void EmitFPMin32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); +void EmitFPMin64(EmitContext& ctx, Register a, Register b); +void EmitFPMul16(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); +void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPNeg16(EmitContext& ctx, Register value); +void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value); +void EmitFPNeg64(EmitContext& ctx, Register value); +void EmitFPSin(EmitContext& ctx, ScalarF32 value); +void EmitFPCos(EmitContext& ctx, ScalarF32 value); +void EmitFPExp2(EmitContext& ctx, ScalarF32 value); +void EmitFPLog2(EmitContext& ctx, ScalarF32 value); +void EmitFPRecip32(EmitContext& ctx, ScalarF32 value); +void EmitFPRecip64(EmitContext& ctx, Register value); +void EmitFPRecipSqrt32(EmitContext& ctx, ScalarF32 value); +void EmitFPRecipSqrt64(EmitContext& ctx, Register value); +void EmitFPSqrt(EmitContext& ctx, ScalarF32 value); +void EmitFPSaturate16(EmitContext& ctx, Register value); +void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPSaturate64(EmitContext& ctx, Register value); +void EmitFPClamp16(EmitContext& ctx, Register value, Register min_value, Register max_value); +void EmitFPClamp32(EmitContext& ctx, ScalarF32 value, ScalarF32 min_value, ScalarF32 max_value); +void EmitFPClamp64(EmitContext& ctx, Register value, Register min_value, Register max_value); +void EmitFPRoundEven16(EmitContext& ctx, Register value); +void EmitFPRoundEven32(EmitContext& ctx, ScalarF32 value); +void EmitFPRoundEven64(EmitContext& ctx, Register value); +void EmitFPFloor16(EmitContext& ctx, Register value); +void EmitFPFloor32(EmitContext& ctx, ScalarF32 value); +void EmitFPFloor64(EmitContext& ctx, Register value); +void EmitFPCeil16(EmitContext& ctx, Register value); +void EmitFPCeil32(EmitContext& ctx, ScalarF32 value); +void EmitFPCeil64(EmitContext& ctx, Register value); +void EmitFPTrunc16(EmitContext& ctx, Register value); +void EmitFPTrunc32(EmitContext& ctx, ScalarF32 value); +void EmitFPTrunc64(EmitContext& ctx, Register value); +void EmitFPOrdEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdNotEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdNotEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdNotEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordNotEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordNotEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordNotEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThan16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdLessThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThan16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordLessThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThan16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdGreaterThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThan16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordGreaterThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThanEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdLessThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThanEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordLessThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPIsNan16(EmitContext& ctx, Register value); +void EmitFPIsNan32(EmitContext& ctx, ScalarF32 value); +void EmitFPIsNan64(EmitContext& ctx, Register value); +void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitIAdd64(EmitContext& ctx, Register a, Register b); +void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitISub64(EmitContext& ctx, Register a, Register b); +void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitINeg32(EmitContext& ctx, ScalarS32 value); +void EmitINeg64(EmitContext& ctx, Register value); +void EmitIAbs32(EmitContext& ctx, ScalarS32 value); +void EmitIAbs64(EmitContext& ctx, Register value); +void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); +void EmitShiftLeftLogical64(EmitContext& ctx, Register base, Register shift); +void EmitShiftRightLogical32(EmitContext& ctx, ScalarU32 base, ScalarU32 shift); +void EmitShiftRightLogical64(EmitContext& ctx, Register base, Register shift); +void EmitShiftRightArithmetic32(EmitContext& ctx, ScalarS32 base, ScalarS32 shift); +void EmitShiftRightArithmetic64(EmitContext& ctx, Register base, Register shift); +void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitBitFieldInsert(EmitContext& ctx, ScalarS32 base, ScalarS32 insert, ScalarS32 offset, + ScalarS32 count); +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset, + ScalarS32 count); +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, + ScalarU32 count); +void EmitBitReverse32(EmitContext& ctx, ScalarS32 value); +void EmitBitCount32(EmitContext& ctx, ScalarS32 value); +void EmitBitwiseNot32(EmitContext& ctx, ScalarS32 value); +void EmitFindSMsb32(EmitContext& ctx, ScalarS32 value); +void EmitFindUMsb32(EmitContext& ctx, ScalarU32 value); +void EmitSMin32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); +void EmitUMin32(EmitContext& ctx, ScalarU32 a, ScalarU32 b); +void EmitSMax32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); +void EmitUMax32(EmitContext& ctx, ScalarU32 a, ScalarU32 b); +void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max); +void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max); +void EmitSLessThan(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitULessThan(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); +void EmitIEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitSLessThanEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitULessThanEqual(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); +void EmitSGreaterThan(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitUGreaterThan(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); +void EmitINotEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitSGreaterThanEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); +void EmitUGreaterThanEqual(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); +void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicSMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value); +void EmitSharedAtomicUMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicSMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value); +void EmitSharedAtomicUMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicInc32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicDec32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicAnd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicOr32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicXor32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicExchange32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); +void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Register value); void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarS32 value); void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarS32 value); void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarU32 value); void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, std::string_view value); + const IR::Value& offset, ScalarU32 value); void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, std::string_view value); + const IR::Value& offset, Register value); void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + ScalarF32 value); void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value); + Register value); void EmitGlobalAtomicIAdd32(EmitContext& ctx); void EmitGlobalAtomicSMin32(EmitContext& ctx); void EmitGlobalAtomicUMin32(EmitContext& ctx); @@ -489,58 +430,58 @@ void EmitGlobalAtomicMinF16x2(EmitContext& ctx); void EmitGlobalAtomicMinF32x2(EmitContext& ctx); void EmitGlobalAtomicMaxF16x2(EmitContext& ctx); void EmitGlobalAtomicMaxF32x2(EmitContext& ctx); -void EmitLogicalOr(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitLogicalAnd(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitLogicalXor(EmitContext& ctx, std::string_view a, std::string_view b); -void EmitLogicalNot(EmitContext& ctx, std::string_view value); -void EmitConvertS16F16(EmitContext& ctx, std::string_view value); -void EmitConvertS16F32(EmitContext& ctx, std::string_view value); -void EmitConvertS16F64(EmitContext& ctx, std::string_view value); -void EmitConvertS32F16(EmitContext& ctx, std::string_view value); -void EmitConvertS32F32(EmitContext& ctx, std::string_view value); -void EmitConvertS32F64(EmitContext& ctx, std::string_view value); -void EmitConvertS64F16(EmitContext& ctx, std::string_view value); -void EmitConvertS64F32(EmitContext& ctx, std::string_view value); -void EmitConvertS64F64(EmitContext& ctx, std::string_view value); -void EmitConvertU16F16(EmitContext& ctx, std::string_view value); -void EmitConvertU16F32(EmitContext& ctx, std::string_view value); -void EmitConvertU16F64(EmitContext& ctx, std::string_view value); -void EmitConvertU32F16(EmitContext& ctx, std::string_view value); -void EmitConvertU32F32(EmitContext& ctx, std::string_view value); -void EmitConvertU32F64(EmitContext& ctx, std::string_view value); -void EmitConvertU64F16(EmitContext& ctx, std::string_view value); -void EmitConvertU64F32(EmitContext& ctx, std::string_view value); -void EmitConvertU64F64(EmitContext& ctx, std::string_view value); -void EmitConvertU64U32(EmitContext& ctx, std::string_view value); -void EmitConvertU32U64(EmitContext& ctx, std::string_view value); -void EmitConvertF16F32(EmitContext& ctx, std::string_view value); -void EmitConvertF32F16(EmitContext& ctx, std::string_view value); -void EmitConvertF32F64(EmitContext& ctx, std::string_view value); -void EmitConvertF64F32(EmitContext& ctx, std::string_view value); -void EmitConvertF16S8(EmitContext& ctx, std::string_view value); -void EmitConvertF16S16(EmitContext& ctx, std::string_view value); -void EmitConvertF16S32(EmitContext& ctx, std::string_view value); -void EmitConvertF16S64(EmitContext& ctx, std::string_view value); -void EmitConvertF16U8(EmitContext& ctx, std::string_view value); -void EmitConvertF16U16(EmitContext& ctx, std::string_view value); -void EmitConvertF16U32(EmitContext& ctx, std::string_view value); -void EmitConvertF16U64(EmitContext& ctx, std::string_view value); -void EmitConvertF32S8(EmitContext& ctx, std::string_view value); -void EmitConvertF32S16(EmitContext& ctx, std::string_view value); -void EmitConvertF32S32(EmitContext& ctx, std::string_view value); -void EmitConvertF32S64(EmitContext& ctx, std::string_view value); -void EmitConvertF32U8(EmitContext& ctx, std::string_view value); -void EmitConvertF32U16(EmitContext& ctx, std::string_view value); -void EmitConvertF32U32(EmitContext& ctx, std::string_view value); -void EmitConvertF32U64(EmitContext& ctx, std::string_view value); -void EmitConvertF64S8(EmitContext& ctx, std::string_view value); -void EmitConvertF64S16(EmitContext& ctx, std::string_view value); -void EmitConvertF64S32(EmitContext& ctx, std::string_view value); -void EmitConvertF64S64(EmitContext& ctx, std::string_view value); -void EmitConvertF64U8(EmitContext& ctx, std::string_view value); -void EmitConvertF64U16(EmitContext& ctx, std::string_view value); -void EmitConvertF64U32(EmitContext& ctx, std::string_view value); -void EmitConvertF64U64(EmitContext& ctx, std::string_view value); +void EmitLogicalOr(EmitContext& ctx, ScalarS32 a, ScalarS32 b); +void EmitLogicalAnd(EmitContext& ctx, ScalarS32 a, ScalarS32 b); +void EmitLogicalXor(EmitContext& ctx, ScalarS32 a, ScalarS32 b); +void EmitLogicalNot(EmitContext& ctx, ScalarS32 value); +void EmitConvertS16F16(EmitContext& ctx, Register value); +void EmitConvertS16F32(EmitContext& ctx, Register value); +void EmitConvertS16F64(EmitContext& ctx, Register value); +void EmitConvertS32F16(EmitContext& ctx, Register value); +void EmitConvertS32F32(EmitContext& ctx, Register value); +void EmitConvertS32F64(EmitContext& ctx, Register value); +void EmitConvertS64F16(EmitContext& ctx, Register value); +void EmitConvertS64F32(EmitContext& ctx, Register value); +void EmitConvertS64F64(EmitContext& ctx, Register value); +void EmitConvertU16F16(EmitContext& ctx, Register value); +void EmitConvertU16F32(EmitContext& ctx, Register value); +void EmitConvertU16F64(EmitContext& ctx, Register value); +void EmitConvertU32F16(EmitContext& ctx, Register value); +void EmitConvertU32F32(EmitContext& ctx, Register value); +void EmitConvertU32F64(EmitContext& ctx, Register value); +void EmitConvertU64F16(EmitContext& ctx, Register value); +void EmitConvertU64F32(EmitContext& ctx, Register value); +void EmitConvertU64F64(EmitContext& ctx, Register value); +void EmitConvertU64U32(EmitContext& ctx, Register value); +void EmitConvertU32U64(EmitContext& ctx, Register value); +void EmitConvertF16F32(EmitContext& ctx, Register value); +void EmitConvertF32F16(EmitContext& ctx, Register value); +void EmitConvertF32F64(EmitContext& ctx, Register value); +void EmitConvertF64F32(EmitContext& ctx, Register value); +void EmitConvertF16S8(EmitContext& ctx, Register value); +void EmitConvertF16S16(EmitContext& ctx, Register value); +void EmitConvertF16S32(EmitContext& ctx, Register value); +void EmitConvertF16S64(EmitContext& ctx, Register value); +void EmitConvertF16U8(EmitContext& ctx, Register value); +void EmitConvertF16U16(EmitContext& ctx, Register value); +void EmitConvertF16U32(EmitContext& ctx, Register value); +void EmitConvertF16U64(EmitContext& ctx, Register value); +void EmitConvertF32S8(EmitContext& ctx, Register value); +void EmitConvertF32S16(EmitContext& ctx, Register value); +void EmitConvertF32S32(EmitContext& ctx, Register value); +void EmitConvertF32S64(EmitContext& ctx, Register value); +void EmitConvertF32U8(EmitContext& ctx, Register value); +void EmitConvertF32U16(EmitContext& ctx, Register value); +void EmitConvertF32U32(EmitContext& ctx, Register value); +void EmitConvertF32U64(EmitContext& ctx, Register value); +void EmitConvertF64S8(EmitContext& ctx, Register value); +void EmitConvertF64S16(EmitContext& ctx, Register value); +void EmitConvertF64S32(EmitContext& ctx, Register value); +void EmitConvertF64S64(EmitContext& ctx, Register value); +void EmitConvertF64U8(EmitContext& ctx, Register value); +void EmitConvertF64U16(EmitContext& ctx, Register value); +void EmitConvertF64U32(EmitContext& ctx, Register value); +void EmitConvertF64U64(EmitContext& ctx, Register value); void EmitBindlessImageSampleImplicitLod(EmitContext&); void EmitBindlessImageSampleExplicitLod(EmitContext&); void EmitBindlessImageSampleDrefImplicitLod(EmitContext&); @@ -566,36 +507,29 @@ void EmitBoundImageGradient(EmitContext&); void EmitBoundImageRead(EmitContext&); void EmitBoundImageWrite(EmitContext&); void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view bias_lc, - const IR::Value& offset); + Register coords, Register bias_lc, const IR::Value& offset); void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view lod_lc, - const IR::Value& offset); + Register coords, Register lod_lc, const IR::Value& offset); void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view dref, - std::string_view bias_lc, const IR::Value& offset); + Register coords, Register dref, Register bias_lc, + const IR::Value& offset); void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view dref, - std::string_view lod_lc, const IR::Value& offset); -void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, const IR::Value& offset, const IR::Value& offset2); -void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, const IR::Value& offset, const IR::Value& offset2, - std::string_view dref); -void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view offset, std::string_view lod, - std::string_view ms); + Register coords, Register dref, Register lod_lc, + const IR::Value& offset); +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + const IR::Value& offset, const IR::Value& offset2); +void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + const IR::Value& offset, const IR::Value& offset2, Register dref); +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register offset, Register lod, Register ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view lod); -void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords); -void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view derivates, std::string_view offset, - std::string_view lod_clamp); -void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords); -void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view color); + Register lod); +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords); +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register derivates, Register offset, Register lod_clamp); +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords); +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register color); void EmitBindlessImageAtomicIAdd32(EmitContext&); void EmitBindlessImageAtomicSMin32(EmitContext&); void EmitBindlessImageAtomicUMin32(EmitContext&); @@ -619,53 +553,49 @@ void EmitBoundImageAtomicOr32(EmitContext&); void EmitBoundImageAtomicXor32(EmitContext&); void EmitBoundImageAtomicExchange32(EmitContext&); void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarU32 value); void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarS32 value); void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarU32 value); void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarS32 value); void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarU32 value); +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value); +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value); +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value); +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value); +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value); void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value); + Register coords, ScalarU32 value); void EmitLaneId(EmitContext& ctx); -void EmitVoteAll(EmitContext& ctx, std::string_view pred); -void EmitVoteAny(EmitContext& ctx, std::string_view pred); -void EmitVoteEqual(EmitContext& ctx, std::string_view pred); -void EmitSubgroupBallot(EmitContext& ctx, std::string_view pred); +void EmitVoteAll(EmitContext& ctx, ScalarS32 pred); +void EmitVoteAny(EmitContext& ctx, ScalarS32 pred); +void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred); +void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred); void EmitSubgroupEqMask(EmitContext& ctx); void EmitSubgroupLtMask(EmitContext& ctx); void EmitSubgroupLeMask(EmitContext& ctx); void EmitSubgroupGtMask(EmitContext& ctx); void EmitSubgroupGeMask(EmitContext& ctx); -void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask); -void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, - std::string_view clamp, std::string_view segmentation_mask); -void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask); -void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask); -void EmitFSwizzleAdd(EmitContext& ctx, std::string_view op_a, std::string_view op_b, - std::string_view swizzle); -void EmitDPdxFine(EmitContext& ctx, std::string_view op_a); -void EmitDPdyFine(EmitContext& ctx, std::string_view op_a); -void EmitDPdxCoarse(EmitContext& ctx, std::string_view op_a); -void EmitDPdyCoarse(EmitContext& ctx, std::string_view op_a); +void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask); +void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask); +void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask); +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask); +void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); +void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); +void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); +void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a); +void EmitDPdyCoarse(EmitContext& ctx, ScalarF32 op_a); } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 579806c38..7b88d6f02 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -2,239 +2,209 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include - #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { -void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("ADD.U {},{},{};", inst, a, b); +void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("ADD.S {}.x,{},{};", inst, a, b); } -void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, + [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("SUB.U {},{},{};", inst, a, b); +void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("SUB.S {}.x,{},{};", inst, a, b); } -void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, + [[maybe_unused]] Register b) { throw NotImplementedException("GLASM instruction"); } -void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - throw NotImplementedException("GLASM instruction"); +void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("MUL.S {}.x,{},{};", inst, a, b); } -void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitShiftLeftLogical32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) { + ctx.Add("SHL.U {}.x,{},{};", inst, base, shift); } -void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { +void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, + [[maybe_unused]] Register shift) { throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { +void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 base, + [[maybe_unused]] ScalarU32 shift) { throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { +void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, + [[maybe_unused]] Register shift) { throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { +void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 base, + [[maybe_unused]] ScalarS32 shift) { throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view base, - [[maybe_unused]] std::string_view shift) { +void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, + [[maybe_unused]] Register shift) { throw NotImplementedException("GLASM instruction"); } -void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("AND {},{},{};", inst, a, b); +void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("AND.S {}.x,{},{};", inst, a, b); } -void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("OR {},{},{};", inst, a, b); +void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("OR.S {}.x,{},{};", inst, a, b); } -void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { - ctx.Add("XOR {},{},{};", inst, a, b); +void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("XOR.S {}.x,{},{};", inst, a, b); } -void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view insert, std::string_view offset, std::string_view count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFI.U {},RC,{},{};", inst, insert, base); +void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 base, + [[maybe_unused]] ScalarS32 insert, [[maybe_unused]] ScalarS32 offset, + [[maybe_unused]] ScalarS32 count) { + throw NotImplementedException("GLASM instruction"); } -void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view offset, std::string_view count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFE.S {},RC,{};", inst, base); +void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] ScalarS32 base, [[maybe_unused]] ScalarS32 offset, + [[maybe_unused]] ScalarS32 count) { + throw NotImplementedException("GLASM instruction"); } -void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base, - std::string_view offset, std::string_view count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFE.U {},RC,{};", inst, base); +void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] ScalarU32 base, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarU32 count) { + throw NotImplementedException("GLASM instruction"); } -void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { - ctx.Add("BFR {},{};", inst, value); +void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); } -void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { - ctx.Add("NOT {},{};", inst, value); +void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); } -void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value) { +void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 a, + [[maybe_unused]] ScalarS32 b) { throw NotImplementedException("GLASM instruction"); } -void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 a, + [[maybe_unused]] ScalarU32 b) { throw NotImplementedException("GLASM instruction"); } -void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 a, + [[maybe_unused]] ScalarS32 b) { throw NotImplementedException("GLASM instruction"); } -void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) { +void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 a, + [[maybe_unused]] ScalarU32 b) { throw NotImplementedException("GLASM instruction"); } void EmitSClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value, [[maybe_unused]] std::string_view min, - [[maybe_unused]] std::string_view max) { + [[maybe_unused]] ScalarS32 value, [[maybe_unused]] ScalarS32 min, + [[maybe_unused]] ScalarS32 max) { throw NotImplementedException("GLASM instruction"); } void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view value, [[maybe_unused]] std::string_view min, - [[maybe_unused]] std::string_view max) { + [[maybe_unused]] ScalarU32 value, [[maybe_unused]] ScalarU32 min, + [[maybe_unused]] ScalarU32 max) { throw NotImplementedException("GLASM instruction"); } -void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - ctx.Add("SLT.S {},{},{};", inst, lhs, rhs); +void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - ctx.Add("SLT.U {},{},{};", inst, lhs, rhs); +void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, + [[maybe_unused]] ScalarU32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - ctx.Add("SEQ {},{},{};", inst, lhs, rhs); +void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SLE.S {},{},{};", inst, lhs, rhs); +void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SLE.U {},{},{};", inst, lhs, rhs); +void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, + [[maybe_unused]] ScalarU32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SGT.S {},{},{};", inst, lhs, rhs); +void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SGT.U {},{},{};", inst, lhs, rhs); +void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, + [[maybe_unused]] ScalarU32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, [[maybe_unused]] std::string_view rhs) { - ctx.Add("SNE.U {},{},{};", inst, lhs, rhs); +void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SGE.S {},{},{};", inst, lhs, rhs); +void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, + [[maybe_unused]] ScalarS32 rhs) { + throw NotImplementedException("GLASM instruction"); } -void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] std::string_view lhs, - [[maybe_unused]] std::string_view rhs) { - ctx.Add("SGE.U {},{},{};", inst, lhs, rhs); +void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, + [[maybe_unused]] ScalarU32 rhs) { + throw NotImplementedException("GLASM instruction"); } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 9e38a1bdf..8ef0f7c17 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -11,7 +11,7 @@ namespace Shader::Backend::GLASM { namespace { -void StorageOp(EmitContext& ctx, const IR::Value& binding, std::string_view offset, +void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, std::string_view then_expr, std::string_view else_expr = {}) { // Operate on bindless SSBO, call the expression with bounds checking // address = c[binding].xy @@ -23,20 +23,21 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, std::string_view offs "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length sb_binding, offset, offset, sb_binding); if (else_expr.empty()) { - ctx.Add("{}", then_expr); + ctx.Add("IF NE.x;{}ENDIF;", then_expr); } else { ctx.Add("IF NE.x;{}ELSE;{}ENDIF;", then_expr, else_expr); } } -void Store(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value, std::string_view size) { +template +void Store(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value, + std::string_view size) { StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, value)); } -void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, std::string_view offset, +void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, std::string_view size) { - const std::string ret{ctx.reg_alloc.Define(inst)}; + const Register ret{ctx.reg_alloc.Define(inst)}; StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, ret), fmt::format("MOV.U {},{{0,0,0,0}};", ret)); } @@ -58,18 +59,15 @@ void EmitLoadGlobalS16([[maybe_unused]] EmitContext& ctx) { throw NotImplementedException("GLASM instruction"); } -void EmitLoadGlobal32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view address) { +void EmitLoadGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { throw NotImplementedException("GLASM instruction"); } -void EmitLoadGlobal64([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view address) { +void EmitLoadGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { throw NotImplementedException("GLASM instruction"); } -void EmitLoadGlobal128([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view address) { +void EmitLoadGlobal128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address) { throw NotImplementedException("GLASM instruction"); } @@ -89,89 +87,88 @@ void EmitWriteGlobalS16([[maybe_unused]] EmitContext& ctx) { throw NotImplementedException("GLASM instruction"); } -void EmitWriteGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view address, - [[maybe_unused]] std::string_view value) { +void EmitWriteGlobal32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, + [[maybe_unused]] ScalarU32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitWriteGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view address, - [[maybe_unused]] std::string_view value) { +void EmitWriteGlobal64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, + [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitWriteGlobal128([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] std::string_view address, - [[maybe_unused]] std::string_view value) { +void EmitWriteGlobal128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register address, + [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "U8"); } void EmitLoadStorageS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "S8"); } void EmitLoadStorageU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "U16"); } void EmitLoadStorageS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "S16"); } void EmitLoadStorage32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "U32"); } void EmitLoadStorage64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "U32X2"); } void EmitLoadStorage128(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - std::string_view offset) { + ScalarU32 offset) { Load(ctx, inst, binding, offset, "U32X4"); } -void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value) { Store(ctx, binding, offset, value, "U8"); } -void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarS32 value) { Store(ctx, binding, offset, value, "S8"); } -void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value) { Store(ctx, binding, offset, value, "U16"); } -void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarS32 value) { Store(ctx, binding, offset, value, "S16"); } -void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + ScalarU32 value) { Store(ctx, binding, offset, value, "U32"); } -void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + Register value) { Store(ctx, binding, offset, value, "U32X2"); } -void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, std::string_view offset, - std::string_view value) { +void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + Register value) { Store(ctx, binding, offset, value, "U32X4"); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 32eb87837..08de3f92f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -25,21 +25,19 @@ void EmitVoid(EmitContext& ctx) { NotImplemented(); } -void EmitBranch(EmitContext& ctx, std::string_view label) { +void EmitBranch(EmitContext& ctx) { NotImplemented(); } -void EmitBranchConditional(EmitContext& ctx, std::string_view condition, - std::string_view true_label, std::string_view false_label) { +void EmitBranchConditional(EmitContext& ctx) { NotImplemented(); } -void EmitLoopMerge(EmitContext& ctx, std::string_view merge_label, - std::string_view continue_label) { +void EmitLoopMerge(EmitContext& ctx) { NotImplemented(); } -void EmitSelectionMerge(EmitContext& ctx, std::string_view merge_label) { +void EmitSelectionMerge(EmitContext& ctx) { NotImplemented(); } @@ -55,7 +53,7 @@ void EmitUnreachable(EmitContext& ctx) { NotImplemented(); } -void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label) { +void EmitDemoteToHelperInvocation(EmitContext& ctx) { NotImplemented(); } @@ -155,8 +153,8 @@ void EmitWorkgroupId(EmitContext& ctx) { NotImplemented(); } -void EmitLocalInvocationId(EmitContext& ctx) { - NotImplemented(); +void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {},invocation.localid;", inst); } void EmitInvocationId(EmitContext& ctx) { @@ -175,11 +173,11 @@ void EmitYDirection(EmitContext& ctx) { NotImplemented(); } -void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset) { +void EmitLoadLocal(EmitContext& ctx, ScalarU32 word_offset) { NotImplemented(); } -void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value) { +void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value) { NotImplemented(); } @@ -203,245 +201,127 @@ void EmitUndefU64(EmitContext& ctx) { NotImplemented(); } -void EmitLoadSharedU8(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedS8(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedU16(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedS16(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedU32(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedU64(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitLoadSharedU128(EmitContext& ctx, std::string_view offset) { - NotImplemented(); -} - -void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value) { - NotImplemented(); -} - -void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value) { - NotImplemented(); -} - -void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value) { - NotImplemented(); -} - -void EmitWriteSharedU64(EmitContext& ctx, std::string_view offset, std::string_view value) { - NotImplemented(); -} - -void EmitWriteSharedU128(EmitContext& ctx, std::string_view offset, std::string_view value) { - NotImplemented(); -} - -void EmitCompositeConstructU32x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { - NotImplemented(); -} - -void EmitCompositeConstructU32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3) { - NotImplemented(); -} - -void EmitCompositeConstructU32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4) { - NotImplemented(); -} - -void EmitCompositeExtractU32x2(EmitContext& ctx, std::string_view composite, u32 index) { - NotImplemented(); -} - -void EmitCompositeExtractU32x3(EmitContext& ctx, std::string_view composite, u32 index) { - NotImplemented(); -} - -void EmitCompositeExtractU32x4(EmitContext& ctx, std::string_view composite, u32 index) { - NotImplemented(); -} - -void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { - NotImplemented(); -} - -void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { - NotImplemented(); -} - -void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { - NotImplemented(); -} - -void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { - NotImplemented(); -} - -void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3) { - NotImplemented(); -} - -void EmitCompositeConstructF16x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4) { - NotImplemented(); -} - -void EmitCompositeExtractF16x2(EmitContext& ctx, std::string_view composite, u32 index) { - NotImplemented(); -} - -void EmitCompositeExtractF16x3(EmitContext& ctx, std::string_view composite, u32 index) { +void EmitLoadSharedU8(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeExtractF16x4(EmitContext& ctx, std::string_view composite, u32 index) { +void EmitLoadSharedS8(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeInsertF16x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitLoadSharedU16(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeInsertF16x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitLoadSharedS16(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeInsertF16x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitLoadSharedU32(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeConstructF32x2(EmitContext& ctx, std::string_view e1, std::string_view e2) { +void EmitLoadSharedU64(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeConstructF32x3(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3) { +void EmitLoadSharedU128(EmitContext& ctx, ScalarU32 offset) { NotImplemented(); } -void EmitCompositeConstructF32x4(EmitContext& ctx, std::string_view e1, std::string_view e2, - std::string_view e3, std::string_view e4) { +void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { NotImplemented(); } -void EmitCompositeExtractF32x2(EmitContext& ctx, std::string_view composite, u32 index) { +void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { NotImplemented(); } -void EmitCompositeExtractF32x3(EmitContext& ctx, std::string_view composite, u32 index) { +void EmitWriteSharedU32(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { NotImplemented(); } -void EmitCompositeExtractF32x4(EmitContext& ctx, std::string_view composite, u32 index) { +void EmitWriteSharedU64(EmitContext& ctx, ScalarU32 offset, Register value) { NotImplemented(); } -void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value) { NotImplemented(); } -void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitSelectU1(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { NotImplemented(); } -void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { NotImplemented(); } -void EmitCompositeConstructF64x2(EmitContext& ctx) { +void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { NotImplemented(); } -void EmitCompositeConstructF64x3(EmitContext& ctx) { +void EmitSelectU32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { NotImplemented(); } -void EmitCompositeConstructF64x4(EmitContext& ctx) { +void EmitSelectU64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitCompositeExtractF64x2(EmitContext& ctx) { +void EmitSelectF16(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitCompositeExtractF64x3(EmitContext& ctx) { +void EmitSelectF32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { NotImplemented(); } -void EmitCompositeExtractF64x4(EmitContext& ctx) { +void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitSelectF16(EmitContext& ctx, Register cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitSelectF32(EmitContext& ctx, Register cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object, - u32 index) { +void EmitSelectF64(EmitContext& ctx, Register cond, Register true_value, Register false_value) { NotImplemented(); } -void EmitPackUint2x32(EmitContext& ctx, std::string_view value) { +void EmitPackUint2x32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitUnpackUint2x32(EmitContext& ctx, std::string_view value) { +void EmitUnpackUint2x32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitPackFloat2x16(EmitContext& ctx, std::string_view value) { +void EmitPackFloat2x16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitUnpackFloat2x16(EmitContext& ctx, std::string_view value) { +void EmitUnpackFloat2x16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitPackHalf2x16(EmitContext& ctx, std::string_view value) { +void EmitPackHalf2x16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitUnpackHalf2x16(EmitContext& ctx, std::string_view value) { +void EmitUnpackHalf2x16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitPackDouble2x32(EmitContext& ctx, std::string_view value) { +void EmitPackDouble2x32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitUnpackDouble2x32(EmitContext& ctx, std::string_view value) { +void EmitUnpackDouble2x32(EmitContext& ctx, Register value) { NotImplemented(); } @@ -469,210 +349,198 @@ void EmitGetInBoundsFromOp(EmitContext& ctx) { NotImplemented(); } -void EmitFPIsNan16(EmitContext& ctx, std::string_view value) { +void EmitFPIsNan16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitFPIsNan32(EmitContext& ctx, std::string_view value) { +void EmitFPIsNan32(EmitContext& ctx, ScalarF32 value) { NotImplemented(); } -void EmitFPIsNan64(EmitContext& ctx, std::string_view value) { +void EmitFPIsNan64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicSMin32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicSMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value) { NotImplemented(); } -void EmitSharedAtomicUMin32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicUMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicSMax32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicSMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value) { NotImplemented(); } -void EmitSharedAtomicUMax32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicUMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicInc32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicInc32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicDec32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicDec32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicAnd32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicAnd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicOr32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicOr32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicXor32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicXor32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicExchange32(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicExchange32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -void EmitSharedAtomicExchange64(EmitContext& ctx, std::string_view pointer_offset, - std::string_view value) { +void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Register value) { NotImplemented(); } void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarS32 value) { NotImplemented(); } void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarS32 value) { NotImplemented(); } void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, std::string_view value) { + const IR::Value& offset, ScalarU32 value) { NotImplemented(); } void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, std::string_view value) { + const IR::Value& offset, Register value) { NotImplemented(); } void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + ScalarF32 value) { NotImplemented(); } void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - std::string_view value) { + Register value) { NotImplemented(); } @@ -792,211 +660,211 @@ void EmitGlobalAtomicMaxF32x2(EmitContext& ctx) { NotImplemented(); } -void EmitLogicalOr(EmitContext& ctx, std::string_view a, std::string_view b) { +void EmitLogicalOr(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { NotImplemented(); } -void EmitLogicalAnd(EmitContext& ctx, std::string_view a, std::string_view b) { +void EmitLogicalAnd(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { NotImplemented(); } -void EmitLogicalXor(EmitContext& ctx, std::string_view a, std::string_view b) { +void EmitLogicalXor(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { NotImplemented(); } -void EmitLogicalNot(EmitContext& ctx, std::string_view value) { +void EmitLogicalNot(EmitContext& ctx, ScalarS32 value) { NotImplemented(); } -void EmitConvertS16F16(EmitContext& ctx, std::string_view value) { +void EmitConvertS16F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS16F32(EmitContext& ctx, std::string_view value) { +void EmitConvertS16F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS16F64(EmitContext& ctx, std::string_view value) { +void EmitConvertS16F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS32F16(EmitContext& ctx, std::string_view value) { +void EmitConvertS32F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS32F32(EmitContext& ctx, std::string_view value) { +void EmitConvertS32F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS32F64(EmitContext& ctx, std::string_view value) { +void EmitConvertS32F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS64F16(EmitContext& ctx, std::string_view value) { +void EmitConvertS64F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS64F32(EmitContext& ctx, std::string_view value) { +void EmitConvertS64F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertS64F64(EmitContext& ctx, std::string_view value) { +void EmitConvertS64F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU16F16(EmitContext& ctx, std::string_view value) { +void EmitConvertU16F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU16F32(EmitContext& ctx, std::string_view value) { +void EmitConvertU16F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU16F64(EmitContext& ctx, std::string_view value) { +void EmitConvertU16F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU32F16(EmitContext& ctx, std::string_view value) { +void EmitConvertU32F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU32F32(EmitContext& ctx, std::string_view value) { +void EmitConvertU32F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU32F64(EmitContext& ctx, std::string_view value) { +void EmitConvertU32F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU64F16(EmitContext& ctx, std::string_view value) { +void EmitConvertU64F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU64F32(EmitContext& ctx, std::string_view value) { +void EmitConvertU64F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU64F64(EmitContext& ctx, std::string_view value) { +void EmitConvertU64F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU64U32(EmitContext& ctx, std::string_view value) { +void EmitConvertU64U32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertU32U64(EmitContext& ctx, std::string_view value) { +void EmitConvertU32U64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16F32(EmitContext& ctx, std::string_view value) { +void EmitConvertF16F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32F16(EmitContext& ctx, std::string_view value) { +void EmitConvertF32F16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32F64(EmitContext& ctx, std::string_view value) { +void EmitConvertF32F64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64F32(EmitContext& ctx, std::string_view value) { +void EmitConvertF64F32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16S8(EmitContext& ctx, std::string_view value) { +void EmitConvertF16S8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16S16(EmitContext& ctx, std::string_view value) { +void EmitConvertF16S16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16S32(EmitContext& ctx, std::string_view value) { +void EmitConvertF16S32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16S64(EmitContext& ctx, std::string_view value) { +void EmitConvertF16S64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16U8(EmitContext& ctx, std::string_view value) { +void EmitConvertF16U8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16U16(EmitContext& ctx, std::string_view value) { +void EmitConvertF16U16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16U32(EmitContext& ctx, std::string_view value) { +void EmitConvertF16U32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF16U64(EmitContext& ctx, std::string_view value) { +void EmitConvertF16U64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32S8(EmitContext& ctx, std::string_view value) { +void EmitConvertF32S8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32S16(EmitContext& ctx, std::string_view value) { +void EmitConvertF32S16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32S32(EmitContext& ctx, std::string_view value) { +void EmitConvertF32S32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32S64(EmitContext& ctx, std::string_view value) { +void EmitConvertF32S64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32U8(EmitContext& ctx, std::string_view value) { +void EmitConvertF32U8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32U16(EmitContext& ctx, std::string_view value) { +void EmitConvertF32U16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32U32(EmitContext& ctx, std::string_view value) { +void EmitConvertF32U32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF32U64(EmitContext& ctx, std::string_view value) { +void EmitConvertF32U64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64S8(EmitContext& ctx, std::string_view value) { +void EmitConvertF64S8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64S16(EmitContext& ctx, std::string_view value) { +void EmitConvertF64S16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64S32(EmitContext& ctx, std::string_view value) { +void EmitConvertF64S32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64S64(EmitContext& ctx, std::string_view value) { +void EmitConvertF64S64(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64U8(EmitContext& ctx, std::string_view value) { +void EmitConvertF64U8(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64U16(EmitContext& ctx, std::string_view value) { +void EmitConvertF64U16(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64U32(EmitContext& ctx, std::string_view value) { +void EmitConvertF64U32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitConvertF64U64(EmitContext& ctx, std::string_view value) { +void EmitConvertF64U64(EmitContext& ctx, Register value) { NotImplemented(); } @@ -1097,69 +965,62 @@ void EmitBoundImageWrite(EmitContext&) { } void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view bias_lc, - const IR::Value& offset) { + Register coords, Register bias_lc, const IR::Value& offset) { NotImplemented(); } void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view lod_lc, - const IR::Value& offset) { + Register coords, Register lod_lc, const IR::Value& offset) { NotImplemented(); } void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view dref, - std::string_view bias_lc, const IR::Value& offset) { + Register coords, Register dref, Register bias_lc, + const IR::Value& offset) { NotImplemented(); } void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view dref, - std::string_view lod_lc, const IR::Value& offset) { + Register coords, Register dref, Register lod_lc, + const IR::Value& offset) { NotImplemented(); } -void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, const IR::Value& offset, const IR::Value& offset2) { +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + const IR::Value& offset, const IR::Value& offset2) { NotImplemented(); } -void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, const IR::Value& offset, const IR::Value& offset2, - std::string_view dref) { +void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + const IR::Value& offset, const IR::Value& offset2, Register dref) { NotImplemented(); } -void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view offset, std::string_view lod, - std::string_view ms) { +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register offset, Register lod, Register ms) { NotImplemented(); } void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view lod) { + Register lod) { NotImplemented(); } -void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords) { +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords) { NotImplemented(); } -void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view derivates, std::string_view offset, - std::string_view lod_clamp) { +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register derivates, Register offset, Register lod_clamp) { NotImplemented(); } -void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords) { +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords) { NotImplemented(); } -void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view color) { +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + Register color) { NotImplemented(); } @@ -1252,57 +1113,57 @@ void EmitBoundImageAtomicExchange32(EmitContext&) { } void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarU32 value) { NotImplemented(); } void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarS32 value) { NotImplemented(); } void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarU32 value) { NotImplemented(); } void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarS32 value) { NotImplemented(); } void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarU32 value) { NotImplemented(); } -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value) { NotImplemented(); } -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value) { NotImplemented(); } -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value) { NotImplemented(); } -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value) { NotImplemented(); } -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, + ScalarU32 value) { NotImplemented(); } void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view coords, std::string_view value) { + Register coords, ScalarU32 value) { NotImplemented(); } @@ -1310,19 +1171,19 @@ void EmitLaneId(EmitContext& ctx) { NotImplemented(); } -void EmitVoteAll(EmitContext& ctx, std::string_view pred) { +void EmitVoteAll(EmitContext& ctx, ScalarS32 pred) { NotImplemented(); } -void EmitVoteAny(EmitContext& ctx, std::string_view pred) { +void EmitVoteAny(EmitContext& ctx, ScalarS32 pred) { NotImplemented(); } -void EmitVoteEqual(EmitContext& ctx, std::string_view pred) { +void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred) { NotImplemented(); } -void EmitSubgroupBallot(EmitContext& ctx, std::string_view pred) { +void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred) { NotImplemented(); } @@ -1346,47 +1207,43 @@ void EmitSubgroupGeMask(EmitContext& ctx) { NotImplemented(); } -void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { +void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask) { NotImplemented(); } -void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, - std::string_view clamp, std::string_view segmentation_mask) { +void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask) { NotImplemented(); } -void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { +void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask) { NotImplemented(); } -void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + ScalarU32 clamp, ScalarU32 segmentation_mask) { NotImplemented(); } -void EmitFSwizzleAdd(EmitContext& ctx, std::string_view op_a, std::string_view op_b, - std::string_view swizzle) { +void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle) { NotImplemented(); } -void EmitDPdxFine(EmitContext& ctx, std::string_view op_a) { +void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a) { NotImplemented(); } -void EmitDPdyFine(EmitContext& ctx, std::string_view op_a) { +void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a) { NotImplemented(); } -void EmitDPdxCoarse(EmitContext& ctx, std::string_view op_a) { +void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a) { NotImplemented(); } -void EmitDPdyCoarse(EmitContext& ctx, std::string_view op_a) { +void EmitDPdyCoarse(EmitContext& ctx, ScalarF32 op_a) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index 16f6c33f3..e69de29bb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -1,46 +0,0 @@ -// Copyright 2021 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include - -#include "shader_recompiler/backend/glasm/emit_context.h" -#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" -#include "shader_recompiler/frontend/ir/value.h" - -namespace Shader::Backend::GLASM { - -void EmitSelectU1(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitSelectU8(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitSelectU16(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, - std::string_view true_value, std::string_view false_value) { - ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); -} - -void EmitSelectU64(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitSelectF16(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, - std::string_view true_value, std::string_view false_value) { - ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); -} - -void EmitSelectF64(EmitContext&, std::string_view, std::string_view, std::string_view) { - throw NotImplementedException("GLASM instruction"); -} -} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index e198dd522..030b48d83 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -12,53 +12,61 @@ #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { -namespace { -std::string Representation(Id id) { - if (id.is_condition_code != 0) { - throw NotImplementedException("Condition code"); - } - if (id.is_spill != 0) { - throw NotImplementedException("Spilling"); - } - const u32 index{static_cast(id.index)}; - return fmt::format("R{}.x", index); + +Register RegAlloc::Define(IR::Inst& inst) { + const Id id{Alloc()}; + inst.SetDefinition(id); + Register ret; + ret.type = Type::Register; + ret.id = id; + return ret; } -std::string ImmValue(const IR::Value& value) { +Value RegAlloc::Consume(const IR::Value& value) { + if (!value.IsImmediate()) { + return Consume(*value.InstRecursive()); + } + Value ret; switch (value.Type()) { case IR::Type::U1: - return value.U1() ? "-1" : "0"; + ret.type = Type::U32; + ret.imm_u32 = value.U1() ? 0xffffffff : 0; + break; case IR::Type::U32: - return fmt::format("{}", value.U32()); + ret.type = Type::U32; + ret.imm_u32 = value.U32(); + break; case IR::Type::F32: - return fmt::format("{}", value.F32()); + ret.type = Type::F32; + ret.imm_f32 = value.F32(); + break; default: throw NotImplementedException("Immediate type {}", value.Type()); } + return ret; } -} // Anonymous namespace -std::string RegAlloc::Define(IR::Inst& inst) { - const Id id{Alloc()}; - inst.SetDefinition(id); - return Representation(id); +Register RegAlloc::AllocReg() { + Register ret; + ret.type = Type::Register; + ret.id = Alloc(); + return ret; } -std::string RegAlloc::Consume(const IR::Value& value) { - if (value.IsImmediate()) { - return ImmValue(value); - } else { - return Consume(*value.InstRecursive()); - } +void RegAlloc::FreeReg(Register reg) { + Free(reg.id); } -std::string RegAlloc::Consume(IR::Inst& inst) { +Value RegAlloc::Consume(IR::Inst& inst) { const Id id{inst.Definition()}; inst.DestructiveRemoveUsage(); if (!inst.HasUses()) { Free(id); } - return Representation(inst.Definition()); + Value ret; + ret.type = Type::Register; + ret.id = id; + return ret; } Id RegAlloc::Alloc() { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index f73aa3348..ef0b6697f 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -6,8 +6,12 @@ #include +#include + +#include "common/bit_cast.h" #include "common/bit_field.h" #include "common/common_types.h" +#include "shader_recompiler/exception.h" namespace Shader::IR { class Inst; @@ -18,6 +22,13 @@ namespace Shader::Backend::GLASM { class EmitContext; +enum class Type : u32 { + Register, + U32, + S32, + F32, +}; + struct Id { union { u32 raw; @@ -25,15 +36,62 @@ struct Id { BitField<30, 1, u32> is_spill; BitField<31, 1, u32> is_condition_code; }; + + bool operator==(Id rhs) const noexcept { + return raw == rhs.raw; + } + bool operator!=(Id rhs) const noexcept { + return !operator==(rhs); + } }; +static_assert(sizeof(Id) == sizeof(u32)); + +struct Value { + Type type; + union { + Id id; + u32 imm_u32; + s32 imm_s32; + f32 imm_f32; + }; + + bool operator==(const Value& rhs) const noexcept { + if (type != rhs.type) { + return false; + } + switch (type) { + case Type::Register: + return id == rhs.id; + case Type::U32: + return imm_u32 == rhs.imm_u32; + case Type::S32: + return imm_s32 == rhs.imm_s32; + case Type::F32: + return Common::BitCast(imm_f32) == Common::BitCast(rhs.imm_f32); + } + return false; + } + bool operator!=(const Value& rhs) const noexcept { + return !operator==(rhs); + } +}; +struct Register : Value {}; +struct ScalarRegister : Value {}; +struct ScalarU32 : Value {}; +struct ScalarS32 : Value {}; +struct ScalarF32 : Value {}; class RegAlloc { public: RegAlloc(EmitContext& ctx_) : ctx{ctx_} {} - std::string Define(IR::Inst& inst); + Register Define(IR::Inst& inst); + + Value Consume(const IR::Value& value); + + Register AllocReg(); - std::string Consume(const IR::Value& value); + void FreeReg(Register reg); [[nodiscard]] size_t NumUsedRegisters() const noexcept { return num_used_registers; @@ -43,16 +101,132 @@ private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; - EmitContext& ctx; - - std::string Consume(IR::Inst& inst); + Value Consume(IR::Inst& inst); Id Alloc(); void Free(Id id); + EmitContext& ctx; size_t num_used_registers{}; std::bitset register_use{}; }; +template +auto FormatTo(FormatContext& ctx, Id id) { + if (id.is_condition_code != 0) { + throw NotImplementedException("Condition code emission"); + } + if (id.is_spill != 0) { + throw NotImplementedException("Spill emission"); + } + if constexpr (scalar) { + return fmt::format_to(ctx.out(), "R{}.x", id.index.Value()); + } else { + return fmt::format_to(ctx.out(), "R{}", id.index.Value()); + } +} + } // namespace Shader::Backend::GLASM + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(Shader::Backend::GLASM::Id id, FormatContext& ctx) { + return FormatTo(ctx, id); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::Register& value, FormatContext& ctx) { + if (value.type != Shader::Backend::GLASM::Type::Register) { + throw Shader::InvalidArgument("Register value type is not register"); + } + return FormatTo(ctx, value.id); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::ScalarRegister& value, FormatContext& ctx) { + if (value.type != Shader::Backend::GLASM::Type::Register) { + throw Shader::InvalidArgument("Register value type is not register"); + } + return FormatTo(ctx, value.id); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::ScalarU32& value, FormatContext& ctx) { + switch (value.type) { + case Shader::Backend::GLASM::Type::Register: + return FormatTo(ctx, value.id); + case Shader::Backend::GLASM::Type::U32: + return fmt::format_to(ctx.out(), "{}", value.imm_u32); + case Shader::Backend::GLASM::Type::S32: + return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_s32)); + case Shader::Backend::GLASM::Type::F32: + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + } + throw Shader::InvalidArgument("Invalid value type {}", value.type); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::ScalarS32& value, FormatContext& ctx) { + switch (value.type) { + case Shader::Backend::GLASM::Type::Register: + return FormatTo(ctx, value.id); + case Shader::Backend::GLASM::Type::U32: + return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_u32)); + case Shader::Backend::GLASM::Type::S32: + return fmt::format_to(ctx.out(), "{}", value.imm_s32); + case Shader::Backend::GLASM::Type::F32: + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + } + throw Shader::InvalidArgument("Invalid value type {}", value.type); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::ScalarF32& value, FormatContext& ctx) { + switch (value.type) { + case Shader::Backend::GLASM::Type::Register: + return FormatTo(ctx, value.id); + case Shader::Backend::GLASM::Type::U32: + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u32)); + case Shader::Backend::GLASM::Type::S32: + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_s32)); + case Shader::Backend::GLASM::Type::F32: + return fmt::format_to(ctx.out(), "{}", value.imm_f32); + } + throw Shader::InvalidArgument("Invalid value type {}", value.type); + } +}; -- cgit v1.2.3 From 939dab71202aa28b907e14876a3811dca0ed2348 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 04:01:17 -0300 Subject: glasm: Implement more GLASM composite instructions --- .../backend/glasm/emit_glasm_composite.cpp | 92 +++++++++++----------- .../backend/glasm/emit_glasm_instructions.h | 25 +++--- 2 files changed, 63 insertions(+), 54 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index 063dcaf13..94dc5019d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp @@ -8,60 +8,71 @@ namespace Shader::Backend::GLASM { namespace { -template -void CompositeConstructU32(EmitContext& ctx, IR::Inst& inst, Values&&... elements) { +template +void CompositeConstruct(EmitContext& ctx, IR::Inst& inst, Values&&... elements) { const Register ret{ctx.reg_alloc.Define(inst)}; if (std::ranges::any_of(std::array{elements...}, [](const IR::Value& value) { return value.IsImmediate(); })) { - const std::array values{(elements.IsImmediate() ? elements.U32() : 0)...}; - ctx.Add("MOV.U {},{{{},{},{},{}}};", ret, fmt::to_string(values[0]), + using Type = std::invoke_result_t; + const std::array values{(elements.IsImmediate() ? (elements.*read_imm)() : 0)...}; + ctx.Add("MOV.{} {},{{{},{},{},{}}};", type, ret, fmt::to_string(values[0]), fmt::to_string(values[1]), fmt::to_string(values[2]), fmt::to_string(values[3])); } size_t index{}; for (const IR::Value& element : {elements...}) { if (!element.IsImmediate()) { const ScalarU32 value{ctx.reg_alloc.Consume(element)}; - ctx.Add("MOV.U {}.{},{};", ret, "xyzw"[index], value); + ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], value); } ++index; } } -void CompositeExtractU32(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { +void CompositeExtract(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index, char type) { const Register ret{ctx.reg_alloc.Define(inst)}; if (ret == composite && index == 0) { // No need to do anything here, the source and destination are the same register return; } - ctx.Add("MOV.U {}.x,{}.{};", ret, composite, "xyzw"[index]); + ctx.Add("MOV.{} {}.x,{}.{};", type, ret, composite, "xyzw"[index]); +} + +template +void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object, + u32 index, char type) { + const Register ret{ctx.reg_alloc.Define(inst)}; + if (ret != composite) { + ctx.Add("MOV.{} {},{};", type, ret, composite); + } + ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], object); } } // Anonymous namespace void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, const IR::Value& e2) { - CompositeConstructU32(ctx, inst, e1, e2); + CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2); } void EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, const IR::Value& e2, const IR::Value& e3) { - CompositeConstructU32(ctx, inst, e1, e2, e3); + CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3); } void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) { - CompositeConstructU32(ctx, inst, e1, e2, e3, e4); + CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3, e4); } void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { - CompositeExtractU32(ctx, inst, composite, index); + CompositeExtract(ctx, inst, composite, index, 'U'); } void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { - CompositeExtractU32(ctx, inst, composite, index); + CompositeExtract(ctx, inst, composite, index, 'U'); } void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { - CompositeExtractU32(ctx, inst, composite, index); + CompositeExtract(ctx, inst, composite, index, 'U'); } void EmitCompositeInsertU32x2([[maybe_unused]] EmitContext& ctx, @@ -131,53 +142,46 @@ void EmitCompositeInsertF16x4([[maybe_unused]] EmitContext& ctx, throw NotImplementedException("GLASM instruction"); } -void EmitCompositeConstructF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, - [[maybe_unused]] ScalarF32 e2) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2) { + CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2); } -void EmitCompositeConstructF32x3([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, - [[maybe_unused]] ScalarF32 e2, [[maybe_unused]] ScalarF32 e3) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3) { + CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3); } -void EmitCompositeConstructF32x4([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 e1, - [[maybe_unused]] ScalarF32 e2, [[maybe_unused]] ScalarF32 e3, - [[maybe_unused]] ScalarF32 e4) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) { + CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3, e4); } -void EmitCompositeExtractF32x2([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtract(ctx, inst, composite, index, 'F'); } -void EmitCompositeExtractF32x3([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtract(ctx, inst, composite, index, 'F'); } -void EmitCompositeExtractF32x4([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { + CompositeExtract(ctx, inst, composite, index, 'F'); } -void EmitCompositeInsertF32x2([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, - [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index) { + CompositeInsert(ctx, inst, composite, object, index, 'F'); } -void EmitCompositeInsertF32x3([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, - [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index) { + CompositeInsert(ctx, inst, composite, object, index, 'F'); } -void EmitCompositeInsertF32x4([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] Register composite, - [[maybe_unused]] ScalarF32 object, [[maybe_unused]] u32 index) { - throw NotImplementedException("GLASM instruction"); +void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index) { + CompositeInsert(ctx, inst, composite, object, index, 'F'); } void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 6db76bf46..42de6716a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -158,16 +158,21 @@ void EmitCompositeExtractF16x4(EmitContext& ctx, Register composite, u32 index); void EmitCompositeInsertF16x2(EmitContext& ctx, Register composite, Register object, u32 index); void EmitCompositeInsertF16x3(EmitContext& ctx, Register composite, Register object, u32 index); void EmitCompositeInsertF16x4(EmitContext& ctx, Register composite, Register object, u32 index); -void EmitCompositeConstructF32x2(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2); -void EmitCompositeConstructF32x3(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2, ScalarF32 e3); -void EmitCompositeConstructF32x4(EmitContext& ctx, ScalarF32 e1, ScalarF32 e2, ScalarF32 e3, - ScalarF32 e4); -void EmitCompositeExtractF32x2(EmitContext& ctx, Register composite, u32 index); -void EmitCompositeExtractF32x3(EmitContext& ctx, Register composite, u32 index); -void EmitCompositeExtractF32x4(EmitContext& ctx, Register composite, u32 index); -void EmitCompositeInsertF32x2(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); -void EmitCompositeInsertF32x3(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); -void EmitCompositeInsertF32x4(EmitContext& ctx, Register composite, ScalarF32 object, u32 index); +void EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2); +void EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3); +void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, + const IR::Value& e2, const IR::Value& e3, const IR::Value& e4); +void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index); +void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index); +void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index); +void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, + ScalarF32 object, u32 index); void EmitCompositeConstructF64x2(EmitContext& ctx); void EmitCompositeConstructF64x3(EmitContext& ctx); void EmitCompositeConstructF64x4(EmitContext& ctx); -- cgit v1.2.3 From 6358b0d0c1968e6491d39d36f08055f834e0030f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 04:08:19 -0300 Subject: glasm: Specify namespace when using FormatTo --- src/shader_recompiler/backend/glasm/reg_alloc.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index ef0b6697f..6a238afa9 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -136,7 +136,7 @@ struct fmt::formatter { } template auto format(Shader::Backend::GLASM::Id id, FormatContext& ctx) { - return FormatTo(ctx, id); + return Shader::Backend::GLASM::FormatTo(ctx, id); } }; @@ -150,7 +150,7 @@ struct fmt::formatter { if (value.type != Shader::Backend::GLASM::Type::Register) { throw Shader::InvalidArgument("Register value type is not register"); } - return FormatTo(ctx, value.id); + return Shader::Backend::GLASM::FormatTo(ctx, value.id); } }; @@ -164,7 +164,7 @@ struct fmt::formatter { if (value.type != Shader::Backend::GLASM::Type::Register) { throw Shader::InvalidArgument("Register value type is not register"); } - return FormatTo(ctx, value.id); + return Shader::Backend::GLASM::FormatTo(ctx, value.id); } }; @@ -177,7 +177,7 @@ struct fmt::formatter { auto format(const Shader::Backend::GLASM::ScalarU32& value, FormatContext& ctx) { switch (value.type) { case Shader::Backend::GLASM::Type::Register: - return FormatTo(ctx, value.id); + return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: return fmt::format_to(ctx.out(), "{}", value.imm_u32); case Shader::Backend::GLASM::Type::S32: @@ -198,7 +198,7 @@ struct fmt::formatter { auto format(const Shader::Backend::GLASM::ScalarS32& value, FormatContext& ctx) { switch (value.type) { case Shader::Backend::GLASM::Type::Register: - return FormatTo(ctx, value.id); + return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_u32)); case Shader::Backend::GLASM::Type::S32: @@ -219,7 +219,7 @@ struct fmt::formatter { auto format(const Shader::Backend::GLASM::ScalarF32& value, FormatContext& ctx) { switch (value.type) { case Shader::Backend::GLASM::Type::Register: - return FormatTo(ctx, value.id); + return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u32)); case Shader::Backend::GLASM::Type::S32: -- cgit v1.2.3 From 4de65fbff410d0d42fa34f8ccd3cf6a1ce136797 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 04:09:17 -0300 Subject: glasm: Remove unused functions left from rebase --- .../backend/glasm/emit_glasm_not_implemented.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 08de3f92f..5729b27a7 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -281,18 +281,6 @@ void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Regist NotImplemented(); } -void EmitSelectF16(EmitContext& ctx, Register cond, Register true_value, Register false_value) { - NotImplemented(); -} - -void EmitSelectF32(EmitContext& ctx, Register cond, Register true_value, Register false_value) { - NotImplemented(); -} - -void EmitSelectF64(EmitContext& ctx, Register cond, Register true_value, Register false_value) { - NotImplemented(); -} - void EmitPackUint2x32(EmitContext& ctx, Register value) { NotImplemented(); } -- cgit v1.2.3 From 9f851e3832fb85c20f406eacfadd12a8bb7d982d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 04:18:37 -0300 Subject: glasm: Implement GLASM fp16 packing and move bitwise insns --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 40 ------------ .../glasm/emit_glasm_bitwise_conversion.cpp | 75 ++++++++++++++++++++++ .../backend/glasm/emit_glasm_instructions.h | 4 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 24 ------- 4 files changed, 77 insertions(+), 66 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8981cf300..842ec157d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -139,18 +139,6 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { } throw LogicError("Invalid opcode {}", inst->GetOpcode()); } - -void Alias(IR::Inst& inst, const IR::Value& value) { - if (value.IsImmediate()) { - return; - } - IR::Inst* const value_inst{value.InstRecursive()}; - if (inst.GetOpcode() == IR::Opcode::Identity) { - value_inst->DestructiveAddUsage(inst.UseCount()); - value_inst->DestructiveRemoveUsage(); - } - inst.SetDefinition(value_inst->Definition()); -} } // Anonymous namespace std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { @@ -183,32 +171,4 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { return ctx.code; } -void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastU32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastF32U32(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - -void EmitBitCastF64U64(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); -} - } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index e69de29bb..918d82375 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -0,0 +1,75 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +static void Alias(IR::Inst& inst, const IR::Value& value) { + if (value.IsImmediate()) { + return; + } + IR::Inst* const value_inst{value.InstRecursive()}; + if (inst.GetOpcode() == IR::Opcode::Identity) { + value_inst->DestructiveAddUsage(inst.UseCount()); + value_inst->DestructiveRemoveUsage(); + } + inst.SetDefinition(value_inst->Definition()); +} + +void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastU32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastF32U32(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitBitCastF64U64(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + +void EmitPackUint2x32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUnpackUint2x32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitPackFloat2x16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitUnpackFloat2x16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitPackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.Add("PK2H {}.x,{};", inst, value); +} + +void EmitUnpackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.Add("UP2H {}.xy,{}.x;", inst, value); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 42de6716a..cb1067dc9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -200,8 +200,8 @@ void EmitPackUint2x32(EmitContext& ctx, Register value); void EmitUnpackUint2x32(EmitContext& ctx, Register value); void EmitPackFloat2x16(EmitContext& ctx, Register value); void EmitUnpackFloat2x16(EmitContext& ctx, Register value); -void EmitPackHalf2x16(EmitContext& ctx, Register value); -void EmitUnpackHalf2x16(EmitContext& ctx, Register value); +void EmitPackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitUnpackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value); void EmitPackDouble2x32(EmitContext& ctx, Register value); void EmitUnpackDouble2x32(EmitContext& ctx, Register value); void EmitGetZeroFromOp(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 5729b27a7..03464524e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -281,30 +281,6 @@ void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Regist NotImplemented(); } -void EmitPackUint2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitUnpackUint2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitPackFloat2x16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitUnpackFloat2x16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitPackHalf2x16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitUnpackHalf2x16(EmitContext& ctx, Register value) { - NotImplemented(); -} - void EmitPackDouble2x32(EmitContext& ctx, Register value) { NotImplemented(); } -- cgit v1.2.3 From 4502595bc2518eecf934110e9393b11bf0c2f75a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 18:03:01 -0300 Subject: glasm: Initial GLASM fp64 support --- src/shader_recompiler/backend/glasm/emit_context.h | 7 +++ src/shader_recompiler/backend/glasm/emit_glasm.cpp | 17 ++++-- .../glasm/emit_glasm_bitwise_conversion.cpp | 8 +++ .../backend/glasm/emit_glasm_floating_point.cpp | 16 +++--- .../backend/glasm/emit_glasm_instructions.h | 12 ++-- .../backend/glasm/emit_glasm_memory.cpp | 10 ++-- .../backend/glasm/emit_glasm_not_implemented.cpp | 8 --- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 66 +++++++++++++++------- src/shader_recompiler/backend/glasm/reg_alloc.h | 63 +++++++++++++++++++-- 9 files changed, 152 insertions(+), 55 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index a59acbf6c..37663c1c8 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -29,6 +29,13 @@ public: code += '\n'; } + template + void LongAdd(const char* format_str, IR::Inst& inst, Args&&... args) { + code += fmt::format(format_str, reg_alloc.LongDefine(inst), std::forward(args)...); + // TODO: Remove this + code += '\n'; + } + template void Add(const char* format_str, Args&&... args) { code += fmt::format(format_str, std::forward(args)...); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 842ec157d..9db6eb4a0 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -42,7 +42,11 @@ template struct RegWrapper { RegWrapper(EmitContext& ctx, Value value) : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { - reg = allocated ? reg_alloc.AllocReg() : Register{value}; + if (allocated) { + reg = value.type == Type::F64 ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); + } else { + reg = Register{value}; + } switch (value.type) { case Type::Register: break; @@ -55,6 +59,9 @@ struct RegWrapper { case Type::F32: ctx.Add("MOV.F {}.x,{};", reg, value.imm_f32); break; + case Type::F64: + ctx.Add("MOV.F64 {}.x,{};", reg, value.imm_f64); + break; } } ~RegWrapper() { @@ -162,10 +169,12 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) { header += fmt::format("R{},", index); } - header += "RC;"; - if (!program.info.storage_buffers_descriptors.empty()) { - header += "LONG TEMP LC;"; + header += "RC;" + "LONG TEMP "; + for (size_t index = 0; index < ctx.reg_alloc.NumUsedLongRegisters(); ++index) { + header += fmt::format("D{},", index); } + header += "DC;"; ctx.code.insert(0, header); ctx.code += "END"; return ctx.code; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index 918d82375..eb6140954 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -72,4 +72,12 @@ void EmitUnpackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value) { ctx.Add("UP2H {}.xy,{}.x;", inst, value); } +void EmitPackDouble2x32(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.LongAdd("PK64 {}.x,{};", inst, value); +} + +void EmitUnpackDouble2x32(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.Add("UP64 {}.xy,{}.x;", inst, value); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index fed6503c6..2b9a210aa 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -10,7 +10,8 @@ namespace Shader::Backend::GLASM { -void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { +void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } @@ -18,8 +19,8 @@ void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { ctx.Add("MOV.F {}.x,|{}|;", inst, value); } -void EmitFPAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPAbs64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + ctx.LongAdd("MOV.F64 {}.x,|{}|;", inst, value); } void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -31,9 +32,8 @@ void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { ctx.Add("ADD.F {}.x,{},{};", inst, a, b); } -void EmitFPAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] Register a, [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { + ctx.LongAdd("ADD.F64 {}.x,{},{};", inst, a, b); } void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -94,8 +94,8 @@ void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value) { ctx.Add("MOV.F {}.x,-{};", inst, value); } -void EmitFPNeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.LongAdd("MOV.F64 {}.x,-{};", inst, value); } void EmitFPSin([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index cb1067dc9..ab1e08215 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -202,20 +202,20 @@ void EmitPackFloat2x16(EmitContext& ctx, Register value); void EmitUnpackFloat2x16(EmitContext& ctx, Register value); void EmitPackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value); void EmitUnpackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value); -void EmitPackDouble2x32(EmitContext& ctx, Register value); -void EmitUnpackDouble2x32(EmitContext& ctx, Register value); +void EmitPackDouble2x32(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitUnpackDouble2x32(EmitContext& ctx, IR::Inst& inst, Register value); void EmitGetZeroFromOp(EmitContext& ctx); void EmitGetSignFromOp(EmitContext& ctx); void EmitGetCarryFromOp(EmitContext& ctx); void EmitGetOverflowFromOp(EmitContext& ctx); void EmitGetSparseFromOp(EmitContext& ctx); void EmitGetInBoundsFromOp(EmitContext& ctx); -void EmitFPAbs16(EmitContext& ctx, Register value); +void EmitFPAbs16(EmitContext& ctx, IR::Inst& inst, Register value); void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); -void EmitFPAbs64(EmitContext& ctx, Register value); +void EmitFPAbs64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitFPAdd16(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); -void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c); void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); @@ -228,7 +228,7 @@ void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitFPNeg16(EmitContext& ctx, Register value); void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value); -void EmitFPNeg64(EmitContext& ctx, Register value); +void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitFPSin(EmitContext& ctx, ScalarF32 value); void EmitFPCos(EmitContext& ctx, ScalarF32 value); void EmitFPExp2(EmitContext& ctx, ScalarF32 value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 8ef0f7c17..0c6a6e1c8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -17,9 +17,9 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, // address = c[binding].xy // length = c[binding].z const u32 sb_binding{binding.U32()}; - ctx.Add("PK64.U LC,c[{}];" // pointer = address - "CVT.U64.U32 LC.z,{};" // offset = uint64_t(offset) - "ADD.U64 LC.x,LC.x,LC.z;" // pointer += offset + ctx.Add("PK64.U DC,c[{}];" // pointer = address + "CVT.U64.U32 DC.z,{};" // offset = uint64_t(offset) + "ADD.U64 DC.x,DC.x,DC.z;" // pointer += offset "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length sb_binding, offset, offset, sb_binding); if (else_expr.empty()) { @@ -32,13 +32,13 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, template void Store(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value, std::string_view size) { - StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, value)); + StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, value)); } void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, std::string_view size) { const Register ret{ctx.reg_alloc.Define(inst)}; - StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},LC.x;", size, ret), + StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, ret), fmt::format("MOV.U {},{{0,0,0,0}};", ret)); } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 03464524e..f3baf33af 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -281,14 +281,6 @@ void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Regist NotImplemented(); } -void EmitPackDouble2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitUnpackDouble2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - void EmitGetZeroFromOp(EmitContext& ctx) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 030b48d83..82b627500 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -14,12 +14,11 @@ namespace Shader::Backend::GLASM { Register RegAlloc::Define(IR::Inst& inst) { - const Id id{Alloc()}; - inst.SetDefinition(id); - Register ret; - ret.type = Type::Register; - ret.id = id; - return ret; + return Define(inst, false); +} + +Register RegAlloc::LongDefine(IR::Inst& inst) { + return Define(inst, true); } Value RegAlloc::Consume(const IR::Value& value) { @@ -40,6 +39,10 @@ Value RegAlloc::Consume(const IR::Value& value) { ret.type = Type::F32; ret.imm_f32 = value.F32(); break; + case IR::Type::F64: + ret.type = Type::F64; + ret.imm_f64 = value.F64(); + break; default: throw NotImplementedException("Immediate type {}", value.Type()); } @@ -49,7 +52,14 @@ Value RegAlloc::Consume(const IR::Value& value) { Register RegAlloc::AllocReg() { Register ret; ret.type = Type::Register; - ret.id = Alloc(); + ret.id = Alloc(false); + return ret; +} + +Register RegAlloc::AllocLongReg() { + Register ret; + ret.type = Type::Register; + ret.id = Alloc(true); return ret; } @@ -57,6 +67,15 @@ void RegAlloc::FreeReg(Register reg) { Free(reg.id); } +Register RegAlloc::Define(IR::Inst& inst, bool is_long) { + const Id id{Alloc(is_long)}; + inst.SetDefinition(id); + Register ret; + ret.type = Type::Register; + ret.id = id; + return ret; +} + Value RegAlloc::Consume(IR::Inst& inst) { const Id id{inst.Definition()}; inst.DestructiveRemoveUsage(); @@ -69,18 +88,23 @@ Value RegAlloc::Consume(IR::Inst& inst) { return ret; } -Id RegAlloc::Alloc() { - for (size_t reg = 0; reg < NUM_REGS; ++reg) { - if (register_use[reg]) { - continue; +Id RegAlloc::Alloc(bool is_long) { + size_t& num_regs{is_long ? num_used_long_registers : num_used_registers}; + std::bitset& use{is_long ? long_register_use : register_use}; + if (num_used_registers + num_used_long_registers < NUM_REGS) { + for (size_t reg = 0; reg < NUM_REGS; ++reg) { + if (use[reg]) { + continue; + } + num_regs = std::max(num_regs, reg + 1); + use[reg] = true; + Id ret{}; + ret.index.Assign(static_cast(reg)); + ret.is_long.Assign(is_long ? 1 : 0); + ret.is_spill.Assign(0); + ret.is_condition_code.Assign(0); + return ret; } - num_used_registers = std::max(num_used_registers, reg + 1); - register_use[reg] = true; - Id ret{}; - ret.index.Assign(static_cast(reg)); - ret.is_spill.Assign(0); - ret.is_condition_code.Assign(0); - return ret; } throw NotImplementedException("Register spilling"); } @@ -89,7 +113,11 @@ void RegAlloc::Free(Id id) { if (id.is_spill != 0) { throw NotImplementedException("Free spill"); } - register_use[id.index] = false; + if (id.is_long != 0) { + long_register_use[id.index] = false; + } else { + register_use[id.index] = false; + } } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 6a238afa9..f1899eae1 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -27,12 +27,14 @@ enum class Type : u32 { U32, S32, F32, + F64, }; struct Id { union { u32 raw; - BitField<0, 30, u32> index; + BitField<0, 29, u32> index; + BitField<29, 1, u32> is_long; BitField<30, 1, u32> is_spill; BitField<31, 1, u32> is_condition_code; }; @@ -53,6 +55,7 @@ struct Value { u32 imm_u32; s32 imm_s32; f32 imm_f32; + f64 imm_f64; }; bool operator==(const Value& rhs) const noexcept { @@ -68,6 +71,8 @@ struct Value { return imm_s32 == rhs.imm_s32; case Type::F32: return Common::BitCast(imm_f32) == Common::BitCast(rhs.imm_f32); + case Type::F64: + return Common::BitCast(imm_f64) == Common::BitCast(rhs.imm_f64); } return false; } @@ -80,6 +85,7 @@ struct ScalarRegister : Value {}; struct ScalarU32 : Value {}; struct ScalarS32 : Value {}; struct ScalarF32 : Value {}; +struct ScalarF64 : Value {}; class RegAlloc { public: @@ -87,9 +93,13 @@ public: Register Define(IR::Inst& inst); + Register LongDefine(IR::Inst& inst); + Value Consume(const IR::Value& value); - Register AllocReg(); + [[nodiscard]] Register AllocReg(); + + [[nodiscard]] Register AllocLongReg(); void FreeReg(Register reg); @@ -97,19 +107,27 @@ public: return num_used_registers; } + [[nodiscard]] size_t NumUsedLongRegisters() const noexcept { + return num_used_long_registers; + } + private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; + Register Define(IR::Inst& inst, bool is_long); + Value Consume(IR::Inst& inst); - Id Alloc(); + Id Alloc(bool is_long); void Free(Id id); EmitContext& ctx; size_t num_used_registers{}; + size_t num_used_long_registers{}; std::bitset register_use{}; + std::bitset long_register_use{}; }; template @@ -121,9 +139,17 @@ auto FormatTo(FormatContext& ctx, Id id) { throw NotImplementedException("Spill emission"); } if constexpr (scalar) { - return fmt::format_to(ctx.out(), "R{}.x", id.index.Value()); + if (id.is_long != 0) { + return fmt::format_to(ctx.out(), "D{}.x", id.index.Value()); + } else { + return fmt::format_to(ctx.out(), "R{}.x", id.index.Value()); + } } else { - return fmt::format_to(ctx.out(), "R{}", id.index.Value()); + if (id.is_long != 0) { + return fmt::format_to(ctx.out(), "D{}", id.index.Value()); + } else { + return fmt::format_to(ctx.out(), "R{}", id.index.Value()); + } } } @@ -184,6 +210,8 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_s32)); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + case Shader::Backend::GLASM::Type::F64: + break; } throw Shader::InvalidArgument("Invalid value type {}", value.type); } @@ -205,6 +233,8 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", value.imm_s32); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + case Shader::Backend::GLASM::Type::F64: + break; } throw Shader::InvalidArgument("Invalid value type {}", value.type); } @@ -226,6 +256,29 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_s32)); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", value.imm_f32); + case Shader::Backend::GLASM::Type::F64: + break; + } + throw Shader::InvalidArgument("Invalid value type {}", value.type); + } +}; + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const Shader::Backend::GLASM::ScalarF64& value, FormatContext& ctx) { + switch (value.type) { + case Shader::Backend::GLASM::Type::Register: + return Shader::Backend::GLASM::FormatTo(ctx, value.id); + case Shader::Backend::GLASM::Type::U32: + case Shader::Backend::GLASM::Type::S32: + case Shader::Backend::GLASM::Type::F32: + break; + case Shader::Backend::GLASM::Type::F64: + return format_to(ctx.out(), "{}", value.imm_f64); } throw Shader::InvalidArgument("Invalid value type {}", value.type); } -- cgit v1.2.3 From 3e10709091ea6d126474dbac2f2c8f0b6e9a0d3f Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 9 May 2021 17:57:57 -0400 Subject: glasm: Reimplement bitwise ops and BFI/BFE --- .../backend/glasm/emit_glasm_instructions.h | 34 ++++----- .../backend/glasm/emit_glasm_integer.cpp | 82 ++++++++++------------ .../backend/glasm/emit_glasm_not_implemented.cpp | 28 +------- .../backend/glasm/emit_glasm_select.cpp | 52 ++++++++++++++ 4 files changed, 108 insertions(+), 88 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index ab1e08215..aef5f7663 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -185,10 +185,12 @@ void EmitCompositeInsertF64x4(EmitContext& ctx, Register composite, Register obj void EmitSelectU1(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); -void EmitSelectU32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value); void EmitSelectU64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); void EmitSelectF16(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); -void EmitSelectF32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value); void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); @@ -313,15 +315,15 @@ void EmitShiftRightArithmetic64(EmitContext& ctx, Register base, Register shift) void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); -void EmitBitFieldInsert(EmitContext& ctx, ScalarS32 base, ScalarS32 insert, ScalarS32 offset, - ScalarS32 count); +void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert, + ScalarS32 offset, ScalarS32 count); void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset, ScalarS32 count); void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, ScalarU32 count); -void EmitBitReverse32(EmitContext& ctx, ScalarS32 value); +void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitBitCount32(EmitContext& ctx, ScalarS32 value); -void EmitBitwiseNot32(EmitContext& ctx, ScalarS32 value); +void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitFindSMsb32(EmitContext& ctx, ScalarS32 value); void EmitFindUMsb32(EmitContext& ctx, ScalarU32 value); void EmitSMin32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); @@ -330,16 +332,16 @@ void EmitSMax32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); void EmitUMax32(EmitContext& ctx, ScalarU32 a, ScalarU32 b); void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max); void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max); -void EmitSLessThan(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitULessThan(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); -void EmitIEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitSLessThanEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitULessThanEqual(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); -void EmitSGreaterThan(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitUGreaterThan(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); -void EmitINotEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitSGreaterThanEqual(EmitContext& ctx, ScalarS32 lhs, ScalarS32 rhs); -void EmitUGreaterThanEqual(EmitContext& ctx, ScalarU32 lhs, ScalarU32 rhs); +void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitULessThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs); +void EmitIEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs); +void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs); +void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); +void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs); void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); void EmitSharedAtomicSMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value); void EmitSharedAtomicUMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 7b88d6f02..2db05e62d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -87,34 +87,34 @@ void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b ctx.Add("XOR.S {}.x,{},{};", inst, a, b); } -void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 base, - [[maybe_unused]] ScalarS32 insert, [[maybe_unused]] ScalarS32 offset, - [[maybe_unused]] ScalarS32 count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert, + ScalarS32 offset, ScalarS32 count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFI.S {},RC,{},{};", inst, insert, base); } -void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] ScalarS32 base, [[maybe_unused]] ScalarS32 offset, - [[maybe_unused]] ScalarS32 count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset, + ScalarS32 count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFE.S {},RC,{};", inst, base); } -void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] ScalarU32 base, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] ScalarU32 count) { - throw NotImplementedException("GLASM instruction"); +void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, + ScalarU32 count) { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); + ctx.Add("BFE.U {},RC,{};", inst, base); } -void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("BFR {},{};", inst, value); } void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { throw NotImplementedException("GLASM instruction"); } -void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("NOT.S {},{};", inst, value); } void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { @@ -157,54 +157,44 @@ void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& throw NotImplementedException("GLASM instruction"); } -void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SLT.S {},{},{};", inst, lhs, rhs); } -void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, - [[maybe_unused]] ScalarU32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitULessThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { + ctx.Add("SLT.U {},{},{};", inst, lhs, rhs); } -void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitIEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SEQ.S {},{},{};", inst, lhs, rhs); } -void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SLE.S {},{},{};", inst, lhs, rhs); } -void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, - [[maybe_unused]] ScalarU32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { + ctx.Add("SLE.U {},{},{};", inst, lhs, rhs); } -void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SGT.S {},{},{};", inst, lhs, rhs); } -void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, - [[maybe_unused]] ScalarU32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { + ctx.Add("SGT.U {},{},{};", inst, lhs, rhs); } -void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SNE.U {},{},{};", inst, lhs, rhs); } -void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 lhs, - [[maybe_unused]] ScalarS32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { + ctx.Add("SGE.S {},{},{};", inst, lhs, rhs); } -void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 lhs, - [[maybe_unused]] ScalarU32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { + ctx.Add("SGE.U {},{},{};", inst, lhs, rhs); } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index f3baf33af..e94571f2d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -249,35 +249,11 @@ void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value) { NotImplemented(); } -void EmitSelectU1(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { +void EmitPackDouble2x32(EmitContext& ctx, Register value) { NotImplemented(); } -void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { - NotImplemented(); -} - -void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { - NotImplemented(); -} - -void EmitSelectU32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { - NotImplemented(); -} - -void EmitSelectU64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { - NotImplemented(); -} - -void EmitSelectF16(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { - NotImplemented(); -} - -void EmitSelectF32(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value) { - NotImplemented(); -} - -void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value) { +void EmitUnpackDouble2x32(EmitContext& ctx, Register value) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index e69de29bb..8f9df8e23 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -0,0 +1,52 @@ + +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitSelectU1([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] ScalarS32 true_value, [[maybe_unused]] ScalarS32 false_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] ScalarS32 true_value, [[maybe_unused]] ScalarS32 false_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] ScalarS32 true_value, [[maybe_unused]] ScalarS32 false_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value) { + ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); +} + +void EmitSelectU64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] Register true_value, [[maybe_unused]] Register false_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectF16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] Register true_value, [[maybe_unused]] Register false_value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value) { + ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); +} + +void EmitSelectF64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, + [[maybe_unused]] Register true_value, [[maybe_unused]] Register false_value) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 6705f56029d627941f56e36273fd4548a88e8b63 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 9 May 2021 18:49:27 -0400 Subject: emit_glasm: Implement more integer alu ops --- .../backend/glasm/emit_glasm_instructions.h | 22 ++++---- .../backend/glasm/emit_glasm_integer.cpp | 66 ++++++++++------------ 2 files changed, 41 insertions(+), 47 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index aef5f7663..b19899624 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -302,15 +302,15 @@ void EmitIAdd64(EmitContext& ctx, Register a, Register b); void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitISub64(EmitContext& ctx, Register a, Register b); void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); -void EmitINeg32(EmitContext& ctx, ScalarS32 value); +void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitINeg64(EmitContext& ctx, Register value); -void EmitIAbs32(EmitContext& ctx, ScalarS32 value); +void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitIAbs64(EmitContext& ctx, Register value); void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); void EmitShiftLeftLogical64(EmitContext& ctx, Register base, Register shift); -void EmitShiftRightLogical32(EmitContext& ctx, ScalarU32 base, ScalarU32 shift); +void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); void EmitShiftRightLogical64(EmitContext& ctx, Register base, Register shift); -void EmitShiftRightArithmetic32(EmitContext& ctx, ScalarS32 base, ScalarS32 shift); +void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 shift); void EmitShiftRightArithmetic64(EmitContext& ctx, Register base, Register shift); void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); @@ -322,14 +322,14 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scal void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, ScalarU32 count); void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitBitCount32(EmitContext& ctx, ScalarS32 value); +void EmitBitCount32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitFindSMsb32(EmitContext& ctx, ScalarS32 value); -void EmitFindUMsb32(EmitContext& ctx, ScalarU32 value); -void EmitSMin32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); -void EmitUMin32(EmitContext& ctx, ScalarU32 a, ScalarU32 b); -void EmitSMax32(EmitContext& ctx, ScalarS32 a, ScalarS32 b); -void EmitUMax32(EmitContext& ctx, ScalarU32 a, ScalarU32 b); +void EmitFindSMsb32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); +void EmitFindUMsb32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); +void EmitSMin32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b); +void EmitSMax32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b); void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max); void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max); void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 2db05e62d..9d72af942 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -30,16 +30,16 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { ctx.Add("MUL.S {}.x,{},{};", inst, a, b); } -void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("MOV.S {},-{};", inst, value); } void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("ABS.S {},{};", inst, value); } void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { @@ -55,9 +55,8 @@ void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 base, - [[maybe_unused]] ScalarU32 shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) { + ctx.Add("SHR.U {}.x,{},{};", inst, base, shift); } void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, @@ -65,9 +64,8 @@ void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] throw NotImplementedException("GLASM instruction"); } -void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 base, - [[maybe_unused]] ScalarS32 shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 shift) { + ctx.Add("SHR.S {}.x,{},{};", inst, base, shift); } void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, @@ -109,52 +107,48 @@ void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("BFR {},{};", inst, value); } -void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitBitCount32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("BTC {},{};", inst, value); } void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("NOT.S {},{};", inst, value); } -void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFindSMsb32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("BTFM.S {},{};", inst, value); } -void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFindUMsb32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value) { + ctx.Add("BTFM.U {},{};", inst, value); } -void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 a, - [[maybe_unused]] ScalarS32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitSMin32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("MIN.S {},{},{};", inst, a, b); } -void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 a, - [[maybe_unused]] ScalarU32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) { + ctx.Add("MIN.U {},{},{};", inst, a, b); } -void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 a, - [[maybe_unused]] ScalarS32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitSMax32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("MAX.S {},{},{};", inst, a, b); } -void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 a, - [[maybe_unused]] ScalarU32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) { + ctx.Add("MAX.U {},{},{};", inst, a, b); } -void EmitSClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] ScalarS32 value, [[maybe_unused]] ScalarS32 min, - [[maybe_unused]] ScalarS32 max) { - throw NotImplementedException("GLASM instruction"); +void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("MIN.S {}.x,{},{};", ret, max, value); + ctx.Add("MAX.S {}.x,{},{};", ret, ret, min); } -void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] ScalarU32 value, [[maybe_unused]] ScalarU32 min, - [[maybe_unused]] ScalarU32 max) { - throw NotImplementedException("GLASM instruction"); +void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("MIN.U {}.x,{},{};", ret, max, value); + ctx.Add("MAX.U {}.x,{},{};", ret, ret, min); } void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { -- cgit v1.2.3 From b4953e79ee5eb9ed0918ce8696571240d7a07af8 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 21:13:09 -0300 Subject: glasm: Add floating-point comparisons on GLASM --- .../backend/glasm/emit_glasm_floating_point.cpp | 170 +++++++++++---------- .../backend/glasm/emit_glasm_instructions.h | 54 +++---- .../backend/glasm/emit_glasm_not_implemented.cpp | 12 -- 3 files changed, 116 insertions(+), 120 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 2b9a210aa..1139a22bd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -10,6 +10,31 @@ namespace Shader::Backend::GLASM { +template +static void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, + std::string_view op, std::string_view type, bool ordered, + bool inequality = false) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("{}.{} RC.x,{},{};", op, type, lhs, rhs); + if (ordered && inequality) { + ctx.Add("SEQ.{} RC.y,{},{};" + "SEQ.{} RC.z,{},{};" + "AND.U RC.x,RC.x,RC.y;" + "AND.U RC.x,RC.x,RC.z;" + "SNE.S {}.x,RC.x,0;", + type, lhs, lhs, type, rhs, rhs, ret); + } else if (ordered) { + ctx.Add("SNE.S {}.x,RC.x,0;", ret); + } else { + ctx.Add("SNE.{} RC.y,{},{};" + "SNE.{} RC.z,{},{};" + "OR.U RC.x,RC.x,RC.y;" + "OR.U RC.x,RC.x,RC.z;" + "SNE.S {}.x,RC.x,0;", + type, lhs, lhs, type, rhs, rhs, ret); + } +} + void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); @@ -46,10 +71,8 @@ void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, Sca ctx.Add("MAD.F {}.x,{},{},{};", inst, a, b, c); } -void EmitFPFma64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] Register a, [[maybe_unused]] Register b, - [[maybe_unused]] Register c) { - throw NotImplementedException("GLASM instruction"); +void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b, ScalarF64 c) { + ctx.LongAdd("MAD.F64 {}.x,{},{},{};", inst, a, b, c); } void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, @@ -57,9 +80,8 @@ void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a throw NotImplementedException("GLASM instruction"); } -void EmitFPMax64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, - [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPMax64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { + ctx.LongAdd("MAX.F64 {},{},{};", inst, a, b); } void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, @@ -67,9 +89,8 @@ void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a throw NotImplementedException("GLASM instruction"); } -void EmitFPMin64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, - [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPMin64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { + ctx.LongAdd("MIN.F64 {},{},{};", inst, a, b); } void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -81,9 +102,8 @@ void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { ctx.Add("MUL.F {}.x,{},{};", inst, a, b); } -void EmitFPMul64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] Register a, [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { + ctx.LongAdd("MUL.F64 {}.x,{},{};", inst, a, b); } void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { @@ -215,13 +235,11 @@ void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Regist } void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { - const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SEQ.F {}.x,{},{};SNE.S {}.x,{},0;", ret, lhs, rhs, ret, ret); + Compare(ctx, inst, lhs, rhs, "SEQ", "F", true); } -void EmitFPOrdEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SEQ", "F64", true); } void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -229,14 +247,12 @@ void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Regi throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SEQ", "F", false); } -void EmitFPUnordEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SEQ", "F64", false); } void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -244,14 +260,12 @@ void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Reg throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdNotEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SNE", "F", true, true); } -void EmitFPOrdNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdNotEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SNE", "F64", true, true); } void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -259,14 +273,12 @@ void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] R throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordNotEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordNotEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SNE", "F", false, true); } -void EmitFPUnordNotEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordNotEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SNE", "F64", false, true); } void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -275,13 +287,11 @@ void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Reg } void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { - const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SLT.F {}.x,{},{};SNE.S {}.x,{}.x,0;", ret, lhs, rhs, ret, ret); + Compare(ctx, inst, lhs, rhs, "SLT", "F", true); } -void EmitFPOrdLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdLessThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SLT", "F64", true); } void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -289,14 +299,12 @@ void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] R throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SLT", "F", false); } -void EmitFPUnordLessThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordLessThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SLT", "F64", false); } void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -304,14 +312,12 @@ void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdGreaterThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SGT", "F", true); } -void EmitFPOrdGreaterThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdGreaterThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SGT", "F64", true); } void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -319,14 +325,12 @@ void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused] throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThan32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordGreaterThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SGT", "F", false); } -void EmitFPUnordGreaterThan64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordGreaterThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SGT", "F64", false); } void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -335,13 +339,11 @@ void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused] } void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { - const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("SLE.F {}.x,{},{};SNE.S {}.x,{}.x,0;", ret, lhs, rhs, ret, ret); + Compare(ctx, inst, lhs, rhs, "SLE", "F", true); } -void EmitFPOrdLessThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdLessThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SLE", "F64", true); } void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -349,14 +351,12 @@ void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unuse throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordLessThanEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SLE", "F", false); } -void EmitFPUnordLessThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordLessThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SLE", "F64", false); } void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -364,14 +364,12 @@ void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unus throw NotImplementedException("GLASM instruction"); } -void EmitFPOrdGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 lhs, - [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SGE", "F", true); } -void EmitFPOrdGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SGE", "F64", true); } void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, @@ -379,14 +377,24 @@ void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_un throw NotImplementedException("GLASM instruction"); } -void EmitFPUnordGreaterThanEqual32([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] ScalarF32 lhs, [[maybe_unused]] ScalarF32 rhs) { - throw NotImplementedException("GLASM instruction"); +void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs) { + Compare(ctx, inst, lhs, rhs, "SGE", "F", false); } -void EmitFPUnordGreaterThanEqual64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, - [[maybe_unused]] Register rhs) { +void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs) { + Compare(ctx, inst, lhs, rhs, "SGE", "F64", false); +} + +void EmitFPIsNan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } +void EmitFPIsNan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Compare(ctx, inst, value, value, "SNE", "F", true, false); +} + +void EmitFPIsNan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Compare(ctx, inst, value, value, "SNE", "F64", true, false); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index b19899624..26c97ce8e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -220,14 +220,14 @@ void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c); -void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); +void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b, ScalarF64 c); void EmitFPMax32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); -void EmitFPMax64(EmitContext& ctx, Register a, Register b); +void EmitFPMax64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPMin32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); -void EmitFPMin64(EmitContext& ctx, Register a, Register b); +void EmitFPMin64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPMul16(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); -void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); +void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPNeg16(EmitContext& ctx, Register value); void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value); void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, Register value); @@ -260,43 +260,43 @@ void EmitFPTrunc32(EmitContext& ctx, ScalarF32 value); void EmitFPTrunc64(EmitContext& ctx, Register value); void EmitFPOrdEqual16(EmitContext& ctx, Register lhs, Register rhs); void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPOrdNotEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPOrdNotEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdNotEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdNotEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdNotEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordNotEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordNotEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordNotEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordNotEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordNotEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPOrdLessThan16(EmitContext& ctx, Register lhs, Register rhs); void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdLessThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordLessThan16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordLessThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordLessThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordLessThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPOrdGreaterThan16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPOrdGreaterThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdGreaterThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdGreaterThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordGreaterThan16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordGreaterThan32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordGreaterThan64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordGreaterThan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPOrdLessThanEqual16(EmitContext& ctx, Register lhs, Register rhs); void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdLessThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdLessThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordLessThanEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordLessThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordLessThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordLessThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordLessThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPOrdGreaterThanEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPUnordGreaterThanEqual16(EmitContext& ctx, Register lhs, Register rhs); -void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, ScalarF32 lhs, ScalarF32 rhs); -void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, Register lhs, Register rhs); +void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); +void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); void EmitFPIsNan16(EmitContext& ctx, Register value); -void EmitFPIsNan32(EmitContext& ctx, ScalarF32 value); -void EmitFPIsNan64(EmitContext& ctx, Register value); +void EmitFPIsNan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPIsNan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitIAdd64(EmitContext& ctx, Register a, Register b); void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index e94571f2d..60eb123cf 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -281,18 +281,6 @@ void EmitGetInBoundsFromOp(EmitContext& ctx) { NotImplemented(); } -void EmitFPIsNan16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitFPIsNan32(EmitContext& ctx, ScalarF32 value) { - NotImplemented(); -} - -void EmitFPIsNan64(EmitContext& ctx, Register value) { - NotImplemented(); -} - void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { NotImplemented(); } -- cgit v1.2.3 From 45ef62d3ba2512be3f2d445c88b85ca6c18a6fe2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 21:15:07 -0300 Subject: glasm: Remove unnecesary new white space on Clamp GLASM --- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 9d72af942..c9386805a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -141,14 +141,14 @@ void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) { void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.S {}.x,{},{};", ret, max, value); - ctx.Add("MAX.S {}.x,{},{};", ret, ret, min); + ctx.Add("MIN.S {}.x,{},{};", ret, max, value); + ctx.Add("MAX.S {}.x,{},{};", ret, ret, min); } void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.U {}.x,{},{};", ret, max, value); - ctx.Add("MAX.U {}.x,{},{};", ret, ret, min); + ctx.Add("MIN.U {}.x,{},{};", ret, max, value); + ctx.Add("MAX.U {}.x,{},{};", ret, ret, min); } void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { -- cgit v1.2.3 From 99352741afba5c88ebd31d199bdd66dcafa29bb4 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 21:17:25 -0300 Subject: glasm: Remove duplicated Fp64 pack instructions on GLASM --- .../backend/glasm/emit_glasm_not_implemented.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 60eb123cf..3f224062f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -249,14 +249,6 @@ void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value) { NotImplemented(); } -void EmitPackDouble2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitUnpackDouble2x32(EmitContext& ctx, Register value) { - NotImplemented(); -} - void EmitGetZeroFromOp(EmitContext& ctx) { NotImplemented(); } -- cgit v1.2.3 From 43a448d98d0d679c343eb81af5cedcd9be2112fa Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 21:17:48 -0300 Subject: glasm: Add logical instructions on GLASM --- .../backend/glasm/emit_glasm_instructions.h | 8 ++++---- .../backend/glasm/emit_glasm_not_implemented.cpp | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 26c97ce8e..174eaaafa 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -437,10 +437,10 @@ void EmitGlobalAtomicMinF16x2(EmitContext& ctx); void EmitGlobalAtomicMinF32x2(EmitContext& ctx); void EmitGlobalAtomicMaxF16x2(EmitContext& ctx); void EmitGlobalAtomicMaxF32x2(EmitContext& ctx); -void EmitLogicalOr(EmitContext& ctx, ScalarS32 a, ScalarS32 b); -void EmitLogicalAnd(EmitContext& ctx, ScalarS32 a, ScalarS32 b); -void EmitLogicalXor(EmitContext& ctx, ScalarS32 a, ScalarS32 b); -void EmitLogicalNot(EmitContext& ctx, ScalarS32 value); +void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitLogicalAnd(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitLogicalXor(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); +void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitConvertS16F16(EmitContext& ctx, Register value); void EmitConvertS16F32(EmitContext& ctx, Register value); void EmitConvertS16F64(EmitContext& ctx, Register value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 3f224062f..29eb75c6a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -572,20 +572,20 @@ void EmitGlobalAtomicMaxF32x2(EmitContext& ctx) { NotImplemented(); } -void EmitLogicalOr(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { - NotImplemented(); +void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("OR.S {},{},{};", inst, a, b); } -void EmitLogicalAnd(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { - NotImplemented(); +void EmitLogicalAnd(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("AND.S {},{},{};", inst, a, b); } -void EmitLogicalXor(EmitContext& ctx, ScalarS32 a, ScalarS32 b) { - NotImplemented(); +void EmitLogicalXor(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + ctx.Add("XOR.S {},{},{};", inst, a, b); } -void EmitLogicalNot(EmitContext& ctx, ScalarS32 value) { - NotImplemented(); +void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + ctx.Add("SEQ.S {},{},0;", inst, value); } void EmitConvertS16F16(EmitContext& ctx, Register value) { -- cgit v1.2.3 From 7703d65f234a3032adef795037320cd30ef28a3a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 21:22:55 -0300 Subject: glasm: Add fp min/max insts and fix store for fp64 on GLASM --- .../backend/glasm/emit_glasm_floating_point.cpp | 14 ++++++-------- .../backend/glasm/emit_glasm_instructions.h | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 1139a22bd..aab506109 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -75,22 +75,20 @@ void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b, Sca ctx.LongAdd("MAD.F64 {}.x,{},{},{};", inst, a, b, c); } -void EmitFPMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, - [[maybe_unused]] ScalarF32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { + ctx.Add("MAX.F {}.x,{},{};", inst, a, b); } void EmitFPMax64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { - ctx.LongAdd("MAX.F64 {},{},{};", inst, a, b); + ctx.LongAdd("MAX.F64 {}.x,{},{};", inst, a, b); } -void EmitFPMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 a, - [[maybe_unused]] ScalarF32 b) { - throw NotImplementedException("GLASM instruction"); +void EmitFPMin32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { + ctx.Add("MIN.F {}.x,{},{};", inst, a, b); } void EmitFPMin64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { - ctx.LongAdd("MIN.F64 {},{},{};", inst, a, b); + ctx.LongAdd("MIN.F64 {}.x,{},{};", inst, a, b); } void EmitFPMul16([[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 174eaaafa..5d94f21a6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -221,9 +221,9 @@ void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPFma16(EmitContext& ctx, IR::Inst& inst, Register a, Register b, Register c); void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c); void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b, ScalarF64 c); -void EmitFPMax32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); +void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); void EmitFPMax64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); -void EmitFPMin32(EmitContext& ctx, ScalarF32 a, ScalarF32 b); +void EmitFPMin32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); void EmitFPMin64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPMul16(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b); -- cgit v1.2.3 From ad61b47f80b96436ef675abcf1123668d9c1180d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 9 May 2021 22:43:29 -0300 Subject: glasm: Add conversion instructions to GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 + .../glasm/emit_glasm_bitwise_conversion.cpp | 8 +- .../backend/glasm/emit_glasm_convert.cpp | 231 +++++++++++++++++++++ .../backend/glasm/emit_glasm_floating_point.cpp | 50 +++-- .../backend/glasm/emit_glasm_instructions.h | 122 +++++------ .../backend/glasm/emit_glasm_integer.cpp | 10 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 192 ----------------- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 4 + src/shader_recompiler/backend/glasm/reg_alloc.h | 13 ++ 9 files changed, 351 insertions(+), 282 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 9db6eb4a0..0e4b189c9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -59,6 +59,9 @@ struct RegWrapper { case Type::F32: ctx.Add("MOV.F {}.x,{};", reg, value.imm_f32); break; + case Type::U64: + ctx.Add("MOV.U64 {}.x,{};", reg, value.imm_u64); + break; case Type::F64: ctx.Add("MOV.F64 {}.x,{};", reg, value.imm_f64); break; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index eb6140954..a6c66b826 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -48,12 +48,12 @@ void EmitBitCastF64U64(EmitContext&, IR::Inst& inst, const IR::Value& value) { Alias(inst, value); } -void EmitPackUint2x32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitPackUint2x32(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.LongAdd("PK64.U {}.x,{};", inst, value); } -void EmitUnpackUint2x32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitUnpackUint2x32(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.Add("UP64.U {}.xy,{}.x;", inst, value); } void EmitPackFloat2x16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp index e69de29bb..ccdf1cbc8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp @@ -0,0 +1,231 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/modifiers.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +std::string_view FpRounding(IR::FpRounding fp_rounding) { + switch (fp_rounding) { + case IR::FpRounding::DontCare: + return ""; + case IR::FpRounding::RN: + return ".ROUND"; + case IR::FpRounding::RZ: + return ".TRUNC"; + case IR::FpRounding::RM: + return ".FLR"; + case IR::FpRounding::RP: + return ".CEIL"; + } + throw InvalidArgument("Invalid floating-point rounding {}", fp_rounding); +} + +template +void Convert(EmitContext& ctx, IR::Inst& inst, InputType value, std::string_view dest, + std::string_view src, bool is_long_result) { + const std::string_view fp_rounding{FpRounding(inst.Flags().rounding)}; + const auto ret{is_long_result ? ctx.reg_alloc.LongDefine(inst) : ctx.reg_alloc.Define(inst)}; + ctx.Add("CVT.{}.{}{} {}.x,{};", dest, src, fp_rounding, ret, value); +} +} // Anonymous namespace + +void EmitConvertS16F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "S16", "F16", false); +} + +void EmitConvertS16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "S16", "F32", false); +} + +void EmitConvertS16F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "S16", "F64", false); +} + +void EmitConvertS32F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "S32", "F16", false); +} + +void EmitConvertS32F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "S32", "F32", false); +} + +void EmitConvertS32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "S32", "F64", false); +} + +void EmitConvertS64F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "S64", "F16", true); +} + +void EmitConvertS64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "S64", "F32", true); +} + +void EmitConvertS64F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "S64", "F64", true); +} + +void EmitConvertU16F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U16", "F16", false); +} + +void EmitConvertU16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "U16", "F32", false); +} + +void EmitConvertU16F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "U16", "F64", false); +} + +void EmitConvertU32F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U32", "F16", false); +} + +void EmitConvertU32F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "U32", "F32", false); +} + +void EmitConvertU32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "U32", "F64", false); +} + +void EmitConvertU64F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U64", "F16", true); +} + +void EmitConvertU64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "U64", "F32", true); +} + +void EmitConvertU64F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "U64", "F64", true); +} + +void EmitConvertU64U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value) { + Convert(ctx, inst, value, "U64", "U32", true); +} + +void EmitConvertU32U64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U32", "U64", false); +} + +void EmitConvertF16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "F16", "F32", false); +} + +void EmitConvertF32F16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "F16", false); +} + +void EmitConvertF32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + Convert(ctx, inst, value, "F32", "F64", false); +} + +void EmitConvertF64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + Convert(ctx, inst, value, "F64", "F32", true); +} + +void EmitConvertF16S8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "S8", false); +} + +void EmitConvertF16S16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "S16", false); +} + +void EmitConvertF16S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + Convert(ctx, inst, value, "F16", "S32", false); +} + +void EmitConvertF16S64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "S64", false); +} + +void EmitConvertF16U8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "U8", false); +} + +void EmitConvertF16U16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "U16", false); +} + +void EmitConvertF16U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value) { + Convert(ctx, inst, value, "F16", "U32", false); +} + +void EmitConvertF16U64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F16", "U64", false); +} + +void EmitConvertF32S8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "S8", false); +} + +void EmitConvertF32S16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "S16", false); +} + +void EmitConvertF32S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + Convert(ctx, inst, value, "F32", "S32", false); +} + +void EmitConvertF32S64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "S64", false); +} + +void EmitConvertF32U8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "U8", false); +} + +void EmitConvertF32U16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "U16", false); +} + +void EmitConvertF32U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value) { + Convert(ctx, inst, value, "F32", "U32", false); +} + +void EmitConvertF32U64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F32", "U64", false); +} + +void EmitConvertF64S8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "S8", true); +} + +void EmitConvertF64S16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "S16", true); +} + +void EmitConvertF64S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { + Convert(ctx, inst, value, "F64", "S32", true); +} + +void EmitConvertF64S64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "S64", true); +} + +void EmitConvertF64U8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "U8", true); +} + +void EmitConvertF64U16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "U16", true); +} + +void EmitConvertF64U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value) { + Convert(ctx, inst, value, "F64", "U32", true); +} + +void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "F64", "U64", true); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index aab506109..2aee5a56c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -169,62 +169,68 @@ void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register throw NotImplementedException("GLASM instruction"); } -void EmitFPClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value, - [[maybe_unused]] ScalarF32 min_value, [[maybe_unused]] ScalarF32 max_value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value, + ScalarF32 max_value) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("MIN.F {}.x,{},{};" + "MAX.F {}.x,{},{};", + ret, max_value, value, ret, ret, min_value); } -void EmitFPClamp64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value, - [[maybe_unused]] Register min_value, [[maybe_unused]] Register max_value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value, + ScalarF64 max_value) { + const Register ret{ctx.reg_alloc.LongDefine(inst)}; + ctx.Add("MIN.F64 {}.x,{},{};" + "MAX.F64 {}.x,{},{};", + ret, max_value, value, ret, ret, min_value); } void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRoundEven32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPRoundEven32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("ROUND.F {}.x,{};", inst, value); } -void EmitFPRoundEven64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPRoundEven64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + ctx.LongAdd("ROUND.F64 {}.x,{};", inst, value); } void EmitFPFloor16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPFloor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPFloor32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("FLR.F {}.x,{};", inst, value); } -void EmitFPFloor64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPFloor64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + ctx.LongAdd("FLR.F64 {}.x,{};", inst, value); } void EmitFPCeil16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPCeil32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPCeil32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("CEIL.F {}.x,{};", inst, value); } -void EmitFPCeil64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPCeil64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + ctx.LongAdd("CEIL.F64 {}.x,{};", inst, value); } void EmitFPTrunc16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPTrunc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPTrunc32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("TRUNC.F {}.x,{};", inst, value); } -void EmitFPTrunc64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPTrunc64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value) { + ctx.LongAdd("TRUNC.F64 {}.x,{};", inst, value); } void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register lhs, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 5d94f21a6..94843cc60 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -198,8 +198,8 @@ void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitPackUint2x32(EmitContext& ctx, Register value); -void EmitUnpackUint2x32(EmitContext& ctx, Register value); +void EmitPackUint2x32(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitUnpackUint2x32(EmitContext& ctx, IR::Inst& inst, Register value); void EmitPackFloat2x16(EmitContext& ctx, Register value); void EmitUnpackFloat2x16(EmitContext& ctx, Register value); void EmitPackHalf2x16(EmitContext& ctx, IR::Inst& inst, Register value); @@ -244,20 +244,22 @@ void EmitFPSaturate16(EmitContext& ctx, Register value); void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPSaturate64(EmitContext& ctx, Register value); void EmitFPClamp16(EmitContext& ctx, Register value, Register min_value, Register max_value); -void EmitFPClamp32(EmitContext& ctx, ScalarF32 value, ScalarF32 min_value, ScalarF32 max_value); -void EmitFPClamp64(EmitContext& ctx, Register value, Register min_value, Register max_value); +void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value, + ScalarF32 max_value); +void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value, + ScalarF64 max_value); void EmitFPRoundEven16(EmitContext& ctx, Register value); -void EmitFPRoundEven32(EmitContext& ctx, ScalarF32 value); -void EmitFPRoundEven64(EmitContext& ctx, Register value); +void EmitFPRoundEven32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPRoundEven64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitFPFloor16(EmitContext& ctx, Register value); -void EmitFPFloor32(EmitContext& ctx, ScalarF32 value); -void EmitFPFloor64(EmitContext& ctx, Register value); +void EmitFPFloor32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPFloor64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitFPCeil16(EmitContext& ctx, Register value); -void EmitFPCeil32(EmitContext& ctx, ScalarF32 value); -void EmitFPCeil64(EmitContext& ctx, Register value); +void EmitFPCeil32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPCeil64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitFPTrunc16(EmitContext& ctx, Register value); -void EmitFPTrunc32(EmitContext& ctx, ScalarF32 value); -void EmitFPTrunc64(EmitContext& ctx, Register value); +void EmitFPTrunc32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPTrunc64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitFPOrdEqual16(EmitContext& ctx, Register lhs, Register rhs); void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, ScalarF32 lhs, ScalarF32 rhs); void EmitFPOrdEqual64(EmitContext& ctx, IR::Inst& inst, ScalarF64 lhs, ScalarF64 rhs); @@ -441,54 +443,54 @@ void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitLogicalAnd(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitLogicalXor(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitConvertS16F16(EmitContext& ctx, Register value); -void EmitConvertS16F32(EmitContext& ctx, Register value); -void EmitConvertS16F64(EmitContext& ctx, Register value); -void EmitConvertS32F16(EmitContext& ctx, Register value); -void EmitConvertS32F32(EmitContext& ctx, Register value); -void EmitConvertS32F64(EmitContext& ctx, Register value); -void EmitConvertS64F16(EmitContext& ctx, Register value); -void EmitConvertS64F32(EmitContext& ctx, Register value); -void EmitConvertS64F64(EmitContext& ctx, Register value); -void EmitConvertU16F16(EmitContext& ctx, Register value); -void EmitConvertU16F32(EmitContext& ctx, Register value); -void EmitConvertU16F64(EmitContext& ctx, Register value); -void EmitConvertU32F16(EmitContext& ctx, Register value); -void EmitConvertU32F32(EmitContext& ctx, Register value); -void EmitConvertU32F64(EmitContext& ctx, Register value); -void EmitConvertU64F16(EmitContext& ctx, Register value); -void EmitConvertU64F32(EmitContext& ctx, Register value); -void EmitConvertU64F64(EmitContext& ctx, Register value); -void EmitConvertU64U32(EmitContext& ctx, Register value); -void EmitConvertU32U64(EmitContext& ctx, Register value); -void EmitConvertF16F32(EmitContext& ctx, Register value); -void EmitConvertF32F16(EmitContext& ctx, Register value); -void EmitConvertF32F64(EmitContext& ctx, Register value); -void EmitConvertF64F32(EmitContext& ctx, Register value); -void EmitConvertF16S8(EmitContext& ctx, Register value); -void EmitConvertF16S16(EmitContext& ctx, Register value); -void EmitConvertF16S32(EmitContext& ctx, Register value); -void EmitConvertF16S64(EmitContext& ctx, Register value); -void EmitConvertF16U8(EmitContext& ctx, Register value); -void EmitConvertF16U16(EmitContext& ctx, Register value); -void EmitConvertF16U32(EmitContext& ctx, Register value); -void EmitConvertF16U64(EmitContext& ctx, Register value); -void EmitConvertF32S8(EmitContext& ctx, Register value); -void EmitConvertF32S16(EmitContext& ctx, Register value); -void EmitConvertF32S32(EmitContext& ctx, Register value); -void EmitConvertF32S64(EmitContext& ctx, Register value); -void EmitConvertF32U8(EmitContext& ctx, Register value); -void EmitConvertF32U16(EmitContext& ctx, Register value); -void EmitConvertF32U32(EmitContext& ctx, Register value); -void EmitConvertF32U64(EmitContext& ctx, Register value); -void EmitConvertF64S8(EmitContext& ctx, Register value); -void EmitConvertF64S16(EmitContext& ctx, Register value); -void EmitConvertF64S32(EmitContext& ctx, Register value); -void EmitConvertF64S64(EmitContext& ctx, Register value); -void EmitConvertF64U8(EmitContext& ctx, Register value); -void EmitConvertF64U16(EmitContext& ctx, Register value); -void EmitConvertF64U32(EmitContext& ctx, Register value); -void EmitConvertF64U64(EmitContext& ctx, Register value); +void EmitConvertS16F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertS16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertS16F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertS32F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertS32F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertS32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertS64F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertS64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertS64F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertU16F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertU16F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertU32F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU32F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertU32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertU64F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertU64F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertU64U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); +void EmitConvertU32U64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertF32F16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32F64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); +void EmitConvertF64F32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitConvertF16S8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16S16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); +void EmitConvertF16S64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16U8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16U16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF16U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); +void EmitConvertF16U64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32S8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32S16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); +void EmitConvertF32S64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32U8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32U16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF32U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); +void EmitConvertF32U64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64S8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64S16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64S32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); +void EmitConvertF64S64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64U8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64U16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertF64U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); +void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitBindlessImageSampleImplicitLod(EmitContext&); void EmitBindlessImageSampleExplicitLod(EmitContext&); void EmitBindlessImageSampleDrefImplicitLod(EmitContext&); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index c9386805a..40f48a091 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -141,14 +141,16 @@ void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) { void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.S {}.x,{},{};", ret, max, value); - ctx.Add("MAX.S {}.x,{},{};", ret, ret, min); + ctx.Add("MIN.S {}.x,{},{};" + "MAX.S {}.x,{},{};", + ret, max, value, ret, ret, min); } void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.U {}.x,{},{};", ret, max, value); - ctx.Add("MAX.U {}.x,{},{};", ret, ret, min); + ctx.Add("MIN.U {}.x,{},{};" + "MAX.U {}.x,{},{};", + ret, max, value, ret, ret, min); } void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 29eb75c6a..ebdbbcf5f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -588,198 +588,6 @@ void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("SEQ.S {},{},0;", inst, value); } -void EmitConvertS16F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS16F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS16F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS32F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS32F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS32F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS64F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS64F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertS64F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU16F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU16F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU16F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU32F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU32F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU32F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU64F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU64F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU64F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU64U32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertU32U64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32F16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32F64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64F32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16S8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16S16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16S32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16S64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16U8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16U16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16U32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF16U64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32S8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32S16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32S32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32S64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32U8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32U16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32U32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF32U64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64S8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64S16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64S32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64S64(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64U8(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64U16(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64U32(EmitContext& ctx, Register value) { - NotImplemented(); -} - -void EmitConvertF64U64(EmitContext& ctx, Register value) { - NotImplemented(); -} - void EmitBindlessImageSampleImplicitLod(EmitContext&) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 82b627500..1a65a5e7d 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -39,6 +39,10 @@ Value RegAlloc::Consume(const IR::Value& value) { ret.type = Type::F32; ret.imm_f32 = value.F32(); break; + case IR::Type::U64: + ret.type = Type::U64; + ret.imm_u64 = value.U64(); + break; case IR::Type::F64: ret.type = Type::F64; ret.imm_f64 = value.F64(); diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index f1899eae1..200c51610 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -27,6 +27,7 @@ enum class Type : u32 { U32, S32, F32, + U64, F64, }; @@ -55,6 +56,7 @@ struct Value { u32 imm_u32; s32 imm_s32; f32 imm_f32; + u64 imm_u64; f64 imm_f64; }; @@ -71,6 +73,8 @@ struct Value { return imm_s32 == rhs.imm_s32; case Type::F32: return Common::BitCast(imm_f32) == Common::BitCast(rhs.imm_f32); + case Type::U64: + return imm_u64 == rhs.imm_u64; case Type::F64: return Common::BitCast(imm_f64) == Common::BitCast(rhs.imm_f64); } @@ -103,6 +107,10 @@ public: void FreeReg(Register reg); + void InvalidateConditionCodes() { + // This does nothing for now + } + [[nodiscard]] size_t NumUsedRegisters() const noexcept { return num_used_registers; } @@ -210,6 +218,7 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_s32)); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + case Shader::Backend::GLASM::Type::U64: case Shader::Backend::GLASM::Type::F64: break; } @@ -233,6 +242,7 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", value.imm_s32); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); + case Shader::Backend::GLASM::Type::U64: case Shader::Backend::GLASM::Type::F64: break; } @@ -256,6 +266,7 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_s32)); case Shader::Backend::GLASM::Type::F32: return fmt::format_to(ctx.out(), "{}", value.imm_f32); + case Shader::Backend::GLASM::Type::U64: case Shader::Backend::GLASM::Type::F64: break; } @@ -277,6 +288,8 @@ struct fmt::formatter { case Shader::Backend::GLASM::Type::S32: case Shader::Backend::GLASM::Type::F32: break; + case Shader::Backend::GLASM::Type::U64: + return format_to(ctx.out(), "{}", Common::BitCast(value.imm_u64)); case Shader::Backend::GLASM::Type::F64: return format_to(ctx.out(), "{}", value.imm_f64); } -- cgit v1.2.3 From 80813b1d144a7f0f11047e7348620b720def93a9 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 9 May 2021 22:01:03 -0400 Subject: glasm: Implement storage atomic ops --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 13 + .../backend/glasm/emit_glasm_atomic.cpp | 291 +++++++++++++++++++++ .../backend/glasm/emit_glasm_instructions.h | 108 ++++---- .../backend/glasm/emit_glasm_not_implemented.cpp | 251 ------------------ 4 files changed, 358 insertions(+), 305 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0e4b189c9..e6e065e7f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -149,6 +149,18 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { } throw LogicError("Invalid opcode {}", inst->GetOpcode()); } + +void SetupOptions(std::string& header, Info info) { + if (info.uses_int64_bit_atomics) { + header += "OPTION NV_shader_atomic_int64;"; + } + if (info.uses_atomic_f32_add) { + header += "OPTION NV_shader_atomic_float;"; + } + if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { + header += "OPTION NV_shader_atomic_fp16_vector;"; + } +} } // Anonymous namespace std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { @@ -160,6 +172,7 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { } std::string header = "!!NVcp5.0\n" "OPTION NV_internal;"; + SetupOptions(header, program.info); switch (program.stage) { case Stage::Compute: header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp index e69de29bb..fe44c3d15 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp @@ -0,0 +1,291 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +namespace { +void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, + std::string_view then_expr, std::string_view else_expr = {}) { + // Operate on bindless SSBO, call the expression with bounds checking + // address = c[binding].xy + // length = c[binding].z + const u32 sb_binding{binding.U32()}; + ctx.Add("PK64.U DC,c[{}];" // pointer = address + "CVT.U64.U32 DC.z,{};" // offset = uint64_t(offset) + "ADD.U64 DC.x,DC.x,DC.z;" // pointer += offset + "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length + sb_binding, offset, offset, sb_binding); + if (else_expr.empty()) { + ctx.Add("IF NE.x;{}ENDIF;", then_expr); + } else { + ctx.Add("IF NE.x;{}ELSE;{}ENDIF;", then_expr, else_expr); + } +} + +template +void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, + ValueType value, std::string_view operation, std::string_view size) { + const Register ret{ctx.reg_alloc.Define(inst)}; + StorageOp(ctx, binding, offset, + fmt::format("ATOM.{}.{} {},{},DC.x;", operation, size, ret, value)); +} +} // namespace + +void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "ADD", "U32"); +} + +void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value) { + Atom(ctx, inst, binding, offset, value, "MIN", "S32"); +} + +void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "MIN", "U32"); +} + +void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value) { + Atom(ctx, inst, binding, offset, value, "MAX", "S32"); +} + +void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "MAX", "U32"); +} + +void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "IWRAP", "U32"); +} + +void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "DWRAP", "U32"); +} + +void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "AND", "U32"); +} + +void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "OR", "U32"); +} + +void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "XOR", "U32"); +} + +void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "EXCH", "U32"); +} + +void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "ADD", "U64"); +} + +void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "S64"); +} + +void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "U64"); +} + +void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "S64"); +} + +void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "U64"); +} + +void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "AND", "U64"); +} + +void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "OR", "U64"); +} + +void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "XOR", "U64"); +} + +void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "EXCH", "U64"); +} + +void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarF32 value) { + Atom(ctx, inst, binding, offset, value, "ADD", "F32"); +} + +void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "ADD", "F16x2"); +} + +void EmitStorageAtomicAddF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "F16x2"); +} + +void EmitStorageAtomicMinF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "F16x2"); +} + +void EmitStorageAtomicMaxF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicIAdd32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMin32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMin32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMax32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMax32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicInc32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicDec32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAnd32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicOr32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicXor32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicExchange32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicIAdd64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMin64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMin64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMax64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMax64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicInc64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicDec64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAnd64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicOr64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicXor64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicExchange64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMinF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMinF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMaxF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMaxF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 94843cc60..817001afb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -356,60 +356,60 @@ void EmitSharedAtomicOr32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 void EmitSharedAtomicXor32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); void EmitSharedAtomicExchange32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Register value); -void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarS32 value); -void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarS32 value); -void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value); -void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, ScalarU32 value); -void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, Register value); -void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarF32 value); -void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); -void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value); +void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value); +void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value); +void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value); +void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarF32 value); +void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicAddF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicMinF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); +void EmitStorageAtomicMaxF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value); void EmitGlobalAtomicIAdd32(EmitContext& ctx); void EmitGlobalAtomicSMin32(EmitContext& ctx); void EmitGlobalAtomicUMin32(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index ebdbbcf5f..85110bcc9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -321,257 +321,6 @@ void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Regi NotImplemented(); } -void EmitStorageAtomicIAdd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicSMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarS32 value) { - NotImplemented(); -} - -void EmitStorageAtomicUMin32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicSMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarS32 value) { - NotImplemented(); -} - -void EmitStorageAtomicUMax32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicInc32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicDec32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicAnd32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicOr32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicXor32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicExchange32(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitStorageAtomicIAdd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicSMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicUMin64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicSMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicUMax64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicAnd64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicOr64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicXor64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, - const IR::Value& offset, Register value) { - NotImplemented(); -} - -void EmitStorageAtomicAddF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - ScalarF32 value) { - NotImplemented(); -} - -void EmitStorageAtomicAddF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicAddF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicMinF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicMinF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicMaxF16x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitStorageAtomicMaxF32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, - Register value) { - NotImplemented(); -} - -void EmitGlobalAtomicIAdd32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicSMin32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicUMin32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicSMax32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicUMax32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicInc32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicDec32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicAnd32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicOr32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicXor32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicExchange32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicIAdd64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicSMin64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicUMin64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicSMax64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicUMax64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicInc64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicDec64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicAnd64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicOr64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicXor64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicExchange64(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicAddF32(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicAddF16x2(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicAddF32x2(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicMinF16x2(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicMinF32x2(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicMaxF16x2(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGlobalAtomicMaxF32x2(EmitContext& ctx) { - NotImplemented(); -} - void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { ctx.Add("OR.S {},{},{};", inst, a, b); } -- cgit v1.2.3 From 8eb72ff0dc3eb428c28b578ffb3912c1bd1c42dd Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 01:33:24 -0300 Subject: glasm: Fix moving U64 immediates to registers in GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 ++- src/shader_recompiler/backend/glasm/reg_alloc.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index e6e065e7f..8e5d575a9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -43,7 +43,8 @@ struct RegWrapper { RegWrapper(EmitContext& ctx, Value value) : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { if (allocated) { - reg = value.type == Type::F64 ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); + const bool is_long{value.type == Type::F64 || value.type == Type::U64}; + reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); } else { reg = Register{value}; } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 200c51610..8df73ca18 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -289,9 +289,9 @@ struct fmt::formatter { case Shader::Backend::GLASM::Type::F32: break; case Shader::Backend::GLASM::Type::U64: - return format_to(ctx.out(), "{}", Common::BitCast(value.imm_u64)); + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u64)); case Shader::Backend::GLASM::Type::F64: - return format_to(ctx.out(), "{}", value.imm_f64); + return fmt::format_to(ctx.out(), "{}", value.imm_f64); } throw Shader::InvalidArgument("Invalid value type {}", value.type); } -- cgit v1.2.3 From 6237300e3605c0b12fb65e2a8818487ec2cb4580 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 01:37:30 -0300 Subject: glasm: Fix clamps so the min value has priority on NAN on GLASM --- .../backend/glasm/emit_glasm_floating_point.cpp | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 2aee5a56c..2e1c7d55f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -9,11 +9,10 @@ #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { - +namespace { template -static void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, - std::string_view op, std::string_view type, bool ordered, - bool inequality = false) { +void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, std::string_view op, + std::string_view type, bool ordered, bool inequality = false) { const Register ret{ctx.reg_alloc.Define(inst)}; ctx.Add("{}.{} RC.x,{},{};", op, type, lhs, rhs); if (ordered && inequality) { @@ -35,6 +34,16 @@ static void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType r } } +template +void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value, + InputType max_value) { + // Call MAX first to properly clamp nan to min_value instead + ctx.Add("MAX.F {}.x,{},{};" + "MIN.F {}.x,{},{};", + ret, min_value, value, ret, ret, max_value); +} +} // Anonymous namespace + void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); @@ -171,18 +180,12 @@ void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value, ScalarF32 max_value) { - const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.F {}.x,{},{};" - "MAX.F {}.x,{},{};", - ret, max_value, value, ret, ret, min_value); + Clamp(ctx, ctx.reg_alloc.Define(inst), value, min_value, max_value); } void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value, ScalarF64 max_value) { - const Register ret{ctx.reg_alloc.LongDefine(inst)}; - ctx.Add("MIN.F64 {}.x,{},{};" - "MAX.F64 {}.x,{},{};", - ret, max_value, value, ret, ret, min_value); + Clamp(ctx, ctx.reg_alloc.LongDefine(inst), value, min_value, max_value); } void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { -- cgit v1.2.3 From 0839e46736858986b422b2ffb163ded59c16421f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 01:41:07 -0300 Subject: glasm: Implement SelectU64 on GLASM --- .../backend/glasm/emit_glasm_instructions.h | 3 ++- .../backend/glasm/emit_glasm_select.cpp | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 817001afb..52420c3c9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -187,7 +187,8 @@ void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, Scalar void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); -void EmitSelectU64(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); +void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, Register true_value, + Register false_value); void EmitSelectF16(EmitContext& ctx, ScalarS32 cond, Register true_value, Register false_value); void EmitSelectF32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index 8f9df8e23..cfde86047 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -29,9 +29,24 @@ void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 t ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); } -void EmitSelectU64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, - [[maybe_unused]] Register true_value, [[maybe_unused]] Register false_value) { - throw NotImplementedException("GLASM instruction"); +void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, Register true_value, + Register false_value) { + ctx.reg_alloc.InvalidateConditionCodes(); + const Register ret{ctx.reg_alloc.LongDefine(inst)}; + if (ret == true_value) { + ctx.Add("MOV.S.CC RC.x,{};" + "MOV.U64 {}.x(EQ.x),{};", + cond, ret, false_value); + } else if (ret == false_value) { + ctx.Add("MOV.S.CC RC.x,{};" + "MOV.U64 {}.x(NE.x),{};", + cond, ret, true_value); + } else { + ctx.Add("MOV.S.CC RC.x,{};" + "MOV.U64 {}.x(EQ.x),{};" + "MOV.U64 {}.x(NE.x),{};", + cond, ret, false_value, ret, true_value); + } } void EmitSelectF16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, -- cgit v1.2.3 From deda89372f78dc78b37e941bf86e3026708e3ea2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 03:47:31 -0300 Subject: glasm: Fix register allocation when moving immediate on GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 50 +++++++++++---- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 71 +++++++++++++--------- src/shader_recompiler/backend/glasm/reg_alloc.h | 10 ++- 3 files changed, 89 insertions(+), 42 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8e5d575a9..ad27b8b06 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -39,14 +39,16 @@ struct Identity { }; template -struct RegWrapper { - RegWrapper(EmitContext& ctx, Value value) - : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { - if (allocated) { +class RegWrapper { +public: + RegWrapper(EmitContext& ctx, const IR::Value& ir_value) : reg_alloc{ctx.reg_alloc} { + const Value value{reg_alloc.Peek(ir_value)}; + if (value.type == Type::Register) { + inst = ir_value.InstRecursive(); + reg = Register{value}; + } else { const bool is_long{value.type == Type::F64 || value.type == Type::U64}; reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); - } else { - reg = Register{value}; } switch (value.type) { case Type::Register: @@ -68,8 +70,11 @@ struct RegWrapper { break; } } + ~RegWrapper() { - if (allocated) { + if (inst) { + reg_alloc.Unref(*inst); + } else { reg_alloc.FreeReg(reg); } } @@ -78,19 +83,42 @@ struct RegWrapper { return std::conditional_t{Value{reg}}; } +private: RegAlloc& reg_alloc; + IR::Inst* inst{}; Register reg{}; - bool allocated{}; +}; + +template +class ValueWrapper { +public: + ValueWrapper(EmitContext& ctx, const IR::Value& ir_value_) + : reg_alloc{ctx.reg_alloc}, ir_value{ir_value_}, value{reg_alloc.Peek(ir_value)} {} + + ~ValueWrapper() { + if (!ir_value.IsImmediate()) { + reg_alloc.Unref(*ir_value.InstRecursive()); + } + } + + ArgType Extract() { + return value; + } + +private: + RegAlloc& reg_alloc; + const IR::Value& ir_value; + ArgType value; }; template auto Arg(EmitContext& ctx, const IR::Value& arg) { if constexpr (std::is_same_v) { - return RegWrapper{ctx, ctx.reg_alloc.Consume(arg)}; + return RegWrapper{ctx, arg}; } else if constexpr (std::is_same_v) { - return RegWrapper{ctx, ctx.reg_alloc.Consume(arg)}; + return RegWrapper{ctx, arg}; } else if constexpr (std::is_base_of_v) { - return Identity{ArgType{ctx.reg_alloc.Consume(arg)}}; + return ValueWrapper{ctx, arg}; } else if constexpr (std::is_same_v) { return Identity{arg}; } else if constexpr (std::is_same_v) { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 1a65a5e7d..f556f3aee 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -21,10 +21,40 @@ Register RegAlloc::LongDefine(IR::Inst& inst) { return Define(inst, true); } +Value RegAlloc::Peek(const IR::Value& value) { + return value.IsImmediate() ? MakeImm(value) : PeekInst(*value.InstRecursive()); +} + Value RegAlloc::Consume(const IR::Value& value) { - if (!value.IsImmediate()) { - return Consume(*value.InstRecursive()); + return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive()); +} + +void RegAlloc::Unref(IR::Inst& inst) { + inst.DestructiveRemoveUsage(); + if (!inst.HasUses()) { + Free(inst.Definition()); } +} + +Register RegAlloc::AllocReg() { + Register ret; + ret.type = Type::Register; + ret.id = Alloc(false); + return ret; +} + +Register RegAlloc::AllocLongReg() { + Register ret; + ret.type = Type::Register; + ret.id = Alloc(true); + return ret; +} + +void RegAlloc::FreeReg(Register reg) { + Free(reg.id); +} + +Value RegAlloc::MakeImm(const IR::Value& value) { Value ret; switch (value.Type()) { case IR::Type::U1: @@ -53,43 +83,24 @@ Value RegAlloc::Consume(const IR::Value& value) { return ret; } -Register RegAlloc::AllocReg() { - Register ret; - ret.type = Type::Register; - ret.id = Alloc(false); - return ret; -} - -Register RegAlloc::AllocLongReg() { - Register ret; - ret.type = Type::Register; - ret.id = Alloc(true); - return ret; -} - -void RegAlloc::FreeReg(Register reg) { - Free(reg.id); +Register RegAlloc::Define(IR::Inst& inst, bool is_long) { + inst.SetDefinition(Alloc(is_long)); + return Register{PeekInst(inst)}; } -Register RegAlloc::Define(IR::Inst& inst, bool is_long) { - const Id id{Alloc(is_long)}; - inst.SetDefinition(id); - Register ret; +Value RegAlloc::PeekInst(IR::Inst& inst) { + Value ret; ret.type = Type::Register; - ret.id = id; + ret.id = inst.Definition(); return ret; } -Value RegAlloc::Consume(IR::Inst& inst) { - const Id id{inst.Definition()}; +Value RegAlloc::ConsumeInst(IR::Inst& inst) { inst.DestructiveRemoveUsage(); if (!inst.HasUses()) { - Free(id); + Free(inst.Definition()); } - Value ret; - ret.type = Type::Register; - ret.id = id; - return ret; + return PeekInst(inst); } Id RegAlloc::Alloc(bool is_long) { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 8df73ca18..5742436cf 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -99,8 +99,12 @@ public: Register LongDefine(IR::Inst& inst); + [[nodiscard]] Value Peek(const IR::Value& value); + Value Consume(const IR::Value& value); + void Unref(IR::Inst& inst); + [[nodiscard]] Register AllocReg(); [[nodiscard]] Register AllocLongReg(); @@ -123,9 +127,13 @@ private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; + Value MakeImm(const IR::Value& value); + Register Define(IR::Inst& inst, bool is_long); - Value Consume(IR::Inst& inst); + Value PeekInst(IR::Inst& inst); + + Value ConsumeInst(IR::Inst& inst); Id Alloc(bool is_long); -- cgit v1.2.3 From 3f00a2ad3f4d5c89599929080b1f6efaf394b62f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 03:47:57 -0300 Subject: glasm: Properly clamp Fp64 on GLASM --- .../backend/glasm/emit_glasm_floating_point.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 2e1c7d55f..84028e01a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -36,11 +36,11 @@ void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, std template void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value, - InputType max_value) { + InputType max_value, std::string_view type) { // Call MAX first to properly clamp nan to min_value instead - ctx.Add("MAX.F {}.x,{},{};" - "MIN.F {}.x,{},{};", - ret, min_value, value, ret, ret, max_value); + ctx.Add("MAX.{} {}.x,{},{};" + "MIN.{} {}.x,{}.x,{};", + type, ret, min_value, value, type, ret, ret, max_value); } } // Anonymous namespace @@ -180,12 +180,12 @@ void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value, ScalarF32 max_value) { - Clamp(ctx, ctx.reg_alloc.Define(inst), value, min_value, max_value); + Clamp(ctx, ctx.reg_alloc.Define(inst), value, min_value, max_value, "F"); } void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value, ScalarF64 max_value) { - Clamp(ctx, ctx.reg_alloc.LongDefine(inst), value, min_value, max_value); + Clamp(ctx, ctx.reg_alloc.LongDefine(inst), value, min_value, max_value, "F64"); } void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { -- cgit v1.2.3 From 5b18a12df2116fcbb4bf10a2becd6cb404af0968 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 03:55:33 -0300 Subject: glasm: Implement IAbs64 and INeg64 on GLASM --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 4 ++-- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 52420c3c9..d65a474f2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -306,9 +306,9 @@ void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitISub64(EmitContext& ctx, Register a, Register b); void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitINeg64(EmitContext& ctx, Register value); +void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitIAbs64(EmitContext& ctx, Register value); +void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); void EmitShiftLeftLogical64(EmitContext& ctx, Register base, Register shift); void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 40f48a091..2be91ccfd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -34,16 +34,16 @@ void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("MOV.S {},-{};", inst, value); } -void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.LongAdd("MOV.S64 {},-{};", inst, value); } void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("ABS.S {},{};", inst, value); } -void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, Register value) { + ctx.LongAdd("MOV.S64 {},|{}|;", inst, value); } void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) { -- cgit v1.2.3 From decda4a2c7e5dc6cce16f359f30bcf320c9dcf00 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 04:05:31 -0300 Subject: glasm: Add MUFU instructions to GLASM --- .../backend/glasm/emit_glasm_floating_point.cpp | 29 +++++++++++----------- .../backend/glasm/emit_glasm_instructions.h | 14 +++++------ 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 84028e01a..15db6618f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -125,40 +125,41 @@ void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, Register value) { ctx.LongAdd("MOV.F64 {}.x,-{};", inst, value); } -void EmitFPSin([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPSin(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("SIN {}.x,{};", inst, value); } -void EmitFPCos([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPCos(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("COS {}.x,{};", inst, value); } -void EmitFPExp2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPExp2(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("EX2 {}.x,{};", inst, value); } -void EmitFPLog2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPLog2(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("LG2 {}.x,{};", inst, value); } -void EmitFPRecip32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPRecip32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("RCP {}.x,{};", inst, value); } void EmitFPRecip64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPRecipSqrt32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + ctx.Add("RSQ {}.x,{};", inst, value); } void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { throw NotImplementedException("GLASM instruction"); } -void EmitFPSqrt([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("RSQ {}.x,{};RCP {}.x,{}.x;", ret, value, ret, ret); } void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index d65a474f2..1bbd02022 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -232,15 +232,15 @@ void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b); void EmitFPNeg16(EmitContext& ctx, Register value); void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, ScalarRegister value); void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, Register value); -void EmitFPSin(EmitContext& ctx, ScalarF32 value); -void EmitFPCos(EmitContext& ctx, ScalarF32 value); -void EmitFPExp2(EmitContext& ctx, ScalarF32 value); -void EmitFPLog2(EmitContext& ctx, ScalarF32 value); -void EmitFPRecip32(EmitContext& ctx, ScalarF32 value); +void EmitFPSin(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPCos(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPExp2(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPLog2(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); +void EmitFPRecip32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPRecip64(EmitContext& ctx, Register value); -void EmitFPRecipSqrt32(EmitContext& ctx, ScalarF32 value); +void EmitFPRecipSqrt32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPRecipSqrt64(EmitContext& ctx, Register value); -void EmitFPSqrt(EmitContext& ctx, ScalarF32 value); +void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPSaturate16(EmitContext& ctx, Register value); void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPSaturate64(EmitContext& ctx, Register value); -- cgit v1.2.3 From c4fd6b55bc9acd06b2fc89f84fd175d78e14110a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 18:21:28 -0300 Subject: glasm: Implement shuffle and vote instructions on GLASM --- .../backend/glasm/emit_context.cpp | 17 +++ src/shader_recompiler/backend/glasm/emit_context.h | 2 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 6 ++ .../backend/glasm/emit_glasm_instructions.h | 28 ++--- .../backend/glasm/emit_glasm_not_implemented.cpp | 84 +-------------- .../backend/glasm/emit_glasm_warp.cpp | 118 +++++++++++++++++++++ 6 files changed, 158 insertions(+), 97 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 9f839f3bf..f9d83dd91 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -25,6 +25,23 @@ EmitContext::EmitContext(IR::Program& program) { if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); } + switch (program.stage) { + case Stage::VertexA: + case Stage::VertexB: + stage_name = "vertex"; + break; + case Stage::TessellationControl: + case Stage::TessellationEval: + case Stage::Geometry: + stage_name = "primitive"; + break; + case Stage::Fragment: + stage_name = "fragment"; + break; + case Stage::Compute: + stage_name = "compute"; + break; + } } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 37663c1c8..4efe42ada 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -45,6 +45,8 @@ public: std::string code; RegAlloc reg_alloc{*this}; + + std::string_view stage_name = "invalid"; }; } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index ad27b8b06..8b42cbf79 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -189,6 +189,12 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { header += "OPTION NV_shader_atomic_fp16_vector;"; } + if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask) { + header += "OPTION NV_shader_thread_group;"; + } + if (info.uses_subgroup_shuffles) { + header += "OPTION NV_shader_thread_shuffle;"; + } } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 1bbd02022..75613571f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -584,24 +584,24 @@ void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& ind ScalarU32 value); void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, ScalarU32 value); -void EmitLaneId(EmitContext& ctx); -void EmitVoteAll(EmitContext& ctx, ScalarS32 pred); -void EmitVoteAny(EmitContext& ctx, ScalarS32 pred); -void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred); -void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred); -void EmitSubgroupEqMask(EmitContext& ctx); -void EmitSubgroupLtMask(EmitContext& ctx); -void EmitSubgroupLeMask(EmitContext& ctx); -void EmitSubgroupGtMask(EmitContext& ctx); -void EmitSubgroupGeMask(EmitContext& ctx); +void EmitLaneId(EmitContext& ctx, IR::Inst& inst); +void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); +void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); +void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); +void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); +void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst); +void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst); +void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst); +void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst); +void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst); void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask); + const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask); + const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask); + const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask); + const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 85110bcc9..3c0a74e3c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -21,9 +21,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } -void EmitVoid(EmitContext& ctx) { - NotImplemented(); -} +void EmitVoid(EmitContext&) {} void EmitBranch(EmitContext& ctx) { NotImplemented(); @@ -636,84 +634,4 @@ void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value NotImplemented(); } -void EmitLaneId(EmitContext& ctx) { - NotImplemented(); -} - -void EmitVoteAll(EmitContext& ctx, ScalarS32 pred) { - NotImplemented(); -} - -void EmitVoteAny(EmitContext& ctx, ScalarS32 pred) { - NotImplemented(); -} - -void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred) { - NotImplemented(); -} - -void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred) { - NotImplemented(); -} - -void EmitSubgroupEqMask(EmitContext& ctx) { - NotImplemented(); -} - -void EmitSubgroupLtMask(EmitContext& ctx) { - NotImplemented(); -} - -void EmitSubgroupLeMask(EmitContext& ctx) { - NotImplemented(); -} - -void EmitSubgroupGtMask(EmitContext& ctx) { - NotImplemented(); -} - -void EmitSubgroupGeMask(EmitContext& ctx) { - NotImplemented(); -} - -void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask) { - NotImplemented(); -} - -void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask) { - NotImplemented(); -} - -void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask) { - NotImplemented(); -} - -void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, - ScalarU32 clamp, ScalarU32 segmentation_mask) { - NotImplemented(); -} - -void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle) { - NotImplemented(); -} - -void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a) { - NotImplemented(); -} - -void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a) { - NotImplemented(); -} - -void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a) { - NotImplemented(); -} - -void EmitDPdyCoarse(EmitContext& ctx, ScalarF32 op_a) { - NotImplemented(); -} - } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index e69de29bb..37eb577cd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -0,0 +1,118 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitLaneId(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,{}.threadid;", inst, ctx.stage_name); +} + +void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { + ctx.Add("TGALL.S {}.x,{};", inst, pred); +} + +void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { + ctx.Add("TGANY.S {}.x,{};", inst, pred); +} + +void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { + ctx.Add("TGEQ.S {}.x,{};", inst, pred); +} + +void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { + ctx.Add("TGBALLOT {}.x,{};", inst, pred); +} + +void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.U {},{}.threadeqmask;", inst, ctx.stage_name); +} + +void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.U {},{}.threadltmask;", inst, ctx.stage_name); +} + +void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.U {},{}.threadlemask;", inst, ctx.stage_name); +} + +void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.U {},{}.threadgtmask;", inst, ctx.stage_name); +} + +void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.U {},{}.threadgemask;", inst, ctx.stage_name); +} + +static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + const IR::Value& clamp, const IR::Value& segmentation_mask, + std::string_view op) { + std::string mask; + if (clamp.IsImmediate() && segmentation_mask.IsImmediate()) { + mask = fmt::to_string(clamp.U32() | (segmentation_mask.U32() << 8)); + } else { + mask = "RC"; + ctx.Add("BFI.U RC.x,{{5,8,0,0}},{},{};", + ScalarU32{ctx.reg_alloc.Consume(segmentation_mask)}, + ScalarU32{ctx.reg_alloc.Consume(clamp)}); + } + const Register value_ret{ctx.reg_alloc.Define(inst)}; + IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; + if (in_bounds) { + const Register bounds_ret{ctx.reg_alloc.Define(*in_bounds)}; + ctx.Add("SHF{}.U {},{},{},{};" + "MOV.U {}.x,{}.y;", + op, bounds_ret, value, index, mask, value_ret, bounds_ret); + in_bounds->Invalidate(); + } else { + ctx.Add("SHF{}.U {},{},{},{};" + "MOV.U {}.x,{}.y;", + op, value_ret, value, index, mask, value_ret, value_ret); + } +} + +void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + const IR::Value& clamp, const IR::Value& segmentation_mask) { + Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "IDX"); +} + +void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + const IR::Value& clamp, const IR::Value& segmentation_mask) { + Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "UP"); +} + +void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + const IR::Value& clamp, const IR::Value& segmentation_mask) { + Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "DOWN"); +} + +void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, + const IR::Value& clamp, const IR::Value& segmentation_mask) { + Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "XOR"); +} + +void EmitFSwizzleAdd(EmitContext&, ScalarF32, ScalarF32, ScalarU32) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitDPdxFine(EmitContext&, ScalarF32) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitDPdyFine(EmitContext&, ScalarF32) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitDPdxCoarse(EmitContext&, ScalarF32) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitDPdyCoarse(EmitContext&, ScalarF32) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 70fbede213bfadfc4015b3227e57fca34bea46eb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 19:20:15 -0300 Subject: glasm: Review all GLASM insts to be aware of register aliasing --- .../backend/glasm/emit_glasm_composite.cpp | 19 ++++++++-- .../backend/glasm/emit_glasm_floating_point.cpp | 8 ++--- .../backend/glasm/emit_glasm_integer.cpp | 42 +++++++++++++++------- .../backend/glasm/emit_glasm_select.cpp | 2 +- 4 files changed, 51 insertions(+), 20 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index 94dc5019d..22321f386 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp @@ -41,10 +41,23 @@ template void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object, u32 index, char type) { const Register ret{ctx.reg_alloc.Define(inst)}; - if (ret != composite) { - ctx.Add("MOV.{} {},{};", type, ret, composite); + const char swizzle{"xyzw"[index]}; + if (ret != composite && ret == object) { + // The object is aliased with the return value, so we have to use a temporary to insert + ctx.Add("MOV.{} RC,{};" + "MOV.{} RC.{},{};" + "MOV.{} {},RC;", + type, composite, type, swizzle, object, type, ret); + } else if (ret != composite) { + // The input composite is not aliased with the return value so we have to copy it before + // hand. But the insert object is not aliased with the return value, so we don't have to + // worry about that + ctx.Add("MOV.{} {},{};MOV.{},{}.{},{};", type, ret, composite, type, ret, swizzle, object); + } else { + // The return value is alised so we can just insert the object, it doesn't matter if it's + // aliased + ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object); } - ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], object); } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index 15db6618f..d2c324ad6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -38,9 +38,9 @@ template void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value, InputType max_value, std::string_view type) { // Call MAX first to properly clamp nan to min_value instead - ctx.Add("MAX.{} {}.x,{},{};" - "MIN.{} {}.x,{}.x,{};", - type, ret, min_value, value, type, ret, ret, max_value); + ctx.Add("MAX.{} RC.x,{},{};" + "MIN.{} {}.x,RC.x,{};", + type, min_value, value, type, ret, max_value); } } // Anonymous namespace @@ -159,7 +159,7 @@ void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Regis void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("RSQ {}.x,{};RCP {}.x,{}.x;", ret, value, ret, ret); + ctx.Add("RSQ RC.x,{};RCP {}.x,RC.x;", value, ret); } void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 2be91ccfd..15fd23356 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -87,20 +87,38 @@ void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert, ScalarS32 offset, ScalarS32 count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFI.S {},RC,{},{};", inst, insert, base); + const Register ret{ctx.reg_alloc.Define(inst)}; + if (count.type != Type::Register && offset.type != Type::Register) { + ctx.Add("BFI.S {},{{{},{},0,0}},{},{};", ret, count, offset, insert, base); + } else { + ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" + "BFI.S {},RC,{},{};", + count, offset, ret, insert, base); + } } void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset, ScalarS32 count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFE.S {},RC,{};", inst, base); + const Register ret{ctx.reg_alloc.Define(inst)}; + if (count.type != Type::Register && offset.type != Type::Register) { + ctx.Add("BFE.S {},{{{},{},0,0}},{};", ret, count, offset, base); + } else { + ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" + "BFE.S {},RC,{};", + count, offset, ret, base); + } } void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, ScalarU32 count) { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset); - ctx.Add("BFE.U {},RC,{};", inst, base); + const Register ret{ctx.reg_alloc.Define(inst)}; + if (count.type != Type::Register && offset.type != Type::Register) { + ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base); + } else { + ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};" + "BFE.U {},RC,{};", + count, offset, ret, base); + } } void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { @@ -141,16 +159,16 @@ void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) { void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.S {}.x,{},{};" - "MAX.S {}.x,{},{};", - ret, max, value, ret, ret, min); + ctx.Add("MIN.S RC.x,{},{};" + "MAX.S {}.x,RC.x,{};", + max, value, ret, min); } void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) { const Register ret{ctx.reg_alloc.Define(inst)}; - ctx.Add("MIN.U {}.x,{},{};" - "MAX.U {}.x,{},{};", - ret, max, value, ret, ret, min); + ctx.Add("MIN.U RC.x,{},{};" + "MAX.U {}.x,RC.x,{};", + max, value, ret, min); } void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index cfde86047..b9e5cbbbe 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -43,7 +43,7 @@ void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, Register tr cond, ret, true_value); } else { ctx.Add("MOV.S.CC RC.x,{};" - "MOV.U64 {}.x(EQ.x),{};" + "MOV.U64 {}.x,{};" "MOV.U64 {}.x(NE.x),{};", cond, ret, false_value, ret, true_value); } -- cgit v1.2.3 From c917290497b313abe2f9ad6983050703615b1888 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 19:20:44 -0300 Subject: glasm: Enable unintentionally disabled register aliasing on GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 27 +++++++++------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8b42cbf79..c90b80e48 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -29,9 +29,9 @@ struct FuncTraits { template struct Identity { - Identity(const T& data_) : data{data_} {} + Identity(T data_) : data{data_} {} - const T& Extract() { + T Extract() { return data; } @@ -71,15 +71,12 @@ public: } } - ~RegWrapper() { + auto Extract() { if (inst) { reg_alloc.Unref(*inst); } else { reg_alloc.FreeReg(reg); } - } - - auto Extract() { return std::conditional_t{Value{reg}}; } @@ -95,13 +92,10 @@ public: ValueWrapper(EmitContext& ctx, const IR::Value& ir_value_) : reg_alloc{ctx.reg_alloc}, ir_value{ir_value_}, value{reg_alloc.Peek(ir_value)} {} - ~ValueWrapper() { + ArgType Extract() { if (!ir_value.IsImmediate()) { reg_alloc.Unref(*ir_value.InstRecursive()); } - } - - ArgType Extract() { return value; } @@ -120,7 +114,7 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) { } else if constexpr (std::is_base_of_v) { return ValueWrapper{ctx, arg}; } else if constexpr (std::is_same_v) { - return Identity{arg}; + return Identity{arg}; } else if constexpr (std::is_same_v) { return Identity{arg.U32()}; } else if constexpr (std::is_same_v) { @@ -137,9 +131,9 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) { template void InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) { if constexpr (is_first_arg_inst) { - func(ctx, *inst, std::forward(args.Extract())...); + func(ctx, *inst, args.Extract()...); } else { - func(ctx, std::forward(args.Extract())...); + func(ctx, args.Extract()...); } } @@ -147,10 +141,11 @@ template void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence) { using Traits = FuncTraits; if constexpr (is_first_arg_inst) { - func(ctx, *inst, - Arg>(ctx, inst->Arg(I)).Extract()...); + InvokeCall( + ctx, inst, Arg>(ctx, inst->Arg(I))...); } else { - func(ctx, Arg>(ctx, inst->Arg(I)).Extract()...); + InvokeCall( + ctx, inst, Arg>(ctx, inst->Arg(I))...); } } -- cgit v1.2.3 From 8c81a20ace8c65d0a9d58b9cf333049a2bc0383a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 10 May 2021 19:32:10 -0300 Subject: glasm: Ensure reg alloc order across compilers on GLASM Use a struct constructor to serialize register allocation arguments to ensure registers are allocated in the same order regardless of the compiler used. The A and B functions can be called in any order when passed as arguments to "foo": foo(A(), B()) But the order is guaranteed for curly-braced constructor calls in classes: Foo{A(), B()} Use this to get consistent behavior. --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index c90b80e48..047b2f89c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -128,24 +128,27 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) { } } -template -void InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) { - if constexpr (is_first_arg_inst) { - func(ctx, *inst, args.Extract()...); - } else { - func(ctx, args.Extract()...); +template +struct InvokeCall { + template + InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) { + if constexpr (is_first_arg_inst) { + func(ctx, *inst, args.Extract()...); + } else { + func(ctx, args.Extract()...); + } } -} +}; template void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence) { using Traits = FuncTraits; if constexpr (is_first_arg_inst) { - InvokeCall( - ctx, inst, Arg>(ctx, inst->Arg(I))...); + InvokeCall{ + ctx, inst, Arg>(ctx, inst->Arg(I))...}; } else { - InvokeCall( - ctx, inst, Arg>(ctx, inst->Arg(I))...); + InvokeCall{ + ctx, inst, Arg>(ctx, inst->Arg(I))...}; } } -- cgit v1.2.3 From 7ff5851608031baca2adceb9f72e7c75eda9b3a9 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Mon, 10 May 2021 22:35:16 -0400 Subject: glasm: Implement Storage atomics StorageAtomicExchangeU64 is failing test seemingly due to failure storing 64-bit result into the register --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 7 ++ .../backend/glasm/emit_glasm_atomic.cpp | 60 ++++++++++++++ .../backend/glasm/emit_glasm_instructions.h | 38 ++++++--- .../backend/glasm/emit_glasm_not_implemented.cpp | 96 ---------------------- .../backend/glasm/emit_glasm_shared_memory.cpp | 64 +++++++++++++++ 5 files changed, 156 insertions(+), 109 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 047b2f89c..056d8cbf8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -193,6 +193,9 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_subgroup_shuffles) { header += "OPTION NV_shader_thread_shuffle;"; } + // TODO: Track the shared atomic ops + header += + "OPTION NV_shader_storage_buffer;OPTION NV_gpu_program_fp64;OPTION NV_bindless_texture;"; } } // Anonymous namespace @@ -214,6 +217,10 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { default: break; } + if (program.shared_memory_size > 0) { + header += fmt::format("SHARED_MEMORY {};", program.shared_memory_size); + header += fmt::format("SHARED shared_mem[]={{program.sharedmem}};"); + } header += "TEMP "; for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) { header += fmt::format("R{},", index); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp index fe44c3d15..e72b252a3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp @@ -35,6 +35,66 @@ void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 } } // namespace +void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.ADD.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value) { + ctx.Add("ATOMS.MIN.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.MIN.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value) { + ctx.Add("ATOMS.MAX.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.MAX.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.IWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.DWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.AND.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.OR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.XOR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.EXCH.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + Register value) { + ctx.LongAdd("ATOMS.EXCH.U64 {}.x,{},shared_mem[{}];", inst, value, pointer_offset); +} + void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, ScalarU32 value) { Atom(ctx, inst, binding, offset, value, "ADD", "U32"); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 75613571f..8202354fe 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -129,7 +129,7 @@ void EmitLoadSharedS8(EmitContext& ctx, ScalarU32 offset); void EmitLoadSharedU16(EmitContext& ctx, ScalarU32 offset); void EmitLoadSharedS16(EmitContext& ctx, ScalarU32 offset); void EmitLoadSharedU32(EmitContext& ctx, ScalarU32 offset); -void EmitLoadSharedU64(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU64(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); void EmitLoadSharedU128(EmitContext& ctx, ScalarU32 offset); void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); @@ -345,18 +345,30 @@ void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs); void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs); -void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicSMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value); -void EmitSharedAtomicUMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicSMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value); -void EmitSharedAtomicUMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicInc32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicDec32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicAnd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicOr32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicXor32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicExchange32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value); -void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Register value); +void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value); +void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value); +void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value); +void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + Register value); void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, ScalarU32 value); void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 3c0a74e3c..b40d09f8c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -199,54 +199,6 @@ void EmitUndefU64(EmitContext& ctx) { NotImplemented(); } -void EmitLoadSharedU8(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedS8(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedU16(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedS16(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedU32(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedU64(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitLoadSharedU128(EmitContext& ctx, ScalarU32 offset) { - NotImplemented(); -} - -void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitWriteSharedU32(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitWriteSharedU64(EmitContext& ctx, ScalarU32 offset, Register value) { - NotImplemented(); -} - -void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value) { - NotImplemented(); -} - void EmitGetZeroFromOp(EmitContext& ctx) { NotImplemented(); } @@ -271,54 +223,6 @@ void EmitGetInBoundsFromOp(EmitContext& ctx) { NotImplemented(); } -void EmitSharedAtomicIAdd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicSMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value) { - NotImplemented(); -} - -void EmitSharedAtomicUMin32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicSMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarS32 value) { - NotImplemented(); -} - -void EmitSharedAtomicUMax32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicInc32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicDec32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicAnd32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicOr32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicXor32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicExchange32(EmitContext& ctx, ScalarU32 pointer_offset, ScalarU32 value) { - NotImplemented(); -} - -void EmitSharedAtomicExchange64(EmitContext& ctx, ScalarU32 pointer_offset, Register value) { - NotImplemented(); -} - void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { ctx.Add("OR.S {},{},{};", inst, a, b); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp index e69de29bb..32cc5d92c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp @@ -0,0 +1,64 @@ + +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { +void EmitLoadSharedU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadSharedS8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadSharedU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadSharedS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadSharedU32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitLoadSharedU64([[maybe_unused]] EmitContext& ctx, IR::Inst& inst, + [[maybe_unused]] ScalarU32 offset) { + ctx.LongAdd("LDS.U64 {},shared_mem[{}];", inst, offset); +} + +void EmitLoadSharedU128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteSharedU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteSharedU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitWriteSharedU32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] ScalarU32 value) { + ctx.Add("STS.U32 {},shared_mem[{}];", value, offset); +} + +void EmitWriteSharedU64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] Register value) { + ctx.Add("STS.U64 {},shared_mem[{}];", value, offset); +} + +void EmitWriteSharedU128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, + [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} +} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From d54d7de40e7295827b0e4e4026441b53d3fc9569 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 14 May 2021 00:40:54 -0300 Subject: glasm: Rework control flow introducing a syntax list This commit regresses VertexA shaders, their transformation pass has to be adapted to the new control flow. --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 41 ++++++++++++++++++---- .../backend/glasm/emit_glasm_instructions.h | 7 +--- .../backend/glasm/emit_glasm_integer.cpp | 9 +++-- .../backend/glasm/emit_glasm_not_implemented.cpp | 24 +------------ 4 files changed, 42 insertions(+), 39 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 056d8cbf8..51ca83d18 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -117,8 +117,6 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) { return Identity{arg}; } else if constexpr (std::is_same_v) { return Identity{arg.U32()}; - } else if constexpr (std::is_same_v) { - return Identity{arg.Label()}; } else if constexpr (std::is_same_v) { return Identity{arg.Attribute()}; } else if constexpr (std::is_same_v) { @@ -177,6 +175,39 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { throw LogicError("Invalid opcode {}", inst->GetOpcode()); } +void EmitCode(EmitContext& ctx, const IR::Program& program) { + const auto eval{ + [&](const IR::U1& cond) { return ScalarS32{ctx.reg_alloc.Consume(IR::Value{cond})}; }}; + for (const IR::AbstractSyntaxNode& node : program.syntax_list) { + switch (node.type) { + case IR::AbstractSyntaxNode::Type::Block: + for (IR::Inst& inst : node.block->Instructions()) { + EmitInst(ctx, &inst); + } + break; + case IR::AbstractSyntaxNode::Type::If: + ctx.Add("MOV.S.CC RC,{};IF NE.x;", eval(node.if_node.cond)); + break; + case IR::AbstractSyntaxNode::Type::EndIf: + ctx.Add("ENDIF;"); + break; + case IR::AbstractSyntaxNode::Type::Loop: + ctx.Add("REP;"); + break; + case IR::AbstractSyntaxNode::Type::Repeat: + ctx.Add("MOV.S.CC RC,{};BRK NE.x;ENDREP;", eval(node.repeat.cond)); + break; + case IR::AbstractSyntaxNode::Type::Break: + ctx.Add("MOV.S.CC RC,{};BRK NE.x;", eval(node.repeat.cond)); + break; + case IR::AbstractSyntaxNode::Type::Return: + case IR::AbstractSyntaxNode::Type::Unreachable: + ctx.Add("RET;"); + break; + } + } +} + void SetupOptions(std::string& header, Info info) { if (info.uses_int64_bit_atomics) { header += "OPTION NV_shader_atomic_int64;"; @@ -201,11 +232,7 @@ void SetupOptions(std::string& header, Info info) { std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { EmitContext ctx{program}; - for (IR::Block* const block : program.blocks) { - for (IR::Inst& inst : block->Instructions()) { - EmitInst(ctx, &inst); - } - } + EmitCode(ctx, program); std::string header = "!!NVcp5.0\n" "OPTION NV_internal;"; SetupOptions(header, program.info); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 8202354fe..0f7f16e6e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -22,13 +22,8 @@ class EmitContext; void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitBranch(EmitContext& ctx); -void EmitBranchConditional(EmitContext& ctx); -void EmitLoopMerge(EmitContext& ctx); -void EmitSelectionMerge(EmitContext& ctx); -void EmitReturn(EmitContext& ctx); +void EmitBranchConditionRef(EmitContext&); void EmitJoin(EmitContext& ctx); -void EmitUnreachable(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 15fd23356..adcc0404b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -91,7 +91,8 @@ void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scalar if (count.type != Type::Register && offset.type != Type::Register) { ctx.Add("BFI.S {},{{{},{},0,0}},{},{};", ret, count, offset, insert, base); } else { - ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" + ctx.Add("MOV.S RC.x,{};" + "MOV.S RC.y,{};" "BFI.S {},RC,{},{};", count, offset, ret, insert, base); } @@ -103,7 +104,8 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scal if (count.type != Type::Register && offset.type != Type::Register) { ctx.Add("BFE.S {},{{{},{},0,0}},{};", ret, count, offset, base); } else { - ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" + ctx.Add("MOV.S RC.x,{};" + "MOV.S RC.y,{};" "BFE.S {},RC,{};", count, offset, ret, base); } @@ -115,7 +117,8 @@ void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, Scal if (count.type != Type::Register && offset.type != Type::Register) { ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base); } else { - ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};" + ctx.Add("MOV.U RC.x,{};" + "MOV.U RC.y,{};" "BFE.U {},RC,{};", count, offset, ret, base); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index b40d09f8c..f37ad5587 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -23,34 +23,12 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst) { void EmitVoid(EmitContext&) {} -void EmitBranch(EmitContext& ctx) { - NotImplemented(); -} - -void EmitBranchConditional(EmitContext& ctx) { - NotImplemented(); -} - -void EmitLoopMerge(EmitContext& ctx) { - NotImplemented(); -} - -void EmitSelectionMerge(EmitContext& ctx) { - NotImplemented(); -} - -void EmitReturn(EmitContext& ctx) { - ctx.Add("RET;"); -} +void EmitBranchConditionRef(EmitContext&) {} void EmitJoin(EmitContext& ctx) { NotImplemented(); } -void EmitUnreachable(EmitContext& ctx) { - NotImplemented(); -} - void EmitDemoteToHelperInvocation(EmitContext& ctx) { NotImplemented(); } -- cgit v1.2.3 From d4385c34e3aee6718502a1c5bc814535a657dc4f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 14 May 2021 02:09:33 -0300 Subject: glasm: Declare NV_shader_thread_group when needed --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 51ca83d18..fa48ba25c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -218,15 +218,16 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { header += "OPTION NV_shader_atomic_fp16_vector;"; } - if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask) { + if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote) { header += "OPTION NV_shader_thread_group;"; } if (info.uses_subgroup_shuffles) { header += "OPTION NV_shader_thread_shuffle;"; } // TODO: Track the shared atomic ops - header += - "OPTION NV_shader_storage_buffer;OPTION NV_gpu_program_fp64;OPTION NV_bindless_texture;"; + header += "OPTION NV_shader_storage_buffer;" + "OPTION NV_gpu_program_fp64;" + "OPTION NV_bindless_texture;"; } } // Anonymous namespace -- cgit v1.2.3 From 0f88fb5d72401e87b2d33aab5fad7cc2a0002fc3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 14 May 2021 02:10:03 -0300 Subject: glasm: Write result to scalar on integer comparison instructions --- .../backend/glasm/emit_glasm_integer.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index adcc0404b..1befeca91 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -175,43 +175,43 @@ void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 m } void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SLT.S {},{},{};", inst, lhs, rhs); + ctx.Add("SLT.S {}.x,{},{};", inst, lhs, rhs); } void EmitULessThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { - ctx.Add("SLT.U {},{},{};", inst, lhs, rhs); + ctx.Add("SLT.U {}.x,{},{};", inst, lhs, rhs); } void EmitIEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SEQ.S {},{},{};", inst, lhs, rhs); + ctx.Add("SEQ.S {}.x,{},{};", inst, lhs, rhs); } void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SLE.S {},{},{};", inst, lhs, rhs); + ctx.Add("SLE.S {}.x,{},{};", inst, lhs, rhs); } void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { - ctx.Add("SLE.U {},{},{};", inst, lhs, rhs); + ctx.Add("SLE.U {}.x,{},{};", inst, lhs, rhs); } void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SGT.S {},{},{};", inst, lhs, rhs); + ctx.Add("SGT.S {}.x,{},{};", inst, lhs, rhs); } void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { - ctx.Add("SGT.U {},{},{};", inst, lhs, rhs); + ctx.Add("SGT.U {}.x,{},{};", inst, lhs, rhs); } void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SNE.U {},{},{};", inst, lhs, rhs); + ctx.Add("SNE.U {}.x,{},{};", inst, lhs, rhs); } void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) { - ctx.Add("SGE.S {},{},{};", inst, lhs, rhs); + ctx.Add("SGE.S {}.x,{},{};", inst, lhs, rhs); } void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, ScalarU32 lhs, ScalarU32 rhs) { - ctx.Add("SGE.U {},{},{};", inst, lhs, rhs); + ctx.Add("SGE.U {}.x,{},{};", inst, lhs, rhs); } } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From bf5e48ffe4bd48ea681f2a01c8919c97125e88df Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 14 May 2021 04:48:46 -0300 Subject: glasm: Initial implementation of phi nodes on GLASM --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 59 ++++++++++++++++++++-- .../backend/glasm/emit_glasm_instructions.h | 3 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 27 ++++++++-- 3 files changed, 81 insertions(+), 8 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index fa48ba25c..775dd9e7e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include @@ -9,6 +10,7 @@ #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/profile.h" @@ -175,6 +177,34 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { throw LogicError("Invalid opcode {}", inst->GetOpcode()); } +void Precolor(EmitContext& ctx, const IR::Program& program) { + for (IR::Block* const block : program.blocks) { + for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { + switch (phi.Arg(0).Type()) { + case IR::Type::U1: + case IR::Type::U32: + case IR::Type::F32: + ctx.reg_alloc.Define(phi); + break; + case IR::Type::U64: + case IR::Type::F64: + ctx.reg_alloc.LongDefine(phi); + break; + default: + throw NotImplementedException("Phi node type {}", phi.Type()); + } + const size_t num_args{phi.NumArgs()}; + for (size_t i = 0; i < num_args; ++i) { + IR::IREmitter{*phi.PhiBlock(i)}.PhiMove(phi, phi.Arg(i)); + } + // Add reference to the phi node on the phi predecessor to avoid overwritting it + for (size_t i = 0; i < num_args; ++i) { + IR::IREmitter{*phi.PhiBlock(i)}.DummyReference(IR::Value{&phi}); + } + } + } +} + void EmitCode(EmitContext& ctx, const IR::Program& program) { const auto eval{ [&](const IR::U1& cond) { return ScalarS32{ctx.reg_alloc.Consume(IR::Value{cond})}; }}; @@ -186,7 +216,9 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } break; case IR::AbstractSyntaxNode::Type::If: - ctx.Add("MOV.S.CC RC,{};IF NE.x;", eval(node.if_node.cond)); + ctx.Add("MOV.S.CC RC,{};" + "IF NE.x;", + eval(node.if_node.cond)); break; case IR::AbstractSyntaxNode::Type::EndIf: ctx.Add("ENDIF;"); @@ -195,10 +227,30 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { ctx.Add("REP;"); break; case IR::AbstractSyntaxNode::Type::Repeat: - ctx.Add("MOV.S.CC RC,{};BRK NE.x;ENDREP;", eval(node.repeat.cond)); + if (node.repeat.cond.IsImmediate()) { + if (node.repeat.cond.U1()) { + ctx.Add("ENDREP;"); + } else { + ctx.Add("BRK;" + "ENDREP;"); + } + } else { + ctx.Add("MOV.S.CC RC,{};" + "BRK (EQ.x);" + "ENDREP;", + eval(node.repeat.cond)); + } break; case IR::AbstractSyntaxNode::Type::Break: - ctx.Add("MOV.S.CC RC,{};BRK NE.x;", eval(node.repeat.cond)); + if (node.break_node.cond.IsImmediate()) { + if (node.break_node.cond.U1()) { + ctx.Add("BRK;"); + } + } else { + ctx.Add("MOV.S.CC RC,{};" + "BRK (NE.x);", + eval(node.break_node.cond)); + } break; case IR::AbstractSyntaxNode::Type::Return: case IR::AbstractSyntaxNode::Type::Unreachable: @@ -233,6 +285,7 @@ void SetupOptions(std::string& header, Info info) { std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { EmitContext ctx{program}; + Precolor(ctx, program); EmitCode(ctx, program); std::string header = "!!NVcp5.0\n" "OPTION NV_internal;"; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 0f7f16e6e..a74e422d6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -22,7 +22,8 @@ class EmitContext; void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitBranchConditionRef(EmitContext&); +void EmitDummyReference(EmitContext&); +void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value); void EmitJoin(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); void EmitBarrier(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index f37ad5587..969b91a81 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -17,13 +17,32 @@ namespace Shader::Backend::GLASM { #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) -void EmitPhi(EmitContext& ctx, IR::Inst& inst) { - NotImplemented(); -} +void EmitPhi(EmitContext&, IR::Inst&) {} void EmitVoid(EmitContext&) {} -void EmitBranchConditionRef(EmitContext&) {} +void EmitDummyReference(EmitContext&) {} + +void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { + if (phi == value) { + return; + } + const Register phi_reg{ctx.reg_alloc.Consume(phi)}; + const Value eval_value{ctx.reg_alloc.Consume(value)}; + switch (phi.InstRecursive()->Arg(0).Type()) { + case IR::Type::U1: + case IR::Type::U32: + case IR::Type::F32: + ctx.Add("MOV.S {}.x,{};", phi_reg, ScalarS32{eval_value}); + break; + case IR::Type::U64: + case IR::Type::F64: + ctx.Add("MOV.U64 {}.x,{};", phi_reg, ScalarRegister{eval_value}); + break; + default: + throw NotImplementedException("Phi node type {}", phi.Type()); + } +} void EmitJoin(EmitContext& ctx) { NotImplemented(); -- cgit v1.2.3 From 057dee48562b0cce69b1fa8bdb02bc0367852b4d Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Fri, 14 May 2021 21:18:53 -0400 Subject: glasm: Implement local memory for glasm --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 +++ .../backend/glasm/emit_glasm_context_get_set.cpp | 8 ++++++++ src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 8 -------- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 775dd9e7e..0b70bf3f6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -306,6 +306,9 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) { header += fmt::format("R{},", index); } + if (program.local_memory_size > 0) { + header += fmt::format("lmem[{}],", program.local_memory_size); + } header += "RC;" "LONG TEMP "; for (size_t index = 0; index < ctx.reg_alloc.NumUsedLongRegisters(); ++index) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index fed79e381..de0be7aed 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -113,4 +113,12 @@ void EmitSetFragDepth([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Scalar throw NotImplementedException("GLASM instruction"); } +void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset) { + ctx.Add("MOV.U {},lmem[{}].x;", inst, word_offset); +} + +void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value) { + ctx.Add("MOV.U lmem[{}].x,{};", word_offset, value); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index a74e422d6..e7af8fa88 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -71,7 +71,7 @@ void EmitInvocationId(EmitContext& ctx); void EmitSampleId(EmitContext& ctx); void EmitIsHelperInvocation(EmitContext& ctx); void EmitYDirection(EmitContext& ctx); -void EmitLoadLocal(EmitContext& ctx, ScalarU32 word_offset); +void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset); void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value); void EmitUndefU1(EmitContext& ctx); void EmitUndefU8(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 969b91a81..ae1735c8f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -168,14 +168,6 @@ void EmitYDirection(EmitContext& ctx) { NotImplemented(); } -void EmitLoadLocal(EmitContext& ctx, ScalarU32 word_offset) { - NotImplemented(); -} - -void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value) { - NotImplemented(); -} - void EmitUndefU1(EmitContext& ctx) { NotImplemented(); } -- cgit v1.2.3 From 3764750339fa60f2d79cf3abe1b91ca42ba61401 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 18:14:29 -0300 Subject: glasm: Add graphics specific shader declarations to GLASM --- .../backend/glasm/emit_context.cpp | 37 ++++++++++++++++++++++ src/shader_recompiler/backend/glasm/emit_glasm.cpp | 32 +++++++++++++++---- 2 files changed, 63 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index f9d83dd91..66c954ff6 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -2,10 +2,25 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/frontend/ir/program.h" namespace Shader::Backend::GLASM { +namespace { +std::string_view InterpDecorator(Interpolation interp) { + switch (interp) { + case Interpolation::Smooth: + return ""; + case Interpolation::Flat: + return "FLAT "; + case Interpolation::NoPerspective: + return "NOPERSPECTIVE "; + } + throw InvalidArgument("Invalid interpolation {}", interp); +} +} // Anonymous namespace EmitContext::EmitContext(IR::Program& program) { // FIXME: Temporary partial implementation @@ -42,6 +57,28 @@ EmitContext::EmitContext(IR::Program& program) { stage_name = "compute"; break; } + for (size_t index = 0; index < program.info.input_generics.size(); ++index) { + const auto& generic{program.info.input_generics[index]}; + if (generic.used) { + Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", + InterpDecorator(generic.interpolation), index, stage_name, index, index); + } + } + for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { + if (!program.info.stores_frag_color[index]) { + continue; + } + if (index == 0) { + Add("OUTPUT frag_color0=result.color;"); + } else { + Add("OUTPUT frag_color{}[]=result.color[{}];", index, index); + } + } + for (size_t index = 0; index < program.info.stores_generics.size(); ++index) { + if (program.info.stores_generics[index]) { + Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); + } + } } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0b70bf3f6..ab6790ce8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -261,6 +261,12 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } void SetupOptions(std::string& header, Info info) { + // TODO: Track the shared atomic ops + header += "OPTION NV_internal;" + "OPTION NV_shader_storage_buffer;" + "OPTION NV_gpu_program_fp64;" + "OPTION NV_bindless_texture;" + "OPTION ARB_derivative_control;"; if (info.uses_int64_bit_atomics) { header += "OPTION NV_shader_atomic_int64;"; } @@ -276,10 +282,25 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_subgroup_shuffles) { header += "OPTION NV_shader_thread_shuffle;"; } - // TODO: Track the shared atomic ops - header += "OPTION NV_shader_storage_buffer;" - "OPTION NV_gpu_program_fp64;" - "OPTION NV_bindless_texture;"; +} + +std::string_view StageHeader(Stage stage) { + switch (stage) { + case Stage::VertexA: + case Stage::VertexB: + return "!!NVvp5.0\n"; + case Stage::TessellationControl: + return "!!NVtcs5.0\n"; + case Stage::TessellationEval: + return "!!NVtes5.0\n"; + case Stage::Geometry: + return "!!NVgp5.0\n"; + case Stage::Fragment: + return "!!NVfp5.0\n"; + case Stage::Compute: + return "!!NVcp5.0\n"; + } + throw InvalidArgument("Invalid stage {}", stage); } } // Anonymous namespace @@ -287,8 +308,7 @@ std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { EmitContext ctx{program}; Precolor(ctx, program); EmitCode(ctx, program); - std::string header = "!!NVcp5.0\n" - "OPTION NV_internal;"; + std::string header{StageHeader(program.stage)}; SetupOptions(header, program.info); switch (program.stage) { case Stage::Compute: -- cgit v1.2.3 From 31d402ee74d7f7045aec7e748fdee489a434db6b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 18:15:13 -0300 Subject: glasm: Add Void type to GLASM values --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 1 + src/shader_recompiler/backend/glasm/reg_alloc.cpp | 3 +++ src/shader_recompiler/backend/glasm/reg_alloc.h | 11 +++++++++++ 3 files changed, 15 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index ab6790ce8..e5c96eb7f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -54,6 +54,7 @@ public: } switch (value.type) { case Type::Register: + case Type::Void: break; case Type::U32: ctx.Add("MOV.U {}.x,{};", reg, value.imm_u32); diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index f556f3aee..0e38f467f 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -57,6 +57,9 @@ void RegAlloc::FreeReg(Register reg) { Value RegAlloc::MakeImm(const IR::Value& value) { Value ret; switch (value.Type()) { + case IR::Type::Void: + ret.type = Type::Void; + break; case IR::Type::U1: ret.type = Type::U32; ret.imm_u32 = value.U1() ? 0xffffffff : 0; diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 5742436cf..ede6edd1f 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -23,6 +23,7 @@ namespace Shader::Backend::GLASM { class EmitContext; enum class Type : u32 { + Void, Register, U32, S32, @@ -65,6 +66,8 @@ struct Value { return false; } switch (type) { + case Type::Void: + return true; case Type::Register: return id == rhs.id; case Type::U32: @@ -218,6 +221,8 @@ struct fmt::formatter { template auto format(const Shader::Backend::GLASM::ScalarU32& value, FormatContext& ctx) { switch (value.type) { + case Shader::Backend::GLASM::Type::Void: + break; case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: @@ -242,6 +247,8 @@ struct fmt::formatter { template auto format(const Shader::Backend::GLASM::ScalarS32& value, FormatContext& ctx) { switch (value.type) { + case Shader::Backend::GLASM::Type::Void: + break; case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: @@ -266,6 +273,8 @@ struct fmt::formatter { template auto format(const Shader::Backend::GLASM::ScalarF32& value, FormatContext& ctx) { switch (value.type) { + case Shader::Backend::GLASM::Type::Void: + break; case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: @@ -290,6 +299,8 @@ struct fmt::formatter { template auto format(const Shader::Backend::GLASM::ScalarF64& value, FormatContext& ctx) { switch (value.type) { + case Shader::Backend::GLASM::Type::Void: + break; case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: -- cgit v1.2.3 From 1f3446b47e2945d2a7a18082e21bc417156c91d3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 18:15:50 -0300 Subject: glasm: Implement some graphics instructions on GLASM --- .../backend/glasm/emit_glasm_context_get_set.cpp | 9 ++++----- .../backend/glasm/emit_glasm_not_implemented.cpp | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index de0be7aed..2de7fb9cc 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -54,7 +54,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; const u32 element{IR::GenericAttributeElement(attr)}; - ctx.Add("MOV.F {}.x,in_attr{}.{};", inst, index, "xyzw"[element]); + ctx.Add("MOV.F {}.x,in_attr{}[0].{};", inst, index, "xyzw"[element]); return; } throw NotImplementedException("Get attribute {}", attr); @@ -66,7 +66,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, const char swizzle{"xyzw"[element]}; if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - ctx.Add("MOV.F out_attr{}.{},{};", index, swizzle, value); + ctx.Add("MOV.F out_attr{}[0].{},{};", index, swizzle, value); return; } switch (attr) { @@ -100,9 +100,8 @@ void EmitSetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch throw NotImplementedException("GLASM instruction"); } -void EmitSetFragColor([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] u32 index, - [[maybe_unused]] u32 component, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value) { + ctx.Add("MOV.F frag_color{}.{},{};", index, "xyzw"[component], value); } void EmitSetSampleMask([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index ae1735c8f..388b7eb02 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -49,7 +49,7 @@ void EmitJoin(EmitContext& ctx) { } void EmitDemoteToHelperInvocation(EmitContext& ctx) { - NotImplemented(); + ctx.Add("KIL TR.x;"); } void EmitBarrier(EmitContext& ctx) { -- cgit v1.2.3 From 9fb2ea08e84f7194136f5a2f320dd3de04e8ca5d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 18:16:39 -0300 Subject: glasm: Initial (broken) implementation of TEX on GLASM --- .../backend/glasm/emit_glasm_image.cpp | 221 +++++++++++++++ .../backend/glasm/emit_glasm_image_atomic.cpp | 165 ++++++++++++ .../backend/glasm/emit_glasm_not_implemented.cpp | 299 --------------------- 3 files changed, 386 insertions(+), 299 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index e69de29bb..a32d01925 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -0,0 +1,221 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/modifiers.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitBindlessImageSampleImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGather(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGatherDref(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageFetch(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageQueryDimensions(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageQueryLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGradient(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageRead(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageWrite(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleDrefImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleDrefExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGather(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGatherDref(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageFetch(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageQueryDimensions(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageQueryLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGradient(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageRead(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageWrite(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, + [[maybe_unused]] const IR::Value& index) { + // FIXME + return fmt::format("texture[{}]", info.descriptor_index); +} + +void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + Register coords, Register bias_lc, + [[maybe_unused]] const IR::Value& offset) { + const auto info{inst.Flags()}; + const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const std::string_view op{info.has_bias ? "TXB" : "TEX"}; + const std::string_view lod_clamp{info.has_lod_clamp ? ".LODCLAMP" : ""}; + const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; + const std::string texture{Texture(ctx, info, index)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + // FIXME + const bool separate{info.type == TextureType::ColorArrayCube}; + if (separate) { + ctx.Add("{}.F{}{} {},{},{},{},2D;", op, lod_clamp, sparse_mod, ret, coords, bias_lc, + texture); + } else { + ctx.Add("MOV.F {}.w,{}.x;" + "{}.F{}{} {},{},{},2D;", + coords, bias_lc, op, lod_clamp, sparse_mod, ret, coords, texture); + } + if (sparse_inst) { + const Register sparse_ret{ctx.reg_alloc.Define(*sparse_inst)}; + ctx.Add("MOV.S {},-1;" + "MOV.S {}(NONRESIDENT),0;", + sparse_ret, sparse_ret); + sparse_inst->Invalidate(); + } +} + +void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] Register lod_lc, + [[maybe_unused]] const IR::Value& offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, + [[maybe_unused]] Register dref, + [[maybe_unused]] Register bias_lc, + [[maybe_unused]] const IR::Value& offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx, + [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, + [[maybe_unused]] Register dref, + [[maybe_unused]] Register lod_lc, + [[maybe_unused]] const IR::Value& offset) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& offset, + [[maybe_unused]] const IR::Value& offset2) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& offset, + [[maybe_unused]] const IR::Value& offset2, + [[maybe_unused]] Register dref) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] Register offset, [[maybe_unused]] Register lod, + [[maybe_unused]] Register ms) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageQueryDimensions([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register lod) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageQueryLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] Register derivates, [[maybe_unused]] Register offset, + [[maybe_unused]] Register lod_clamp) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] Register color) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp index e69de29bb..a0b9866de 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp @@ -0,0 +1,165 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "shader_recompiler/backend/glasm/emit_context.h" +#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/value.h" + +namespace Shader::Backend::GLASM { + +void EmitBindlessImageAtomicIAdd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicSMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicUMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicSMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicUMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicInc32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicDec32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicAnd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicOr32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicXor32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicExchange32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicIAdd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicSMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicUMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicSMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicUMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicInc32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicDec32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicAnd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicOr32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicXor32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicExchange32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitImageAtomicIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicInc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicDec32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicExchange32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 388b7eb02..a4c1ca481 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -228,303 +228,4 @@ void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("SEQ.S {},{},0;", inst, value); } -void EmitBindlessImageSampleImplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageSampleExplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageGather(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageGatherDref(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageFetch(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageQueryDimensions(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageQueryLod(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageGradient(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageRead(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageWrite(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageSampleImplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageSampleExplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageSampleDrefImplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageSampleDrefExplicitLod(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageGather(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageGatherDref(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageFetch(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageQueryDimensions(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageQueryLod(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageGradient(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageRead(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageWrite(EmitContext&) { - NotImplemented(); -} - -void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register bias_lc, const IR::Value& offset) { - NotImplemented(); -} - -void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register lod_lc, const IR::Value& offset) { - NotImplemented(); -} - -void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register dref, Register bias_lc, - const IR::Value& offset) { - NotImplemented(); -} - -void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register dref, Register lod_lc, - const IR::Value& offset) { - NotImplemented(); -} - -void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - const IR::Value& offset, const IR::Value& offset2) { - NotImplemented(); -} - -void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - const IR::Value& offset, const IR::Value& offset2, Register dref) { - NotImplemented(); -} - -void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - Register offset, Register lod, Register ms) { - NotImplemented(); -} - -void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register lod) { - NotImplemented(); -} - -void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords) { - NotImplemented(); -} - -void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - Register derivates, Register offset, Register lod_clamp) { - NotImplemented(); -} - -void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords) { - NotImplemented(); -} - -void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - Register color) { - NotImplemented(); -} - -void EmitBindlessImageAtomicIAdd32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicSMin32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicUMin32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicSMax32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicUMax32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicInc32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicDec32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicAnd32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicOr32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicXor32(EmitContext&) { - NotImplemented(); -} - -void EmitBindlessImageAtomicExchange32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicIAdd32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicSMin32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicUMin32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicSMax32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicUMax32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicInc32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicDec32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicAnd32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicOr32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicXor32(EmitContext&) { - NotImplemented(); -} - -void EmitBoundImageAtomicExchange32(EmitContext&) { - NotImplemented(); -} - -void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarS32 value) { - NotImplemented(); -} - -void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarS32 value) { - NotImplemented(); -} - -void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, - ScalarU32 value) { - NotImplemented(); -} - -void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value) { - NotImplemented(); -} - } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 464f13fe0b65a6908086c91e0d3a97d74494a576 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 18:17:03 -0300 Subject: glasm: Implement derivative instructions on GLASM --- .../backend/glasm/emit_glasm_instructions.h | 8 ++++---- src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index e7af8fa88..9f76fc6c2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -611,9 +611,9 @@ void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU3 void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); -void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); -void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); -void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a); -void EmitDPdyCoarse(EmitContext& ctx, ScalarF32 op_a); +void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); +void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); +void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); +void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index 37eb577cd..0f987daeb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -99,20 +99,20 @@ void EmitFSwizzleAdd(EmitContext&, ScalarF32, ScalarF32, ScalarU32) { throw NotImplementedException("GLASM instruction"); } -void EmitDPdxFine(EmitContext&, ScalarF32) { - throw NotImplementedException("GLASM instruction"); +void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { + ctx.Add("DDX.FINE {}.x,{};", inst, p); } -void EmitDPdyFine(EmitContext&, ScalarF32) { - throw NotImplementedException("GLASM instruction"); +void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { + ctx.Add("DDY.FINE {}.x,{};", inst, p); } -void EmitDPdxCoarse(EmitContext&, ScalarF32) { - throw NotImplementedException("GLASM instruction"); +void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { + ctx.Add("DDX.COARSE {}.x,{};", inst, p); } -void EmitDPdyCoarse(EmitContext&, ScalarF32) { - throw NotImplementedException("GLASM instruction"); +void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { + ctx.Add("DDY.COARSE {}.x,{};", inst, p); } } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From d4f9c798d652b0a225a47ab9032dd56dc49fa0d0 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 15 May 2021 00:53:32 -0400 Subject: glasm: Implement rest of shared mem --- .../backend/glasm/emit_glasm_instructions.h | 12 ++--- .../backend/glasm/emit_glasm_shared_memory.cpp | 52 ++++++++++------------ 2 files changed, 29 insertions(+), 35 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 9f76fc6c2..ad640bcb9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -120,13 +120,13 @@ void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, ScalarU32 of Register value); void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, Register value); -void EmitLoadSharedU8(EmitContext& ctx, ScalarU32 offset); -void EmitLoadSharedS8(EmitContext& ctx, ScalarU32 offset); -void EmitLoadSharedU16(EmitContext& ctx, ScalarU32 offset); -void EmitLoadSharedS16(EmitContext& ctx, ScalarU32 offset); -void EmitLoadSharedU32(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); +void EmitLoadSharedS8(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); +void EmitLoadSharedU16(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); +void EmitLoadSharedS16(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); +void EmitLoadSharedU32(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); void EmitLoadSharedU64(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); -void EmitLoadSharedU128(EmitContext& ctx, ScalarU32 offset); +void EmitLoadSharedU128(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset); void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); void EmitWriteSharedU32(EmitContext& ctx, ScalarU32 offset, ScalarU32 value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp index 32cc5d92c..c1498f449 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp @@ -8,57 +8,51 @@ #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { -void EmitLoadSharedU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.U8 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedS8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedS8(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.S8 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedU16(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.U16 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedS16(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.S16 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedU32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedU32(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.U32 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedU64([[maybe_unused]] EmitContext& ctx, IR::Inst& inst, - [[maybe_unused]] ScalarU32 offset) { - ctx.LongAdd("LDS.U64 {},shared_mem[{}];", inst, offset); +void EmitLoadSharedU64(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.U32X2 {},shared_mem[{}];", inst, offset); } -void EmitLoadSharedU128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset) { - throw NotImplementedException("GLASM instruction"); +void EmitLoadSharedU128(EmitContext& ctx, IR::Inst& inst, ScalarU32 offset) { + ctx.Add("LDS.U32X4 {},shared_mem[{}];", inst, offset); } -void EmitWriteSharedU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteSharedU8(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { + ctx.Add("STS.U8 {},shared_mem[{}];", value, offset); } -void EmitWriteSharedU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteSharedU16(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { + ctx.Add("STS.U16 {},shared_mem[{}];", value, offset); } -void EmitWriteSharedU32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] ScalarU32 value) { +void EmitWriteSharedU32(EmitContext& ctx, ScalarU32 offset, ScalarU32 value) { ctx.Add("STS.U32 {},shared_mem[{}];", value, offset); } -void EmitWriteSharedU64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] Register value) { - ctx.Add("STS.U64 {},shared_mem[{}];", value, offset); +void EmitWriteSharedU64(EmitContext& ctx, ScalarU32 offset, Register value) { + ctx.Add("STS.U32X2 {},shared_mem[{}];", value, offset); } -void EmitWriteSharedU128([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); +void EmitWriteSharedU128(EmitContext& ctx, ScalarU32 offset, Register value) { + ctx.Add("STS.U32X4 {},shared_mem[{}];", value, offset); } } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From f7a2340205b4fa2db32403f20d7b7afe32b15f33 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sun, 16 May 2021 17:06:13 -0400 Subject: shader_recompiler: GCC fixes Fixes members of unnamed union not being accessible, and one function without a declaration. --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 16 ++++++++-------- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index e5c96eb7f..0a76423f4 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -212,14 +212,14 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { for (const IR::AbstractSyntaxNode& node : program.syntax_list) { switch (node.type) { case IR::AbstractSyntaxNode::Type::Block: - for (IR::Inst& inst : node.block->Instructions()) { + for (IR::Inst& inst : node.data.block->Instructions()) { EmitInst(ctx, &inst); } break; case IR::AbstractSyntaxNode::Type::If: ctx.Add("MOV.S.CC RC,{};" "IF NE.x;", - eval(node.if_node.cond)); + eval(node.data.if_node.cond)); break; case IR::AbstractSyntaxNode::Type::EndIf: ctx.Add("ENDIF;"); @@ -228,8 +228,8 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { ctx.Add("REP;"); break; case IR::AbstractSyntaxNode::Type::Repeat: - if (node.repeat.cond.IsImmediate()) { - if (node.repeat.cond.U1()) { + if (node.data.repeat.cond.IsImmediate()) { + if (node.data.repeat.cond.U1()) { ctx.Add("ENDREP;"); } else { ctx.Add("BRK;" @@ -239,18 +239,18 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { ctx.Add("MOV.S.CC RC,{};" "BRK (EQ.x);" "ENDREP;", - eval(node.repeat.cond)); + eval(node.data.repeat.cond)); } break; case IR::AbstractSyntaxNode::Type::Break: - if (node.break_node.cond.IsImmediate()) { - if (node.break_node.cond.U1()) { + if (node.data.break_node.cond.IsImmediate()) { + if (node.data.break_node.cond.U1()) { ctx.Add("BRK;"); } } else { ctx.Add("MOV.S.CC RC,{};" "BRK (NE.x);", - eval(node.break_node.cond)); + eval(node.data.break_node.cond)); } break; case IR::AbstractSyntaxNode::Type::Return: diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index a32d01925..4d146d34e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -105,7 +105,7 @@ void EmitBoundImageWrite(EmitContext&) { throw LogicError("Unreachable instruction"); } -std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, +static std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { // FIXME return fmt::format("texture[{}]", info.descriptor_index); -- cgit v1.2.3 From 3c06293e20bde507ed1bc5dabf6c66cc443c2ed4 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 15 May 2021 20:33:57 -0300 Subject: emit_glasm: Add support for reading position attributes --- .../backend/glasm/emit_glasm_context_get_set.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 2de7fb9cc..9ce6c9214 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -51,13 +51,23 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, [[maybe_unused]] ScalarU32 vertex) { + const u32 element{static_cast(attr) % 4}; + const char swizzle{"xyzw"[element]}; if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - const u32 element{IR::GenericAttributeElement(attr)}; - ctx.Add("MOV.F {}.x,in_attr{}[0].{};", inst, index, "xyzw"[element]); + ctx.Add("MOV.F {}.x,in_attr{}[0].{};", inst, index, swizzle); return; } - throw NotImplementedException("Get attribute {}", attr); + switch (attr) { + case IR::Attribute::PositionX: + case IR::Attribute::PositionY: + case IR::Attribute::PositionZ: + case IR::Attribute::PositionW: + ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.stage_name, swizzle); + break; + default: + throw NotImplementedException("Get attribute {}", attr); + } } void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, -- cgit v1.2.3 From db2f0f410810d3d8310a6a476a8bcfd5e509869e Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 16 May 2021 17:52:30 -0300 Subject: emit_glasm: Enable ARB_draw_buffers when needed --- src/shader_recompiler/backend/glasm/emit_context.cpp | 2 +- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 66c954ff6..4903e9d8e 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -71,7 +71,7 @@ EmitContext::EmitContext(IR::Program& program) { if (index == 0) { Add("OUTPUT frag_color0=result.color;"); } else { - Add("OUTPUT frag_color{}[]=result.color[{}];", index, index); + Add("OUTPUT frag_color{}=result.color[{}];", index, index); } } for (size_t index = 0; index < program.info.stores_generics.size(); ++index) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0a76423f4..0c591f73c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -283,6 +283,10 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_subgroup_shuffles) { header += "OPTION NV_shader_thread_shuffle;"; } + const auto non_zero_frag_colors{info.stores_frag_color | std::views::drop(1)}; + if (std::ranges::find(non_zero_frag_colors, true) != non_zero_frag_colors.end()) { + header += "OPTION ARB_draw_buffers;"; + } } std::string_view StageHeader(Stage stage) { -- cgit v1.2.3 From bf2949df100d43f3d54ca74a028aa59678ba76c8 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 16 May 2021 17:54:43 -0300 Subject: glasm: Improve texture sampling instructions --- .../backend/glasm/emit_glasm_image.cpp | 66 ++++++++++++++-------- .../backend/glasm/emit_glasm_instructions.h | 54 +++++++++--------- 2 files changed, 70 insertions(+), 50 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 4d146d34e..7f2cf052a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -112,24 +112,46 @@ static std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInf } void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register bias_lc, + const IR::Value& coord, Register bias_lc, [[maybe_unused]] const IR::Value& offset) { const auto info{inst.Flags()}; const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; - const std::string_view op{info.has_bias ? "TXB" : "TEX"}; - const std::string_view lod_clamp{info.has_lod_clamp ? ".LODCLAMP" : ""}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; + const std::string_view lod_clamp_mod{info.has_lod_clamp ? ".LODCLAMP" : ""}; + const std::string_view type{"2D"}; // FIXME const std::string texture{Texture(ctx, info, index)}; + + std::string coord_vec{fmt::to_string(Register{ctx.reg_alloc.Consume(coord)})}; + if (coord.InstRecursive()->HasUses()) { + // Move non-dead coords to a separate register, although this should never happen because + // vectors are only assembled for immediate texture instructions + ctx.Add("MOV.F RC,{};", coord_vec); + coord_vec = "RC"; + } const Register ret{ctx.reg_alloc.Define(inst)}; - // FIXME - const bool separate{info.type == TextureType::ColorArrayCube}; - if (separate) { - ctx.Add("{}.F{}{} {},{},{},{},2D;", op, lod_clamp, sparse_mod, ret, coords, bias_lc, - texture); + if (info.has_bias) { + if (info.type == TextureType::ColorArrayCube) { + ctx.Add("TXB.F{}{} {},{},{},{},ARRAYCUBE;", lod_clamp_mod, sparse_mod, ret, coord_vec, + bias_lc, texture); + } else { + if (info.has_lod_clamp) { + ctx.Add("MOV.F {}.w,{}.x;" + "TXB.F.LODCLAMP{} {},{},{}.y,{},{};", + coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, texture, type); + } else { + ctx.Add("MOV.F {}.w,{}.x;" + "TXB.F{} {},{},{},{};", + coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, type); + } + } } else { - ctx.Add("MOV.F {}.w,{}.x;" - "{}.F{}{} {},{},{},2D;", - coords, bias_lc, op, lod_clamp, sparse_mod, ret, coords, texture); + if (info.has_lod_clamp && info.type == TextureType::ColorArrayCube) { + ctx.Add("TEX.F.LODCLAMP{} {},{},{},{},ARRAYCUBE;", sparse_mod, ret, coord_vec, bias_lc, + texture); + } else { + ctx.Add("TEX.F{}{} {},{},{},{};", lod_clamp_mod, sparse_mod, ret, coord_vec, texture, + type); + } } if (sparse_inst) { const Register sparse_ret{ctx.reg_alloc.Define(*sparse_inst)}; @@ -142,7 +164,7 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] Register lod_lc, + [[maybe_unused]] Register coord, [[maybe_unused]] Register lod_lc, [[maybe_unused]] const IR::Value& offset) { throw NotImplementedException("GLASM instruction"); } @@ -150,8 +172,7 @@ void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unuse void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, - [[maybe_unused]] Register dref, + [[maybe_unused]] Register coord, [[maybe_unused]] Register dref, [[maybe_unused]] Register bias_lc, [[maybe_unused]] const IR::Value& offset) { throw NotImplementedException("GLASM instruction"); @@ -160,22 +181,21 @@ void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx, void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, - [[maybe_unused]] Register dref, + [[maybe_unused]] Register coord, [[maybe_unused]] Register dref, [[maybe_unused]] Register lod_lc, [[maybe_unused]] const IR::Value& offset) { throw NotImplementedException("GLASM instruction"); } void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, [[maybe_unused]] const IR::Value& offset, [[maybe_unused]] const IR::Value& offset2) { throw NotImplementedException("GLASM instruction"); } void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, [[maybe_unused]] const IR::Value& offset, [[maybe_unused]] const IR::Value& offset2, [[maybe_unused]] Register dref) { @@ -183,7 +203,7 @@ void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR: } void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[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"); @@ -196,24 +216,24 @@ void EmitImageQueryDimensions([[maybe_unused]] EmitContext& ctx, [[maybe_unused] } void EmitImageQueryLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords) { + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord) { throw NotImplementedException("GLASM instruction"); } void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, [[maybe_unused]] Register derivates, [[maybe_unused]] Register offset, [[maybe_unused]] Register lod_clamp) { throw NotImplementedException("GLASM instruction"); } void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords) { + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord) { throw NotImplementedException("GLASM instruction"); } void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, [[maybe_unused]] Register color) { throw NotImplementedException("GLASM instruction"); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index ad640bcb9..a128f9ac4 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -525,28 +525,28 @@ void EmitBoundImageGradient(EmitContext&); void EmitBoundImageRead(EmitContext&); void EmitBoundImageWrite(EmitContext&); void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register bias_lc, const IR::Value& offset); + const IR::Value& coord, Register bias_lc, const IR::Value& offset); void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register lod_lc, const IR::Value& offset); + Register coord, Register lod_lc, const IR::Value& offset); void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register dref, Register bias_lc, + Register coord, Register dref, Register bias_lc, const IR::Value& offset); void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, Register dref, Register lod_lc, + Register coord, Register dref, Register lod_lc, const IR::Value& offset); -void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, const IR::Value& offset, const IR::Value& offset2); -void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, const IR::Value& offset, const IR::Value& offset2, Register dref); -void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register offset, Register lod, Register ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register lod); -void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords); -void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register derivates, Register offset, Register lod_clamp); -void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords); -void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register color); void EmitBindlessImageAtomicIAdd32(EmitContext&); void EmitBindlessImageAtomicSMin32(EmitContext&); @@ -570,28 +570,28 @@ void EmitBoundImageAtomicAnd32(EmitContext&); void EmitBoundImageAtomicOr32(EmitContext&); void EmitBoundImageAtomicXor32(EmitContext&); void EmitBoundImageAtomicExchange32(EmitContext&); -void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value); -void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarS32 value); -void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value); -void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarS32 value); -void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value); -void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value); +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarS32 value); +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value); +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarS32 value); +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value); +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, ScalarU32 value); -void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, ScalarU32 value); -void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, ScalarU32 value); -void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, ScalarU32 value); -void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coords, +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, ScalarU32 value); void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coords, ScalarU32 value); + Register coord, ScalarU32 value); void EmitLaneId(EmitContext& ctx, IR::Inst& inst); void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); -- cgit v1.2.3 From e6b4d461d2424d4fc46eeb3601a5b25cd850c2af Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 16 May 2021 18:00:31 -0300 Subject: glasm: Add support for texture offsets --- .../backend/glasm/emit_glasm_image.cpp | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 7f2cf052a..c395248ed 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -120,7 +120,10 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu const std::string_view lod_clamp_mod{info.has_lod_clamp ? ".LODCLAMP" : ""}; const std::string_view type{"2D"}; // FIXME const std::string texture{Texture(ctx, info, index)}; - + std::string offset_vec; + if (!offset.IsEmpty()) { + offset_vec = fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); + } std::string coord_vec{fmt::to_string(Register{ctx.reg_alloc.Consume(coord)})}; if (coord.InstRecursive()->HasUses()) { // Move non-dead coords to a separate register, although this should never happen because @@ -131,26 +134,27 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu const Register ret{ctx.reg_alloc.Define(inst)}; if (info.has_bias) { if (info.type == TextureType::ColorArrayCube) { - ctx.Add("TXB.F{}{} {},{},{},{},ARRAYCUBE;", lod_clamp_mod, sparse_mod, ret, coord_vec, - bias_lc, texture); + ctx.Add("TXB.F{}{} {},{},{},{},ARRAYCUBE{};", lod_clamp_mod, sparse_mod, ret, coord_vec, + bias_lc, texture, offset_vec); } else { if (info.has_lod_clamp) { ctx.Add("MOV.F {}.w,{}.x;" - "TXB.F.LODCLAMP{} {},{},{}.y,{},{};", - coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, texture, type); + "TXB.F.LODCLAMP{} {},{},{}.y,{},{}{};", + coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, texture, type, + offset_vec); } else { ctx.Add("MOV.F {}.w,{}.x;" - "TXB.F{} {},{},{},{};", - coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, type); + "TXB.F{} {},{},{},{}{};", + coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, type, offset_vec); } } } else { if (info.has_lod_clamp && info.type == TextureType::ColorArrayCube) { - ctx.Add("TEX.F.LODCLAMP{} {},{},{},{},ARRAYCUBE;", sparse_mod, ret, coord_vec, bias_lc, - texture); + ctx.Add("TEX.F.LODCLAMP{} {},{},{},{},ARRAYCUBE{};", sparse_mod, ret, coord_vec, + bias_lc, texture, offset_vec); } else { - ctx.Add("TEX.F{}{} {},{},{},{};", lod_clamp_mod, sparse_mod, ret, coord_vec, texture, - type); + ctx.Add("TEX.F{}{} {},{},{},{}{};", lod_clamp_mod, sparse_mod, ret, coord_vec, texture, + type, offset_vec); } } if (sparse_inst) { -- cgit v1.2.3 From bee9fb0563f2bffd08df6f78091233fb3fc8d4ed Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 16 May 2021 18:01:09 -0300 Subject: glasm: Reorder unreachable image instructions to the bottom --- .../backend/glasm/emit_glasm_image.cpp | 194 ++++++++++----------- 1 file changed, 97 insertions(+), 97 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index c395248ed..247118dff 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -9,103 +9,7 @@ namespace Shader::Backend::GLASM { -void EmitBindlessImageSampleImplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageSampleExplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageGather(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageGatherDref(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageFetch(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageQueryDimensions(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageQueryLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageGradient(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageRead(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageWrite(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageSampleImplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageSampleExplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageSampleDrefImplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageSampleDrefExplicitLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageGather(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageGatherDref(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageFetch(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageQueryDimensions(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageQueryLod(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageGradient(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageRead(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageWrite(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -static std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, +std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { // FIXME return fmt::format("texture[{}]", info.descriptor_index); @@ -242,4 +146,100 @@ void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst throw NotImplementedException("GLASM instruction"); } +void EmitBindlessImageSampleImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGather(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGatherDref(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageFetch(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageQueryDimensions(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageQueryLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageGradient(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageRead(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageWrite(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleDrefImplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageSampleDrefExplicitLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGather(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGatherDref(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageFetch(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageQueryDimensions(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageQueryLod(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageGradient(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageRead(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageWrite(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From c42a6143a55e202974f6ea03e4eb752151c754c3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 16 May 2021 18:06:37 -0300 Subject: glasm: Add support for non-2D texture samples --- .../backend/glasm/emit_glasm_image.cpp | 30 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 247118dff..2af5483d9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -8,21 +8,43 @@ #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { - +namespace { std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { // FIXME return fmt::format("texture[{}]", info.descriptor_index); } +std::string_view TextureType(IR::TextureInstInfo info) { + switch (info.type) { + case TextureType::Color1D: + return "1D"; + case TextureType::ColorArray1D: + return "ARRAY1D"; + case TextureType::Color2D: + return "2D"; + case TextureType::ColorArray2D: + return "ARRAY2D"; + case TextureType::Color3D: + return "3D"; + case TextureType::ColorCube: + return "CUBE"; + case TextureType::ColorArrayCube: + return "ARRAYCUBE"; + case TextureType::Buffer: + return "BUFFER"; + } + throw InvalidArgument("Invalid texture type {}", info.type.Value()); +} +} // Anonymous namespace + void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - const IR::Value& coord, Register bias_lc, - [[maybe_unused]] const IR::Value& offset) { + const IR::Value& coord, Register bias_lc, const IR::Value& offset) { 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 lod_clamp_mod{info.has_lod_clamp ? ".LODCLAMP" : ""}; - const std::string_view type{"2D"}; // FIXME + const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; std::string offset_vec; if (!offset.IsEmpty()) { -- cgit v1.2.3 From ec6fc5fe78c9038fc9ad7259b7b3a7be751ecef6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 May 2021 02:52:01 -0300 Subject: glasm: Implement TEX and TEXS instructions Remove lod clamp from texture instructions with lod, as this is not needed (nor supported). --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 + .../backend/glasm/emit_glasm_image.cpp | 282 ++++++++++++++++++--- .../backend/glasm/emit_glasm_instructions.h | 6 +- .../backend/glasm/emit_glasm_memory.cpp | 2 +- 4 files changed, 252 insertions(+), 41 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0c591f73c..d7a08e4b3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -283,6 +283,9 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_subgroup_shuffles) { header += "OPTION NV_shader_thread_shuffle;"; } + if (info.uses_sparse_residency) { + header += "OPTION EXT_sparse_texture2;"; + } const auto non_zero_frag_colors{info.stores_frag_color | std::views::drop(1)}; if (std::ranges::find(non_zero_frag_colors, true) != non_zero_frag_colors.end()) { header += "OPTION ARB_draw_buffers;"; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 2af5483d9..3d76ab315 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -9,6 +9,34 @@ namespace Shader::Backend::GLASM { namespace { +struct ScopedRegister { + ScopedRegister() = default; + ScopedRegister(RegAlloc& reg_alloc_) : reg_alloc{®_alloc_}, reg{reg_alloc->AllocReg()} {} + + ~ScopedRegister() { + if (reg_alloc) { + reg_alloc->FreeReg(reg); + } + } + + ScopedRegister& operator=(ScopedRegister&& rhs) noexcept { + if (reg_alloc) { + reg_alloc->FreeReg(reg); + } + reg_alloc = std::exchange(rhs.reg_alloc, nullptr); + reg = rhs.reg; + } + + ScopedRegister(ScopedRegister&& rhs) noexcept + : reg_alloc{std::exchange(rhs.reg_alloc, nullptr)}, reg{rhs.reg} {} + + ScopedRegister& operator=(const ScopedRegister&) = delete; + ScopedRegister(const ScopedRegister&) = delete; + + RegAlloc* reg_alloc{}; + Register reg; +}; + std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { // FIXME @@ -36,6 +64,61 @@ std::string_view TextureType(IR::TextureInstInfo info) { } throw InvalidArgument("Invalid texture type {}", info.type.Value()); } + +std::string_view ShadowTextureType(IR::TextureInstInfo info) { + switch (info.type) { + case TextureType::Color1D: + return "SHADOW1D"; + case TextureType::ColorArray1D: + return "SHADOWARRAY1D"; + case TextureType::Color2D: + return "SHADOW2D"; + case TextureType::ColorArray2D: + return "SHADOWARRAY2D"; + case TextureType::Color3D: + return "SHADOW3D"; + case TextureType::ColorCube: + return "SHADOWCUBE"; + case TextureType::ColorArrayCube: + return "SHADOWARRAYCUBE"; + case TextureType::Buffer: + return "SHADOWBUFFER"; + } + throw InvalidArgument("Invalid texture type {}", info.type.Value()); +} + +std::string Offset(EmitContext& ctx, const IR::Value& offset) { + if (offset.IsEmpty()) { + return ""; + } + return fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); +} + +std::pair Coord(EmitContext& ctx, const IR::Value& coord) { + if (coord.IsImmediate()) { + ScopedRegister scoped_reg(ctx.reg_alloc); + return {fmt::to_string(scoped_reg.reg), std::move(scoped_reg)}; + } + std::string coord_vec{fmt::to_string(Register{ctx.reg_alloc.Consume(coord)})}; + if (coord.InstRecursive()->HasUses()) { + // Move non-dead coords to a separate register, although this should never happen because + // vectors are only assembled for immediate texture instructions + ctx.Add("MOV.F RC,{};", coord_vec); + coord_vec = "RC"; + } + return {std::move(coord_vec), ScopedRegister{}}; +} + +void StoreSparse(EmitContext& ctx, IR::Inst* sparse_inst) { + if (!sparse_inst) { + return; + } + const Register sparse_ret{ctx.reg_alloc.Define(*sparse_inst)}; + ctx.Add("MOV.S {},-1;" + "MOV.S {}(NONRESIDENT),0;", + sparse_ret, sparse_ret); + sparse_inst->Invalidate(); +} } // Anonymous namespace void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, @@ -46,17 +129,8 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu const std::string_view lod_clamp_mod{info.has_lod_clamp ? ".LODCLAMP" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; - std::string offset_vec; - if (!offset.IsEmpty()) { - offset_vec = fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); - } - std::string coord_vec{fmt::to_string(Register{ctx.reg_alloc.Consume(coord)})}; - if (coord.InstRecursive()->HasUses()) { - // Move non-dead coords to a separate register, although this should never happen because - // vectors are only assembled for immediate texture instructions - ctx.Add("MOV.F RC,{};", coord_vec); - coord_vec = "RC"; - } + 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.has_bias) { if (info.type == TextureType::ColorArrayCube) { @@ -83,38 +157,172 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu type, offset_vec); } } - if (sparse_inst) { - const Register sparse_ret{ctx.reg_alloc.Define(*sparse_inst)}; - ctx.Add("MOV.S {},-1;" - "MOV.S {}(NONRESIDENT),0;", - sparse_ret, sparse_ret); - sparse_inst->Invalidate(); - } + StoreSparse(ctx, sparse_inst); } -void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coord, [[maybe_unused]] Register lod_lc, - [[maybe_unused]] const IR::Value& offset) { - throw NotImplementedException("GLASM instruction"); +void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, ScalarF32 lod, const IR::Value& offset) { + 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::ColorArrayCube) { + ctx.Add("TXL.F{} {},{},{},{},ARRAYCUBE{};", sparse_mod, ret, coord_vec, lod, texture, + offset_vec); + } else { + ctx.Add("MOV.F {}.w,{};" + "TXL.F{} {},{},{},{}{};", + coord_vec, lod, sparse_mod, ret, coord_vec, texture, type, offset_vec); + } + StoreSparse(ctx, sparse_inst); } -void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coord, [[maybe_unused]] Register dref, - [[maybe_unused]] Register bias_lc, - [[maybe_unused]] const IR::Value& offset) { - throw NotImplementedException("GLASM instruction"); +void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, ScalarF32 dref, Register bias_lc, + const IR::Value& offset) { + 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{ShadowTextureType(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.has_bias) { + if (info.has_lod_clamp) { + switch (info.type) { + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color2D: + ctx.Add("MOV.F {}.z,{};" + "MOV.F {}.w,{}.x;" + "TXB.F.LODCLAMP{} {},{},{}.y,{},{}{};", + coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, + texture, type, offset_vec); + break; + case TextureType::ColorArray2D: + case TextureType::ColorCube: + ctx.Add("MOV.F {}.w,{};" + "TXB.F.LODCLAMP{} {},{},{},{},{}{};", + coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, + offset_vec); + break; + default: + throw NotImplementedException("Invalid type {} with bias and lod clamp", + info.type.Value()); + } + } else { + switch (info.type) { + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color2D: + ctx.Add("MOV.F {}.z,{};" + "MOV.F {}.w,{}.x;" + "TXB.F{} {},{},{},{}{};", + coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, + type, offset_vec); + break; + case TextureType::ColorArray2D: + case TextureType::ColorCube: + ctx.Add("MOV.F {}.w,{};" + "TXB.F{} {},{},{},{},{}{};", + coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, + offset_vec); + break; + case TextureType::ColorArrayCube: { + const ScopedRegister pair{ctx.reg_alloc}; + ctx.Add("MOV.F {}.x,{};" + "MOV.F {}.y,{}.x;" + "TXB.F{} {},{},{},{},{}{};", + pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, + texture, type, offset_vec); + break; + } + default: + throw NotImplementedException("Invalid type {}", info.type.Value()); + } + } + } else { + if (info.has_lod_clamp) { + if (info.type != TextureType::ColorArrayCube) { + const bool w_swizzle{info.type == TextureType::ColorArray2D || + info.type == TextureType::ColorCube}; + const char dref_swizzle{w_swizzle ? 'w' : 'z'}; + ctx.Add("MOV.F {}.{},{};" + "TEX.F.LODCLAMP{} {},{},{},{},{}{};", + coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, bias_lc, texture, + type, offset_vec); + } else { + const ScopedRegister pair{ctx.reg_alloc}; + ctx.Add("MOV.F {}.x,{};" + "MOV.F {}.y,{};" + "TEX.F.LODCLAMP{} {},{},{},{},{}{};", + pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, + texture, type, offset_vec); + } + } else { + if (info.type != TextureType::ColorArrayCube) { + const bool w_swizzle{info.type == TextureType::ColorArray2D || + info.type == TextureType::ColorCube}; + const char dref_swizzle{w_swizzle ? 'w' : 'z'}; + ctx.Add("MOV.F {}.{},{};" + "TEX.F{} {},{},{},{}{};", + coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, texture, type, + offset_vec); + } else { + const ScopedRegister pair{ctx.reg_alloc}; + ctx.Add("TEX.F{} {},{},{},{},{}{};", sparse_mod, ret, coord_vec, dref, texture, + type, offset_vec); + } + } + } + StoreSparse(ctx, sparse_inst); } -void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx, - [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coord, [[maybe_unused]] Register dref, - [[maybe_unused]] Register lod_lc, - [[maybe_unused]] const IR::Value& offset) { - throw NotImplementedException("GLASM instruction"); +void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, + const IR::Value& offset) { + 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{ShadowTextureType(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)}; + switch (info.type) { + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color2D: + ctx.Add("MOV.F {}.z,{};" + "MOV.F {}.w,{};" + "TXL.F{} {},{},{},{}{};", + coord_vec, dref, coord_vec, lod, sparse_mod, ret, coord_vec, texture, type, + offset_vec); + break; + case TextureType::ColorArray2D: + case TextureType::ColorCube: + ctx.Add("MOV.F {}.w,{};" + "TXL.F{} {},{},{},{},{}{};", + coord_vec, dref, sparse_mod, ret, coord_vec, lod, texture, type, offset_vec); + break; + case TextureType::ColorArrayCube: { + const ScopedRegister pair{ctx.reg_alloc}; + ctx.Add("MOV.F {}.x,{};" + "MOV.F {}.y,{};" + "TXL.F{} {},{},{},{},{}{};", + pair.reg, dref, pair.reg, lod, sparse_mod, ret, coord_vec, pair.reg, texture, type, + offset_vec); + break; + } + default: + throw NotImplementedException("Invalid type {}", info.type.Value()); + } + StoreSparse(ctx, sparse_inst); } void EmitImageGather([[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 a128f9ac4..54e7fab3c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -527,12 +527,12 @@ void EmitBoundImageWrite(EmitContext&); void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, Register bias_lc, const IR::Value& offset); void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coord, Register lod_lc, const IR::Value& offset); + const IR::Value& coord, ScalarF32 lod, const IR::Value& offset); void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coord, Register dref, Register bias_lc, + const IR::Value& coord, ScalarF32 dref, Register bias_lc, const IR::Value& offset); void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register coord, Register dref, Register lod_lc, + const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, const IR::Value& offset); void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, const IR::Value& offset, const IR::Value& offset2); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 0c6a6e1c8..dd307a9a3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -38,7 +38,7 @@ void Store(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueTy void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, std::string_view size) { const Register ret{ctx.reg_alloc.Define(inst)}; - StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, ret), + StorageOp(ctx, binding, offset, fmt::format("LOAD.{} {},DC.x;", size, ret), fmt::format("MOV.U {},{{0,0,0,0}};", ret)); } } // Anonymous namespace -- cgit v1.2.3 From f1b334b9f950fa58e2cb0e27574b06a0622a99f6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 May 2021 04:44:13 -0300 Subject: glasm: Remove unintentional comma on vector insert --- src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index 22321f386..d829f05b3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp @@ -52,7 +52,7 @@ void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, Objec // The input composite is not aliased with the return value so we have to copy it before // hand. But the insert object is not aliased with the return value, so we don't have to // worry about that - ctx.Add("MOV.{} {},{};MOV.{},{}.{},{};", type, ret, composite, type, ret, swizzle, object); + ctx.Add("MOV.{} {},{};MOV.{} {}.{},{};", type, ret, composite, type, ret, swizzle, object); } else { // The return value is alised so we can just insert the object, it doesn't matter if it's // aliased -- cgit v1.2.3 From fb3ba62b3a47ad645b007d5031ed9f8aaa7cb5c0 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 May 2021 19:24:09 -0300 Subject: glasm: Fix aliased bitcasts ref counting --- .../glasm/emit_glasm_bitwise_conversion.cpp | 10 +++--- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 39 ++++++++++++++++++---- src/shader_recompiler/backend/glasm/reg_alloc.h | 6 ++++ 3 files changed, 42 insertions(+), 13 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index a6c66b826..cdbf6e93e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -12,12 +12,10 @@ static void Alias(IR::Inst& inst, const IR::Value& value) { if (value.IsImmediate()) { return; } - IR::Inst* const value_inst{value.InstRecursive()}; - if (inst.GetOpcode() == IR::Opcode::Identity) { - value_inst->DestructiveAddUsage(inst.UseCount()); - value_inst->DestructiveRemoveUsage(); - } - inst.SetDefinition(value_inst->Definition()); + IR::Inst& value_inst{RegAlloc::AliasInst(*value.Inst())}; + value_inst.DestructiveAddUsage(inst.UseCount()); + value_inst.DestructiveRemoveUsage(); + inst.SetDefinition(value_inst.Definition()); } void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 0e38f467f..707b22247 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -30,9 +30,10 @@ Value RegAlloc::Consume(const IR::Value& value) { } void RegAlloc::Unref(IR::Inst& inst) { - inst.DestructiveRemoveUsage(); - if (!inst.HasUses()) { - Free(inst.Definition()); + IR::Inst& value_inst{AliasInst(inst)}; + value_inst.DestructiveRemoveUsage(); + if (!value_inst.HasUses()) { + Free(value_inst.Definition()); } } @@ -99,10 +100,7 @@ Value RegAlloc::PeekInst(IR::Inst& inst) { } Value RegAlloc::ConsumeInst(IR::Inst& inst) { - inst.DestructiveRemoveUsage(); - if (!inst.HasUses()) { - Free(inst.Definition()); - } + Unref(inst); return PeekInst(inst); } @@ -138,4 +136,31 @@ void RegAlloc::Free(Id id) { } } +/*static*/ bool RegAlloc::IsAliased(const IR::Inst& inst) { + switch (inst.GetOpcode()) { + case IR::Opcode::Identity: + case IR::Opcode::BitCastU16F16: + case IR::Opcode::BitCastU32F32: + case IR::Opcode::BitCastU64F64: + case IR::Opcode::BitCastF16U16: + case IR::Opcode::BitCastF32U32: + case IR::Opcode::BitCastF64U64: + return true; + default: + return false; + } +} + +/*static*/ IR::Inst& RegAlloc::AliasInst(IR::Inst& inst) { + IR::Inst* it{&inst}; + while (IsAliased(*it)) { + const IR::Value arg{it->Arg(0)}; + if (arg.IsImmediate()) { + break; + } + it = arg.InstRecursive(); + } + return *it; +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index ede6edd1f..41b7c92be 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -126,6 +126,12 @@ public: return num_used_long_registers; } + /// Returns true if the instruction is expected to be aliased to another + static bool IsAliased(const IR::Inst& inst); + + /// Returns the underlying value out of an alias sequence + static IR::Inst& AliasInst(IR::Inst& inst); + private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; -- cgit v1.2.3 From afcb14018542825e23f392698b93fb4a9a4b4a8b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 May 2021 19:25:01 -0300 Subject: glasm: Add missing return value on move assignment --- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 3d76ab315..77da3400b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -25,6 +25,7 @@ struct ScopedRegister { } reg_alloc = std::exchange(rhs.reg_alloc, nullptr); reg = rhs.reg; + return *this; } ScopedRegister(ScopedRegister&& rhs) noexcept -- cgit v1.2.3 From 4bad415bcab581c55770a16ef2e8fe1e6d105ff1 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 May 2021 19:25:19 -0300 Subject: glasm: Implement InstanceId and VertexId --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 9ce6c9214..ceadb3333 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -65,6 +65,12 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::PositionW: ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.stage_name, swizzle); break; + case IR::Attribute::InstanceId: + ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.stage_name); + break; + case IR::Attribute::VertexId: + ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.stage_name); + break; default: throw NotImplementedException("Get attribute {}", attr); } -- cgit v1.2.3 From 9bb3e008c9f4bbdd35c095b506c3a3312d17e383 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 02:04:22 -0300 Subject: shader: Read branch conditions from an instruction Fixes the identity removal pass. --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp | 4 ++++ src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 3 ++- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 2 +- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 1 + 5 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index d7a08e4b3..a893fa3fb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -200,7 +200,7 @@ void Precolor(EmitContext& ctx, const IR::Program& program) { } // Add reference to the phi node on the phi predecessor to avoid overwritting it for (size_t i = 0; i < num_args; ++i) { - IR::IREmitter{*phi.PhiBlock(i)}.DummyReference(IR::Value{&phi}); + IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); } } } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index cdbf6e93e..505378bfd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -22,6 +22,10 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { Alias(inst, value); } +void EmitConditionRef(EmitContext&, IR::Inst& inst, const IR::Value& value) { + Alias(inst, value); +} + void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { Alias(inst, value); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 54e7fab3c..df0933a3f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -22,7 +22,8 @@ class EmitContext; void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitDummyReference(EmitContext&); +void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); +void EmitReference(EmitContext&); void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value); void EmitJoin(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index a4c1ca481..015cb5576 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -21,7 +21,7 @@ void EmitPhi(EmitContext&, IR::Inst&) {} void EmitVoid(EmitContext&) {} -void EmitDummyReference(EmitContext&) {} +void EmitReference(EmitContext&) {} void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { if (phi == value) { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 707b22247..1a88331b4 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -139,6 +139,7 @@ void RegAlloc::Free(Id id) { /*static*/ bool RegAlloc::IsAliased(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::Identity: + case IR::Opcode::ConditionRef: case IR::Opcode::BitCastU16F16: case IR::Opcode::BitCastU32F32: case IR::Opcode::BitCastU64F64: -- cgit v1.2.3 From 1ee7f8b943d1ab6ac6dec18bae6c2be3fd8d246c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 04:04:06 -0300 Subject: glasm: Do not alias ConditionRef for now Immediate condition refs where not handled correctly. Just move the value for now. --- src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp | 4 ++-- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index 505378bfd..808c72105 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -22,8 +22,8 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { Alias(inst, value); } -void EmitConditionRef(EmitContext&, IR::Inst& inst, const IR::Value& value) { - Alias(inst, value); +void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { + ctx.Add("MOV.S {},{};", inst, ScalarS32{ctx.reg_alloc.Consume(value)}); } void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 1a88331b4..707b22247 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -139,7 +139,6 @@ void RegAlloc::Free(Id id) { /*static*/ bool RegAlloc::IsAliased(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::Identity: - case IR::Opcode::ConditionRef: case IR::Opcode::BitCastU16F16: case IR::Opcode::BitCastU32F32: case IR::Opcode::BitCastU64F64: -- cgit v1.2.3 From 0fa421f82f4efbb7fe2d86a18427b4889fd8d855 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 19:43:17 -0300 Subject: glasm: Implement gl_FragDepth and gl_SampleMask stores --- .../backend/glasm/emit_glasm_context_get_set.cpp | 8 ++++---- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index ceadb3333..0b6d853eb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -120,12 +120,12 @@ void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 valu ctx.Add("MOV.F frag_color{}.{},{};", index, "xyzw"[component], value); } -void EmitSetSampleMask([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitSetSampleMask(EmitContext& ctx, ScalarS32 value) { + ctx.Add("MOV.S result.samplemask.x,{};", value); } -void EmitSetFragDepth([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitSetFragDepth(EmitContext& ctx, ScalarF32 value) { + ctx.Add("MOV.F result.depth.z,{};", value); } void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index df0933a3f..ce0181fd2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -56,7 +56,7 @@ void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value void EmitGetPatch(EmitContext& ctx, IR::Patch patch); void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value); void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value); -void EmitSetSampleMask(EmitContext& ctx, ScalarF32 value); +void EmitSetSampleMask(EmitContext& ctx, ScalarS32 value); void EmitSetFragDepth(EmitContext& ctx, ScalarF32 value); void EmitGetZFlag(EmitContext& ctx); void EmitGetSFlag(EmitContext& ctx); -- cgit v1.2.3 From 3d3ed53511dcd338806a97bfff2afa1644ddb424 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 19:43:52 -0300 Subject: glasm: Implement textureGather instructions --- .../backend/glasm/emit_glasm_image.cpp | 103 ++++++++++++++++++--- .../backend/glasm/emit_glasm_instructions.h | 9 +- 2 files changed, 97 insertions(+), 15 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') 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 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/modifiers.h" @@ -95,6 +97,33 @@ std::string Offset(EmitContext& ctx, const IR::Value& offset) { return fmt::format(",offset({})", Register{ctx.reg_alloc.Consume(offset)}); } +std::pair AllocOffsetsRegs(EmitContext& ctx, + const IR::Value& offset2) { + if (offset2.IsEmpty()) { + return {}; + } else { + return {ctx.reg_alloc, ctx.reg_alloc}; + } +} + +void SwizzleOffsets(EmitContext& ctx, Register off_x, Register off_y, const IR::Value& offset1, + const IR::Value& offset2) { + const Register offsets_a{ctx.reg_alloc.Consume(offset1)}; + const Register offsets_b{ctx.reg_alloc.Consume(offset2)}; + // Input swizzle: [XYXY] [XYXY] + // Output swizzle: [XXXX] [YYYY] + ctx.Add("MOV {}.x,{}.x;" + "MOV {}.y,{}.z;" + "MOV {}.z,{}.x;" + "MOV {}.w,{}.z;" + "MOV {}.x,{}.y;" + "MOV {}.y,{}.w;" + "MOV {}.z,{}.y;" + "MOV {}.w,{}.w;", + off_x, offsets_a, off_x, offsets_a, off_x, offsets_b, off_x, offsets_b, off_y, + offsets_a, off_y, offsets_a, off_y, offsets_b, off_y, offsets_b); +} + std::pair Coord(EmitContext& ctx, const IR::Value& coord) { if (coord.IsImmediate()) { ScopedRegister scoped_reg(ctx.reg_alloc); @@ -326,19 +355,71 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: StoreSparse(ctx, sparse_inst); } -void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, - [[maybe_unused]] const IR::Value& offset, - [[maybe_unused]] const IR::Value& offset2) { - throw NotImplementedException("GLASM instruction"); +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2) { + // Allocate offsets early so they don't overwrite any consumed register + const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; + const auto info{inst.Flags()}; + const char comp{"xyzw"[info.gather_component]}; + 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 Register coord_vec{ctx.reg_alloc.Consume(coord)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + if (offset2.IsEmpty()) { + const std::string offset_vec{Offset(ctx, offset)}; + ctx.Add("TXG.F{} {},{},{}.{},{}{};", sparse_mod, ret, coord_vec, texture, comp, type, + offset_vec); + } else { + SwizzleOffsets(ctx, off_x.reg, off_y.reg, offset, offset2); + ctx.Add("TXGO.F{} {},{},{},{},{}.{},{};", sparse_mod, ret, coord_vec, off_x.reg, off_y.reg, + texture, comp, type); + } + StoreSparse(ctx, sparse_inst); } -void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, - [[maybe_unused]] const IR::Value& offset, - [[maybe_unused]] const IR::Value& offset2, - [[maybe_unused]] Register dref) { - throw NotImplementedException("GLASM instruction"); +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) { + // FIXME: This instruction is not working as expected + + // Allocate offsets early so they don't overwrite any consumed register + const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; + 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{ShadowTextureType(info)}; + const std::string texture{Texture(ctx, info, index)}; + const Register coord_vec{ctx.reg_alloc.Consume(coord)}; + const ScalarF32 dref_value{ctx.reg_alloc.Consume(dref)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + std::string args; + switch (info.type) { + case TextureType::Color2D: + ctx.Add("MOV.F {}.z,{};", coord_vec, dref_value); + args = fmt::to_string(coord_vec); + break; + case TextureType::ColorArray2D: + case TextureType::ColorCube: + ctx.Add("MOV.F {}.w,{};", coord_vec, dref_value); + args = fmt::to_string(coord_vec); + break; + case TextureType::ColorArrayCube: + args = fmt::format("{},{}", coord_vec, dref_value); + break; + default: + throw NotImplementedException("Invalid type {}", info.type.Value()); + } + if (offset2.IsEmpty()) { + const std::string offset_vec{Offset(ctx, offset)}; + ctx.Add("TXG.F{} {},{},{},{}{};", sparse_mod, ret, args, texture, type, offset_vec); + } else { + SwizzleOffsets(ctx, off_x.reg, off_y.reg, offset, offset2); + ctx.Add("TXGO.F{} {},{},{},{},{},{};", sparse_mod, ret, args, off_x.reg, off_y.reg, texture, + type); + } + StoreSparse(ctx, sparse_inst); } void EmitImageFetch([[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 ce0181fd2..53e9bdac7 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -535,10 +535,11 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, const IR::Value& offset); -void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, - const IR::Value& offset, const IR::Value& offset2); -void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, - const IR::Value& offset, const IR::Value& offset2, Register dref); +void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2); +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 EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, -- cgit v1.2.3 From 8b7d5912d61d56f65fb7e3a03bba544a4c40bfa6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:04:09 -0300 Subject: glasm: Support textures used in more than one stage --- src/shader_recompiler/backend/glasm/emit_context.cpp | 10 +++++++++- src/shader_recompiler/backend/glasm/emit_context.h | 14 +++++++++++++- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 4903e9d8e..d1fe84a5f 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -4,6 +4,7 @@ #include +#include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/frontend/ir/program.h" @@ -22,7 +23,7 @@ std::string_view InterpDecorator(Interpolation interp) { } } // Anonymous namespace -EmitContext::EmitContext(IR::Program& program) { +EmitContext::EmitContext(IR::Program& program, Bindings& bindings) : info{program.info} { // FIXME: Temporary partial implementation u32 cbuf_index{}; for (const auto& desc : program.info.constant_buffer_descriptors) { @@ -79,6 +80,13 @@ EmitContext::EmitContext(IR::Program& program) { 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; + bindings.texture += desc.count; + } } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 4efe42ada..084635c77 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -6,11 +6,20 @@ #include #include +#include #include #include "shader_recompiler/backend/glasm/reg_alloc.h" +namespace Shader { +struct Info; +} + +namespace Shader::Backend { +struct Bindings; +} + namespace Shader::IR { class Inst; struct Program; @@ -20,7 +29,7 @@ namespace Shader::Backend::GLASM { class EmitContext { public: - explicit EmitContext(IR::Program& program); + explicit EmitContext(IR::Program& program, Bindings& bindings); template void Add(const char* format_str, IR::Inst& inst, Args&&... args) { @@ -45,6 +54,9 @@ public: std::string code; RegAlloc reg_alloc{*this}; + const Info& info; + + std::vector texture_bindings; std::string_view stage_name = "invalid"; }; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index a893fa3fb..edf6f5e13 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -312,8 +312,8 @@ std::string_view StageHeader(Stage stage) { } } // Anonymous namespace -std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { - EmitContext ctx{program}; +std::string EmitGLASM(const Profile&, IR::Program& program, Bindings& bindings) { + EmitContext ctx{program, bindings}; Precolor(ctx, program); EmitCode(ctx, program); std::string header{StageHeader(program.stage)}; -- cgit v1.2.3 From c560bf99c273e21f53387635515a08f5d50b8583 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:04:27 -0300 Subject: glasm: Implement gl_FrongFacing attribute --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 0b6d853eb..8c5cd286d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -71,6 +71,9 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::VertexId: ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.stage_name); break; + case IR::Attribute::FrontFace: + ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.stage_name); + break; default: throw NotImplementedException("Get attribute {}", attr); } -- cgit v1.2.3 From 0a42277a4f7ffc822b334781467ed4588335ba02 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:05:46 -0300 Subject: glasm: Implement TXQ and improve texture info reads --- .../backend/glasm/emit_glasm_image.cpp | 99 +++++++++++----------- .../backend/glasm/emit_glasm_instructions.h | 2 +- 2 files changed, 51 insertions(+), 50 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 9da4da331..7b95505e2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -40,52 +40,51 @@ struct ScopedRegister { Register reg; }; -std::string Texture([[maybe_unused]] EmitContext& ctx, IR::TextureInstInfo info, +std::string Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { - // FIXME - return fmt::format("texture[{}]", info.descriptor_index); + // FIXME: indexed reads + return fmt::format("texture[{}]", ctx.texture_bindings.at(info.descriptor_index)); } std::string_view TextureType(IR::TextureInstInfo info) { - switch (info.type) { - case TextureType::Color1D: - return "1D"; - case TextureType::ColorArray1D: - return "ARRAY1D"; - case TextureType::Color2D: - return "2D"; - case TextureType::ColorArray2D: - return "ARRAY2D"; - case TextureType::Color3D: - return "3D"; - case TextureType::ColorCube: - return "CUBE"; - case TextureType::ColorArrayCube: - return "ARRAYCUBE"; - case TextureType::Buffer: - return "BUFFER"; - } - throw InvalidArgument("Invalid texture type {}", info.type.Value()); -} - -std::string_view ShadowTextureType(IR::TextureInstInfo info) { - switch (info.type) { - case TextureType::Color1D: - return "SHADOW1D"; - case TextureType::ColorArray1D: - return "SHADOWARRAY1D"; - case TextureType::Color2D: - return "SHADOW2D"; - case TextureType::ColorArray2D: - return "SHADOWARRAY2D"; - case TextureType::Color3D: - return "SHADOW3D"; - case TextureType::ColorCube: - return "SHADOWCUBE"; - case TextureType::ColorArrayCube: - return "SHADOWARRAYCUBE"; - case TextureType::Buffer: - return "SHADOWBUFFER"; + if (info.is_depth) { + switch (info.type) { + case TextureType::Color1D: + return "SHADOW1D"; + case TextureType::ColorArray1D: + return "SHADOWARRAY1D"; + case TextureType::Color2D: + return "SHADOW2D"; + case TextureType::ColorArray2D: + return "SHADOWARRAY2D"; + case TextureType::Color3D: + return "SHADOW3D"; + case TextureType::ColorCube: + return "SHADOWCUBE"; + case TextureType::ColorArrayCube: + return "SHADOWARRAYCUBE"; + case TextureType::Buffer: + return "SHADOWBUFFER"; + } + } else { + switch (info.type) { + case TextureType::Color1D: + return "1D"; + case TextureType::ColorArray1D: + return "ARRAY1D"; + case TextureType::Color2D: + return "2D"; + case TextureType::ColorArray2D: + return "ARRAY2D"; + case TextureType::Color3D: + return "3D"; + case TextureType::ColorCube: + return "CUBE"; + case TextureType::ColorArrayCube: + return "ARRAYCUBE"; + case TextureType::Buffer: + return "BUFFER"; + } } throw InvalidArgument("Invalid texture type {}", info.type.Value()); } @@ -217,7 +216,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: 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{ShadowTextureType(info)}; + 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)}; @@ -319,7 +318,7 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: 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{ShadowTextureType(info)}; + 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)}; @@ -389,7 +388,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde 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{ShadowTextureType(info)}; + const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; const Register coord_vec{ctx.reg_alloc.Consume(coord)}; const ScalarF32 dref_value{ctx.reg_alloc.Consume(dref)}; @@ -429,10 +428,12 @@ void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst throw NotImplementedException("GLASM instruction"); } -void EmitImageQueryDimensions([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register lod) { - throw NotImplementedException("GLASM instruction"); +void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + ScalarF32 lod) { + const auto info{inst.Flags()}; + const std::string texture{Texture(ctx, info, index)}; + const std::string_view type{TextureType(info)}; + ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); } void EmitImageQueryLod([[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 53e9bdac7..17bec1d58 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -543,7 +543,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register offset, Register lod, Register ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - Register lod); + ScalarF32 lod); void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register derivates, Register offset, Register lod_clamp); -- cgit v1.2.3 From e8ed90480518c200c8beaefa0ddb2bbb164a429c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:06:19 -0300 Subject: glasm: Implement gl_WorkGroupID --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 17bec1d58..7893f1c2a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -66,7 +66,7 @@ void EmitSetZFlag(EmitContext& ctx); void EmitSetSFlag(EmitContext& ctx); void EmitSetCFlag(EmitContext& ctx); void EmitSetOFlag(EmitContext& ctx); -void EmitWorkgroupId(EmitContext& ctx); +void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst); void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitInvocationId(EmitContext& ctx); void EmitSampleId(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 015cb5576..f8a7e2781 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -144,8 +144,8 @@ void EmitSetOFlag(EmitContext& ctx) { NotImplemented(); } -void EmitWorkgroupId(EmitContext& ctx) { - NotImplemented(); +void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {},invocation.groupid;", inst); } void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) { -- cgit v1.2.3 From 2e0d56da7e9c294f690590a1db6067f3034af665 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:30:09 -0300 Subject: glasm: Implement SelectU1 --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 3 ++- src/shader_recompiler/backend/glasm/emit_glasm_select.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 7893f1c2a..8a707d924 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -179,7 +179,8 @@ void EmitCompositeExtractF64x4(EmitContext& ctx); void EmitCompositeInsertF64x2(EmitContext& ctx, Register composite, Register object, u32 index); void EmitCompositeInsertF64x3(EmitContext& ctx, Register composite, Register object, u32 index); void EmitCompositeInsertF64x4(EmitContext& ctx, Register composite, Register object, u32 index); -void EmitSelectU1(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); +void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value); void EmitSelectU8(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); void EmitSelectU16(EmitContext& ctx, ScalarS32 cond, ScalarS32 true_value, ScalarS32 false_value); void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp index b9e5cbbbe..68fff613c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp @@ -9,9 +9,9 @@ namespace Shader::Backend::GLASM { -void EmitSelectU1([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, - [[maybe_unused]] ScalarS32 true_value, [[maybe_unused]] ScalarS32 false_value) { - throw NotImplementedException("GLASM instruction"); +void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, ScalarS32 true_value, + ScalarS32 false_value) { + ctx.Add("CMP.S {},{},{},{};", inst, cond, true_value, false_value); } void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarS32 cond, -- cgit v1.2.3 From 98ed8ff103a975be93dbbb89d554fbea355aacde Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 May 2021 21:30:24 -0300 Subject: glasm: Implement BFE.CC --- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 1befeca91..ba69c7a1b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -122,6 +122,14 @@ void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, Scal "BFE.U {},RC,{};", count, offset, ret, base); } + if (const auto zero = inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)) { + ctx.Add("SEQ.S {},{},0;", *zero, ret); + zero->Invalidate(); + } + if (const auto sign = inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)) { + ctx.Add("SLT.S {},{},0;", *sign, ret); + sign->Invalidate(); + } } void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { -- cgit v1.2.3 From 3777592ada560e2943a066f7d2d62fd468dbf62c Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 19 May 2021 00:29:07 -0400 Subject: glasm: Implement IADD.CC --- .../backend/glasm/emit_glasm_integer.cpp | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index ba69c7a1b..ff353df8d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -9,7 +9,32 @@ namespace Shader::Backend::GLASM { void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { - ctx.Add("ADD.S {}.x,{},{};", inst, a, b); + const bool cc{inst.HasAssociatedPseudoOperation()}; + const std::string_view cc_mod{cc ? ".CC" : ""}; + if (cc) { + ctx.reg_alloc.InvalidateConditionCodes(); + } + const auto ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("ADD.S{} {}.x,{},{};", cc_mod, ret, a, b); + if (!cc) { + return; + } + static constexpr std::array masks{"EQ", "SF", "CF", "OF"}; + const std::array flags{ + inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp), + }; + for (size_t i = 0; i < flags.size(); ++i) { + if (flags[i]) { + const auto flag_ret{ctx.reg_alloc.Define(*flags[i])}; + ctx.Add("MOV.S {},0;" + "MOV.S {}({}.x),-1;", + flag_ret, flag_ret, masks[i]); + flags[i]->Invalidate(); + } + } } void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, -- cgit v1.2.3 From 4a22942f452dd1bba5e10d20217a0bfbf214dacb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 02:05:24 -0300 Subject: glasm: Implement ImageFetch --- .../backend/glasm/emit_context.cpp | 13 +++++---- src/shader_recompiler/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(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index d1fe84a5f..e2182400c 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 084635c77..d6b0bf73c 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 7b95505e2..333a003c9 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 8a707d924..119b166af 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); -- cgit v1.2.3 From 12dcb9fcc256d016a46e15a61d139878fdd5caec Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 02:12:38 -0300 Subject: glasm: Implement ImageQueryLod --- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 333a003c9..747af84fe 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -457,9 +457,11 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); } -void EmitImageQueryLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord) { - throw NotImplementedException("GLASM instruction"); +void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord) { + const auto info{inst.Flags()}; + const std::string texture{Texture(ctx, info, index)}; + const std::string_view type{TextureType(info)}; + ctx.Add("LOD.F {},{},{},{};", inst, coord, texture, type); } void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, -- cgit v1.2.3 From 9415c435fc447f2cd5a9e5d92401f08931ac1261 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 02:25:53 -0300 Subject: glasm: Implement gl_PointCoord --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 8c5cd286d..7bbb3e1af 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -65,6 +65,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::PositionW: ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.stage_name, swizzle); break; + case IR::Attribute::PointSpriteS: + case IR::Attribute::PointSpriteT: + ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.stage_name, swizzle); + break; case IR::Attribute::InstanceId: ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.stage_name); break; -- cgit v1.2.3 From 2494dbe183660297d9b66d4300a28ca95f740f08 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 02:26:32 -0300 Subject: glasm: Implement gl_PointSize stores --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 7bbb3e1af..f362dd2c8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -93,6 +93,9 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, return; } switch (attr) { + case IR::Attribute::PointSize: + ctx.Add("MOV.F result.pointsize.x,{};", value); + break; case IR::Attribute::PositionX: case IR::Attribute::PositionY: case IR::Attribute::PositionZ: -- cgit v1.2.3 From accad56ee7cc9f77886d164701a35f1e89a3519b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 16:32:03 -0300 Subject: glasm: Implement stores to gl_ViewportIndex --- src/shader_recompiler/backend/glasm/emit_context.cpp | 4 +++- src/shader_recompiler/backend/glasm/emit_context.h | 8 ++++++-- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 16 ++++++++++++---- .../backend/glasm/emit_glasm_context_get_set.cpp | 8 ++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index e2182400c..395ac87f2 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -23,7 +23,8 @@ std::string_view InterpDecorator(Interpolation interp) { } } // Anonymous namespace -EmitContext::EmitContext(IR::Program& program, Bindings& bindings) : info{program.info} { +EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_) + : info{program.info}, profile{profile_} { // FIXME: Temporary partial implementation u32 cbuf_index{}; for (const auto& desc : program.info.constant_buffer_descriptors) { @@ -41,6 +42,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings) : info{progra if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); } + stage = program.stage; switch (program.stage) { case Stage::VertexA: case Stage::VertexB: diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index d6b0bf73c..dd1f9ac9f 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -11,10 +11,12 @@ #include #include "shader_recompiler/backend/glasm/reg_alloc.h" +#include "shader_recompiler/stage.h" namespace Shader { struct Info; -} +struct Profile; +} // namespace Shader namespace Shader::Backend { struct Bindings; @@ -29,7 +31,7 @@ namespace Shader::Backend::GLASM { class EmitContext { public: - explicit EmitContext(IR::Program& program, Bindings& bindings); + explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_); template void Add(const char* format_str, IR::Inst& inst, Args&&... args) { @@ -55,10 +57,12 @@ public: std::string code; RegAlloc reg_alloc{*this}; const Info& info; + const Profile& profile; std::vector texture_buffer_bindings; std::vector texture_bindings; + Stage stage{}; std::string_view stage_name = "invalid"; }; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index edf6f5e13..9dc0cacbe 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -261,7 +261,10 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } } -void SetupOptions(std::string& header, Info info) { +void SetupOptions(const IR::Program& program, const Profile& profile, std::string& header) { + const Info& info{program.info}; + const Stage stage{program.stage}; + // TODO: Track the shared atomic ops header += "OPTION NV_internal;" "OPTION NV_shader_storage_buffer;" @@ -286,6 +289,11 @@ void SetupOptions(std::string& header, Info info) { if (info.uses_sparse_residency) { header += "OPTION EXT_sparse_texture2;"; } + if ((info.stores_viewport_index || info.stores_layer) && stage != Stage::Geometry) { + if (profile.support_viewport_index_layer_non_geometry) { + header += "OPTION NV_viewport_array2;"; + } + } const auto non_zero_frag_colors{info.stores_frag_color | std::views::drop(1)}; if (std::ranges::find(non_zero_frag_colors, true) != non_zero_frag_colors.end()) { header += "OPTION ARB_draw_buffers;"; @@ -312,12 +320,12 @@ std::string_view StageHeader(Stage stage) { } } // Anonymous namespace -std::string EmitGLASM(const Profile&, IR::Program& program, Bindings& bindings) { - EmitContext ctx{program, bindings}; +std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bindings) { + EmitContext ctx{program, bindings, profile}; Precolor(ctx, program); EmitCode(ctx, program); std::string header{StageHeader(program.stage)}; - SetupOptions(header, program.info); + SetupOptions(program, profile, header); switch (program.stage) { case Stage::Compute: header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index f362dd2c8..6484387bc 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -7,6 +7,7 @@ #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/value.h" +#include "shader_recompiler/profile.h" namespace Shader::Backend::GLASM { namespace { @@ -102,6 +103,13 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, case IR::Attribute::PositionW: ctx.Add("MOV.F result.position.{},{};", swizzle, value); break; + case IR::Attribute::ViewportIndex: + if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { + ctx.Add("MOV.F result.viewport.x,{};", value); + } else { + // LOG_WARNING + } + break; default: throw NotImplementedException("Set attribute {}", attr); } -- cgit v1.2.3 From 91a3c2c1c095880a3582f9362943db84b40064f7 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 16:32:21 -0300 Subject: glasm: Implement PREC on relevant instructions --- .../backend/glasm/emit_glasm_floating_point.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp index d2c324ad6..4ed58619d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp @@ -6,6 +6,7 @@ #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" +#include "shader_recompiler/frontend/ir/modifiers.h" #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { @@ -42,6 +43,11 @@ void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value, "MIN.{} {}.x,RC.x,{};", type, min_value, value, type, ret, max_value); } + +std::string_view Precise(IR::Inst& inst) { + const bool precise{inst.Flags().no_contraction}; + return precise ? ".PREC" : ""; +} } // Anonymous namespace void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -63,11 +69,11 @@ void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i } void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { - ctx.Add("ADD.F {}.x,{},{};", inst, a, b); + ctx.Add("ADD.F{} {}.x,{},{};", Precise(inst), ctx.reg_alloc.Define(inst), a, b); } void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { - ctx.LongAdd("ADD.F64 {}.x,{},{};", inst, a, b); + ctx.Add("ADD.F64{} {}.x,{},{};", Precise(inst), ctx.reg_alloc.LongDefine(inst), a, b); } void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, @@ -77,11 +83,11 @@ void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i } void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b, ScalarF32 c) { - ctx.Add("MAD.F {}.x,{},{},{};", inst, a, b, c); + ctx.Add("MAD.F{} {}.x,{},{},{};", Precise(inst), ctx.reg_alloc.Define(inst), a, b, c); } void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b, ScalarF64 c) { - ctx.LongAdd("MAD.F64 {}.x,{},{},{};", inst, a, b, c); + ctx.Add("MAD.F64{} {}.x,{},{},{};", Precise(inst), ctx.reg_alloc.LongDefine(inst), a, b, c); } void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { @@ -106,11 +112,11 @@ void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i } void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, ScalarF32 a, ScalarF32 b) { - ctx.Add("MUL.F {}.x,{},{};", inst, a, b); + ctx.Add("MUL.F{} {}.x,{},{};", Precise(inst), ctx.reg_alloc.Define(inst), a, b); } void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, ScalarF64 a, ScalarF64 b) { - ctx.LongAdd("MUL.F64 {}.x,{},{};", inst, a, b); + ctx.Add("MUL.F64{} {}.x,{},{};", Precise(inst), ctx.reg_alloc.LongDefine(inst), a, b); } void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { -- cgit v1.2.3 From 96962c1d3c638d7cb15c89dcc9933b03237c03f6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 16:32:38 -0300 Subject: glasm: Fix phi instruction types --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index f8a7e2781..066ed1012 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -29,7 +29,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) } const Register phi_reg{ctx.reg_alloc.Consume(phi)}; const Value eval_value{ctx.reg_alloc.Consume(value)}; - switch (phi.InstRecursive()->Arg(0).Type()) { + switch (phi.Inst()->Flags()) { case IR::Type::U1: case IR::Type::U32: case IR::Type::F32: -- cgit v1.2.3 From b60b3fa11389f9aca72bc00a4ab686b3bdb668f0 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 16:51:28 -0300 Subject: glasm: Fix compute stage name --- src/shader_recompiler/backend/glasm/emit_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 395ac87f2..463930a18 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -57,7 +57,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile stage_name = "fragment"; break; case Stage::Compute: - stage_name = "compute"; + stage_name = "invocation"; break; } for (size_t index = 0; index < program.info.input_generics.size(); ++index) { -- cgit v1.2.3 From d957b3a8fef35ec0c2797e5ff0793f7236c08a3f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 16:51:52 -0300 Subject: glasm: Implement barriers --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 066ed1012..f7fec0545 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -53,15 +53,15 @@ void EmitDemoteToHelperInvocation(EmitContext& ctx) { } void EmitBarrier(EmitContext& ctx) { - NotImplemented(); + ctx.Add("BAR;"); } void EmitWorkgroupMemoryBarrier(EmitContext& ctx) { - NotImplemented(); + ctx.Add("MEMBAR.CTA;"); } void EmitDeviceMemoryBarrier(EmitContext& ctx) { - NotImplemented(); + ctx.Add("MEMBAR;"); } void EmitPrologue(EmitContext& ctx) { -- cgit v1.2.3 From 291f220be37d5fed36906b4fce977a5e4e23f481 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 May 2021 17:09:29 -0300 Subject: glasm: Implement 64-bit shifts --- .../backend/glasm/emit_glasm_instructions.h | 8 +++++--- .../backend/glasm/emit_glasm_integer.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 119b166af..94e545ad4 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -308,11 +308,13 @@ void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); -void EmitShiftLeftLogical64(EmitContext& ctx, Register base, Register shift); +void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, ScalarU32 shift); void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); -void EmitShiftRightLogical64(EmitContext& ctx, Register base, Register shift); +void EmitShiftRightLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, + ScalarU32 shift); void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 shift); -void EmitShiftRightArithmetic64(EmitContext& ctx, Register base, Register shift); +void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, + ScalarS32 shift); void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index ff353df8d..f75fcba47 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -75,27 +75,27 @@ void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, Sc ctx.Add("SHL.U {}.x,{},{};", inst, base, shift); } -void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, - [[maybe_unused]] Register shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, + ScalarU32 shift) { + ctx.LongAdd("SHL.U64 {}.x,{},{};", inst, base, shift); } void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) { ctx.Add("SHR.U {}.x,{},{};", inst, base, shift); } -void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, - [[maybe_unused]] Register shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftRightLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, + ScalarU32 shift) { + ctx.LongAdd("SHR.U64 {}.x,{},{};", inst, base, shift); } void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 shift) { ctx.Add("SHR.S {}.x,{},{};", inst, base, shift); } -void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register base, - [[maybe_unused]] Register shift) { - throw NotImplementedException("GLASM instruction"); +void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, + ScalarS32 shift) { + ctx.LongAdd("SHR.S64 {}.x,{},{};", inst, base, shift); } void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { -- cgit v1.2.3 From f79cbbf814b679f4302283852081faabec1316e8 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 01:46:47 -0300 Subject: glasm: Implement ImageGradient --- .../backend/glasm/emit_glasm_image.cpp | 67 ++++++++++++++++++++-- .../backend/glasm/emit_glasm_instructions.h | 5 +- 2 files changed, 65 insertions(+), 7 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') 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:: offsets_a, off_y, offsets_a, off_y, offsets_b, off_y, offsets_b); } +std::string GradOffset(const IR::Value& offset) { + if (offset.IsImmediate()) { + // LOG_WARNING immediate + return ""; + } + IR::Inst* const vector{offset.InstRecursive()}; + if (!vector->AreAllArgsImmediates()) { + // LOG_WARNING elements not immediate + return ""; + } + switch (vector->NumArgs()) { + case 1: + return fmt::format(",({})", static_cast(vector->Arg(0).U32())); + case 2: + return fmt::format(",({},{})", static_cast(vector->Arg(0).U32()), + static_cast(vector->Arg(1).U32())); + default: + throw LogicError("Invalid number of gradient offsets {}", vector->NumArgs()); + } +} + std::pair Coord(EmitContext& ctx, const IR::Value& coord) { if (coord.IsImmediate()) { ScopedRegister scoped_reg(ctx.reg_alloc); @@ -464,11 +485,47 @@ void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, ctx.Add("LOD.F {},{},{},{};", inst, coord, texture, type); } -void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, - [[maybe_unused]] Register derivates, [[maybe_unused]] Register offset, - [[maybe_unused]] Register lod_clamp) { - throw NotImplementedException("GLASM instruction"); +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& derivatives, + const IR::Value& offset, const IR::Value& lod_clamp) { + const auto info{inst.Flags()}; + ScopedRegister dpdx, dpdy; + const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; + if (multi_component) { + // Allocate this early to avoid aliasing other registers + dpdx = ScopedRegister{ctx.reg_alloc}; + dpdy = ScopedRegister{ctx.reg_alloc}; + } + 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{GradOffset(offset)}; + const Register coord_vec{ctx.reg_alloc.Consume(coord)}; + const Register derivatives_vec{ctx.reg_alloc.Consume(derivatives)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + if (multi_component) { + ctx.Add("MOV.F {}.x,{}.x;" + "MOV.F {}.y,{}.z;" + "MOV.F {}.x,{}.y;" + "MOV.F {}.y,{}.w;", + dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec, + dpdy.reg, derivatives_vec); + if (info.has_lod_clamp) { + const ScalarF32 lod_clamp_value{ctx.reg_alloc.Consume(lod_clamp)}; + ctx.Add("MOV.F {}.w,{};" + "TXD.F.LODCLAMP{} {},{},{},{},{},{}{};", + dpdy.reg, lod_clamp_value, sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg, + texture, type, offset_vec); + } else { + ctx.Add("TXD.F{} {},{},{},{},{},{}{};", sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg, + texture, type, offset_vec); + } + } else { + ctx.Add("TXD.F{} {},{},{}.x,{}.y,{},{}{};", sparse_mod, ret, coord_vec, derivatives_vec, + derivatives_vec, texture, type, offset_vec); + } + StoreSparse(ctx, sparse_inst); } 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, 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); -void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, - Register derivates, Register offset, Register lod_clamp); +void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + const IR::Value& coord, const IR::Value& derivatives, + const IR::Value& offset, const IR::Value& lod_clamp); void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, Register color); -- cgit v1.2.3 From 3d0ffc6ad077174e2af9f3923fd99ced6f5e373b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 01:49:26 -0300 Subject: glasm: Implement EmitVertex and EndPrimitive --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 7ccba4c6f..0ce00db67 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -32,7 +32,7 @@ void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); void EmitPrologue(EmitContext& ctx); void EmitEpilogue(EmitContext& ctx); -void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream); +void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream); void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream); void EmitGetRegister(EmitContext& ctx); void EmitSetRegister(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index f7fec0545..9b962427c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -72,12 +72,16 @@ void EmitEpilogue(EmitContext& ctx) { // TODO } -void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { - NotImplemented(); +void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) { + ctx.Add("EMITS {};", stream); } void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { - NotImplemented(); + if (!stream.IsImmediate()) { + // LOG_WARNING not immediate + } + ctx.reg_alloc.Consume(stream); + ctx.Add("ENDPRIM;"); } void EmitGetRegister(EmitContext& ctx) { -- cgit v1.2.3 From dadd192b30d547dfa078057796a5ae16820eb4be Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 02:18:52 -0300 Subject: glasm: Implement ImageRead --- .../backend/glasm/emit_context.cpp | 10 +++++ src/shader_recompiler/backend/glasm/emit_context.h | 2 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 +- .../backend/glasm/emit_glasm_image.cpp | 45 ++++++++++++++++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 463930a18..8f418936e 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -82,6 +82,16 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); } } + image_buffer_bindings.reserve(program.info.image_buffer_descriptors.size()); + for (const auto& desc : program.info.image_buffer_descriptors) { + image_buffer_bindings.push_back(bindings.image); + bindings.image += desc.count; + } + image_bindings.reserve(program.info.image_descriptors.size()); + for (const auto& desc : program.info.image_descriptors) { + image_bindings.push_back(bindings.image); + bindings.image += desc.count; + } 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); diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index dd1f9ac9f..d5bab48ea 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -60,7 +60,9 @@ public: const Profile& profile; std::vector texture_buffer_bindings; + std::vector image_buffer_bindings; std::vector texture_bindings; + std::vector image_bindings; Stage stage{}; std::string_view stage_name = "invalid"; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 9dc0cacbe..3910d00ee 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -270,7 +270,8 @@ void SetupOptions(const IR::Program& program, const Profile& profile, std::strin "OPTION NV_shader_storage_buffer;" "OPTION NV_gpu_program_fp64;" "OPTION NV_bindless_texture;" - "OPTION ARB_derivative_control;"; + "OPTION ARB_derivative_control;" + "OPTION EXT_shader_image_load_formatted;"; if (info.uses_int64_bit_atomics) { header += "OPTION NV_shader_atomic_int64;"; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index ab5a694fd..beee9cf06 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -50,6 +50,16 @@ std::string Texture(EmitContext& ctx, IR::TextureInstInfo info, } } +std::string Image(EmitContext& ctx, IR::TextureInstInfo info, + [[maybe_unused]] const IR::Value& index) { + // FIXME: indexed reads + if (info.type == TextureType::Buffer) { + return fmt::format("image[{}]", ctx.image_buffer_bindings.at(info.descriptor_index)); + } else { + return fmt::format("image[{}]", ctx.image_bindings.at(info.descriptor_index)); + } +} + std::string_view TextureType(IR::TextureInstInfo info) { if (info.is_depth) { switch (info.type) { @@ -173,6 +183,28 @@ void StoreSparse(EmitContext& ctx, IR::Inst* sparse_inst) { sparse_ret, sparse_ret); sparse_inst->Invalidate(); } + +std::string_view FormatStorage(ImageFormat format) { + switch (format) { + case ImageFormat::Typeless: + return "U"; + case ImageFormat::R8_UINT: + return "U8"; + case ImageFormat::R8_SINT: + return "S8"; + case ImageFormat::R16_UINT: + return "U16"; + case ImageFormat::R16_SINT: + return "S16"; + case ImageFormat::R32_UINT: + return "U32"; + case ImageFormat::R32G32_UINT: + return "U32X2"; + case ImageFormat::R32G32B32A32_UINT: + return "U32X4"; + } + throw InvalidArgument("Invalid image format {}", format); +} } // Anonymous namespace void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, @@ -528,9 +560,16 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, StoreSparse(ctx, sparse_inst); } -void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord) { - throw NotImplementedException("GLASM instruction"); +void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord) { + const auto info{inst.Flags()}; + const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const std::string_view format{FormatStorage(info.image_format)}; + const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; + const std::string_view type{TextureType(info)}; + const std::string image{Image(ctx, info, index)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("LOADIM.{}{} {},{},{},{};", format, sparse_mod, ret, coord, image, type); + StoreSparse(ctx, sparse_inst); } void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, -- cgit v1.2.3 From 8fdb00a2b5fccb2378497dc7229639851c60f02b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 02:40:58 -0300 Subject: glasm: Implement ImageWrite --- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index beee9cf06..ed0b65e16 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -572,10 +572,13 @@ void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Reg StoreSparse(ctx, sparse_inst); } -void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coord, - [[maybe_unused]] Register color) { - throw NotImplementedException("GLASM instruction"); +void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + Register color) { + const auto info{inst.Flags()}; + const std::string_view format{FormatStorage(info.image_format)}; + const std::string_view type{TextureType(info)}; + const std::string image{Image(ctx, info, index)}; + ctx.Add("STOREIM.{} {},{},{},{};", format, image, color, coord, type); } void EmitBindlessImageSampleImplicitLod(EmitContext&) { -- cgit v1.2.3 From 0a54291c9c750d89feacef0644959326b9612b64 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 15:58:39 -0300 Subject: glasm: Fix potential aliasing bug on cube array samples --- .../backend/glasm/emit_glasm_image.cpp | 71 ++++++++++++---------- .../backend/glasm/emit_glasm_instructions.h | 8 +-- 2 files changed, 44 insertions(+), 35 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index ed0b65e16..385ca51ac 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -268,9 +268,16 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu } void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - const IR::Value& coord, ScalarF32 dref, Register bias_lc, - const IR::Value& offset) { + const IR::Value& coord, const IR::Value& dref, + const IR::Value& bias_lc, const IR::Value& offset) { + // Allocate early to avoid aliases const auto info{inst.Flags()}; + ScopedRegister staging; + if (info.type == TextureType::ColorArrayCube) { + staging = ScopedRegister{ctx.reg_alloc}; + } + const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)}; + const Register bias_lc_vec{ctx.reg_alloc.Consume(bias_lc)}; 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)}; @@ -287,14 +294,14 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: ctx.Add("MOV.F {}.z,{};" "MOV.F {}.w,{}.x;" "TXB.F.LODCLAMP{} {},{},{}.y,{},{}{};", - coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, - texture, type, offset_vec); + coord_vec, dref_val, coord_vec, bias_lc_vec, sparse_mod, ret, coord_vec, + bias_lc_vec, texture, type, offset_vec); break; case TextureType::ColorArray2D: case TextureType::ColorCube: ctx.Add("MOV.F {}.w,{};" "TXB.F.LODCLAMP{} {},{},{},{},{}{};", - coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, + coord_vec, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec, texture, type, offset_vec); break; default: @@ -309,25 +316,23 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: ctx.Add("MOV.F {}.z,{};" "MOV.F {}.w,{}.x;" "TXB.F{} {},{},{},{}{};", - coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, - type, offset_vec); + coord_vec, dref_val, coord_vec, bias_lc_vec, sparse_mod, ret, coord_vec, + texture, type, offset_vec); break; case TextureType::ColorArray2D: case TextureType::ColorCube: ctx.Add("MOV.F {}.w,{};" "TXB.F{} {},{},{},{},{}{};", - coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, + coord_vec, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec, texture, type, offset_vec); break; - case TextureType::ColorArrayCube: { - const ScopedRegister pair{ctx.reg_alloc}; + case TextureType::ColorArrayCube: ctx.Add("MOV.F {}.x,{};" "MOV.F {}.y,{}.x;" "TXB.F{} {},{},{},{},{}{};", - pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, - texture, type, offset_vec); + staging.reg, dref_val, staging.reg, bias_lc_vec, sparse_mod, ret, coord_vec, + staging.reg, texture, type, offset_vec); break; - } default: throw NotImplementedException("Invalid type {}", info.type.Value()); } @@ -340,15 +345,14 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: const char dref_swizzle{w_swizzle ? 'w' : 'z'}; ctx.Add("MOV.F {}.{},{};" "TEX.F.LODCLAMP{} {},{},{},{},{}{};", - coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, bias_lc, texture, - type, offset_vec); + coord_vec, dref_swizzle, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec, + texture, type, offset_vec); } else { - const ScopedRegister pair{ctx.reg_alloc}; ctx.Add("MOV.F {}.x,{};" "MOV.F {}.y,{};" "TEX.F.LODCLAMP{} {},{},{},{},{}{};", - pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, - texture, type, offset_vec); + staging.reg, dref_val, staging.reg, bias_lc_vec, sparse_mod, ret, coord_vec, + staging.reg, texture, type, offset_vec); } } else { if (info.type != TextureType::ColorArrayCube) { @@ -357,11 +361,10 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: const char dref_swizzle{w_swizzle ? 'w' : 'z'}; ctx.Add("MOV.F {}.{},{};" "TEX.F{} {},{},{},{}{};", - coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, texture, type, - offset_vec); + coord_vec, dref_swizzle, dref_val, sparse_mod, ret, coord_vec, texture, + type, offset_vec); } else { - const ScopedRegister pair{ctx.reg_alloc}; - ctx.Add("TEX.F{} {},{},{},{},{}{};", sparse_mod, ret, coord_vec, dref, texture, + ctx.Add("TEX.F{} {},{},{},{},{}{};", sparse_mod, ret, coord_vec, dref_val, texture, type, offset_vec); } } @@ -370,9 +373,16 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: } void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, - const IR::Value& offset) { + const IR::Value& coord, const IR::Value& dref, + const IR::Value& lod, const IR::Value& offset) { + // Allocate early to avoid aliases const auto info{inst.Flags()}; + ScopedRegister staging; + if (info.type == TextureType::ColorArrayCube) { + staging = ScopedRegister{ctx.reg_alloc}; + } + const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)}; + const ScalarF32 lod_val{ctx.reg_alloc.Consume(lod)}; 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)}; @@ -387,24 +397,23 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: ctx.Add("MOV.F {}.z,{};" "MOV.F {}.w,{};" "TXL.F{} {},{},{},{}{};", - coord_vec, dref, coord_vec, lod, sparse_mod, ret, coord_vec, texture, type, + coord_vec, dref_val, coord_vec, lod_val, sparse_mod, ret, coord_vec, texture, type, offset_vec); break; case TextureType::ColorArray2D: case TextureType::ColorCube: ctx.Add("MOV.F {}.w,{};" "TXL.F{} {},{},{},{},{}{};", - coord_vec, dref, sparse_mod, ret, coord_vec, lod, texture, type, offset_vec); + coord_vec, dref_val, sparse_mod, ret, coord_vec, lod_val, texture, type, + offset_vec); break; - case TextureType::ColorArrayCube: { - const ScopedRegister pair{ctx.reg_alloc}; + case TextureType::ColorArrayCube: ctx.Add("MOV.F {}.x,{};" "MOV.F {}.y,{};" "TXL.F{} {},{},{},{},{}{};", - pair.reg, dref, pair.reg, lod, sparse_mod, ret, coord_vec, pair.reg, texture, type, - offset_vec); + staging.reg, dref_val, staging.reg, lod_val, sparse_mod, ret, coord_vec, + staging.reg, texture, type, offset_vec); break; - } default: throw NotImplementedException("Invalid type {}", info.type.Value()); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 0ce00db67..22d427817 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -533,11 +533,11 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, ScalarF32 lod, const IR::Value& offset); void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - const IR::Value& coord, ScalarF32 dref, Register bias_lc, - const IR::Value& offset); + const IR::Value& coord, const IR::Value& dref, + const IR::Value& bias_lc, const IR::Value& offset); void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, - const IR::Value& offset); + const IR::Value& coord, const IR::Value& dref, + const IR::Value& lod, const IR::Value& offset); void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2); void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, -- cgit v1.2.3 From fad139a3e6f8273acb5b14296ba8fcbd0946fe76 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 17:27:39 -0300 Subject: glasm: Declare geometry program headers --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 3910d00ee..b6b8d504e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -319,6 +319,34 @@ std::string_view StageHeader(Stage stage) { } throw InvalidArgument("Invalid stage {}", stage); } + +std::string_view InputPrimitive(InputTopology topology) { + switch (topology) { + case InputTopology::Points: + return "POINTS"; + case InputTopology::Lines: + return "LINES"; + case InputTopology::LinesAdjacency: + return "LINESS_ADJACENCY"; + case InputTopology::Triangles: + return "TRIANGLES"; + case InputTopology::TrianglesAdjacency: + return "TRIANGLES_ADJACENCY"; + } + throw InvalidArgument("Invalid input topology {}", topology); +} + +std::string_view OutputPrimitive(OutputTopology topology) { + switch (topology) { + case OutputTopology::PointList: + return "POINTS"; + case OutputTopology::LineStrip: + return "LINE_STRIP"; + case OutputTopology::TriangleStrip: + return "TRIANGLE_STRIP"; + } + throw InvalidArgument("Invalid output topology {}", topology); +} } // Anonymous namespace std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bindings) { @@ -328,6 +356,13 @@ std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bi std::string header{StageHeader(program.stage)}; SetupOptions(program, profile, header); switch (program.stage) { + case Stage::Geometry: + header += fmt::format("PRIMITIVE_IN {};" + "PRIMITIVE_OUT {};" + "VERTICES_OUT {};", + InputPrimitive(profile.input_topology), + OutputPrimitive(program.output_topology), program.output_vertices); + break; case Stage::Compute: header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], program.workgroup_size[1], program.workgroup_size[2]); -- cgit v1.2.3 From 83cef0426b058014ad94dd687a29e7c31a1fbbef Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 17:28:09 -0300 Subject: glasm: Properly declare attributes on geometry programs --- src/shader_recompiler/backend/glasm/emit_context.cpp | 9 ++++++++- src/shader_recompiler/backend/glasm/emit_context.h | 1 + .../backend/glasm/emit_glasm_context_get_set.cpp | 10 +++++----- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 8f418936e..a9bbb680f 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -47,24 +47,31 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile case Stage::VertexA: case Stage::VertexB: stage_name = "vertex"; + attrib_name = "vertex"; break; case Stage::TessellationControl: case Stage::TessellationEval: + stage_name = "primitive"; + attrib_name = "primitive"; + break; case Stage::Geometry: stage_name = "primitive"; + attrib_name = "vertex"; break; case Stage::Fragment: stage_name = "fragment"; + attrib_name = "fragment"; break; case Stage::Compute: stage_name = "invocation"; break; } + const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; for (size_t index = 0; index < program.info.input_generics.size(); ++index) { const auto& generic{program.info.input_generics[index]}; if (generic.used) { Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", - InterpDecorator(generic.interpolation), index, stage_name, index, index); + InterpDecorator(generic.interpolation), index, attr_stage, index, index); } } for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index d5bab48ea..e76ed1d7c 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -66,6 +66,7 @@ public: Stage stage{}; std::string_view stage_name = "invalid"; + std::string_view attrib_name = "invalid"; }; } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 6484387bc..a81bd209b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -64,20 +64,20 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::PositionY: case IR::Attribute::PositionZ: case IR::Attribute::PositionW: - ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.stage_name, swizzle); + ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: - ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.stage_name, swizzle); + ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.attrib_name, swizzle); break; case IR::Attribute::InstanceId: - ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.stage_name); + ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name); break; case IR::Attribute::VertexId: - ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.stage_name); + ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name); break; case IR::Attribute::FrontFace: - ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.stage_name); + ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name); break; default: throw NotImplementedException("Get attribute {}", attr); -- cgit v1.2.3 From 79929be8331fabdb83b5595704241f863a0ae33a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 19:21:38 -0300 Subject: glasm: Implement geometry shader attribute reads --- src/shader_recompiler/backend/glasm/emit_context.cpp | 3 +++ .../backend/glasm/emit_glasm_context_get_set.cpp | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index a9bbb680f..d8451b41f 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -74,6 +74,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile InterpDecorator(generic.interpolation), index, attr_stage, index, index); } } + if (stage == Stage::Geometry && info.loads_position) { + Add("ATTRIB vertex_position=vertex.position;"); + } for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { if (!program.info.stores_frag_color[index]) { continue; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index a81bd209b..d736775c8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -19,6 +19,14 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU const Register ret{ctx.reg_alloc.Define(inst)}; ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset); } + +std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) { + if (ctx.stage == Stage::Geometry) { + return fmt::format("[{}]", vertex); + } else { + return ""; + } +} } // Anonymous namespace void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { @@ -50,13 +58,12 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding GetCbuf(ctx, inst, binding, offset, "U32X2"); } -void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, - [[maybe_unused]] ScalarU32 vertex) { +void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex) { const u32 element{static_cast(attr) % 4}; const char swizzle{"xyzw"[element]}; if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - ctx.Add("MOV.F {}.x,in_attr{}[0].{};", inst, index, swizzle); + ctx.Add("MOV.F {}.x,in_attr{}{}[0].{};", inst, index, VertexIndex(ctx, vertex), swizzle); return; } switch (attr) { @@ -64,7 +71,11 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::PositionY: case IR::Attribute::PositionZ: case IR::Attribute::PositionW: - ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); + if (ctx.stage == Stage::Geometry) { + ctx.Add("MOV.F {}.x,vertex_position{}.{};", inst, VertexIndex(ctx, vertex), swizzle); + } else { + ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); + } break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: -- cgit v1.2.3 From 679e7146a701b961ac83b7f5f074ebd5a1bd7e45 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 19:22:08 -0300 Subject: glasm: Optimize EmitVertex into EMIT --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 9b962427c..82abbdab3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -73,7 +73,11 @@ void EmitEpilogue(EmitContext& ctx) { } void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) { - ctx.Add("EMITS {};", stream); + if (stream.type == Type::U32 && stream.imm_u32) { + ctx.Add("EMIT;"); + } else { + ctx.Add("EMITS {};", stream); + } } void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { -- cgit v1.2.3 From d5db96386d08652a8fd90757d9933835c06a84d6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 20:36:04 -0300 Subject: glasm: Implement InvocationId --- src/shader_recompiler/backend/glasm/emit_context.cpp | 3 +++ src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index d8451b41f..7b25fa042 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -77,6 +77,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile if (stage == Stage::Geometry && info.loads_position) { Add("ATTRIB vertex_position=vertex.position;"); } + if (info.uses_invocation_id) { + Add("ATTRIB primitive_invocation=primitive.invocation;"); + } for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { if (!program.info.stores_frag_color[index]) { continue; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 82abbdab3..b60c907df 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -160,8 +160,8 @@ void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) { ctx.Add("MOV.S {},invocation.localid;", inst); } -void EmitInvocationId(EmitContext& ctx) { - NotImplemented(); +void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,primitive_invocation.x;", inst); } void EmitSampleId(EmitContext& ctx) { -- cgit v1.2.3 From 164b8c1ec5385339c8c29368cc02512aff4a6590 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 20:59:55 -0300 Subject: glasm: Fix InvocationId declaration --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 22d427817..b0af02235 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -68,7 +68,7 @@ void EmitSetCFlag(EmitContext& ctx); void EmitSetOFlag(EmitContext& ctx); void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst); void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); -void EmitInvocationId(EmitContext& ctx); +void EmitInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitSampleId(EmitContext& ctx); void EmitIsHelperInvocation(EmitContext& ctx); void EmitYDirection(EmitContext& ctx); -- cgit v1.2.3 From a569ac418e232ed631b5a884a1d54aaa619d8341 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:00:17 -0300 Subject: glasm: Implement patch memory --- .../backend/glasm/emit_context.cpp | 18 +++++++++++ .../backend/glasm/emit_glasm_context_get_set.cpp | 37 +++++++++++++++++++--- .../backend/glasm/emit_glasm_instructions.h | 2 +- 3 files changed, 51 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 7b25fa042..bb68b3d19 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -80,6 +80,24 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile if (info.uses_invocation_id) { Add("ATTRIB primitive_invocation=primitive.invocation;"); } + if (info.stores_tess_level_outer) { + Add("OUTPUT result_patch_tessouter[]={{result.patch.tessouter[0..3]}};"); + } + if (info.stores_tess_level_inner) { + Add("OUTPUT result_patch_tessinner[]={{result.patch.tessinner[0..1]}};"); + } + for (size_t index = 0; index < info.uses_patches.size(); ++index) { + if (!info.uses_patches[index]) { + continue; + } + if (stage == Stage::TessellationEval) { + Add("OUTPUT result_patch_attrib{}[]={{result.patch.attrib[{}..{}]}};", index, index, + index); + } else { + Add("ATTRIB primitive_patch_attrib{}[]={{primitive.patch.attrib[{}..{}]}};", index, + index, index); + } + } for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { if (!program.info.stores_frag_color[index]) { continue; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index d736775c8..c3a2c6b70 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -136,13 +136,40 @@ void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] throw NotImplementedException("GLASM instruction"); } -void EmitGetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch) { - throw NotImplementedException("GLASM instruction"); +void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { + if (!IR::IsGeneric(patch)) { + throw NotImplementedException("Non-generic patch load"); + } + const u32 index{IR::GenericPatchIndex(patch)}; + const u32 element{IR::GenericPatchElement(patch)}; + ctx.Add("MOV.F {},result.patch.attrib[{}].{}", inst, index, "xyzw"[element]); } -void EmitSetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch, - [[maybe_unused]] ScalarF32 value) { - throw NotImplementedException("GLASM instruction"); +void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value) { + if (IR::IsGeneric(patch)) { + const u32 index{IR::GenericPatchIndex(patch)}; + const u32 element{IR::GenericPatchElement(patch)}; + ctx.Add("MOV.F result.patch.attrib[{}].{},{}", index, "xyzw"[element], value); + return; + } + switch (patch) { + case IR::Patch::TessellationLodLeft: + case IR::Patch::TessellationLodRight: + case IR::Patch::TessellationLodTop: + case IR::Patch::TessellationLodBottom: { + const u32 index{static_cast(patch) - u32(IR::Patch::TessellationLodLeft)}; + ctx.Add("MOV.F result.patch.tessouter[{}].x,{};", index, value); + break; + } + case IR::Patch::TessellationLodInteriorU: + ctx.Add("MOV.F result.patch.tessinner[0].x,{};", value); + break; + case IR::Patch::TessellationLodInteriorV: + ctx.Add("MOV.F result.patch.tessinner[1].x,{};", value); + break; + default: + throw NotImplementedException("Patch {}", patch); + } } void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index b0af02235..2eb1eb123 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -53,7 +53,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); void EmitGetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarU32 vertex); void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); -void EmitGetPatch(EmitContext& ctx, IR::Patch patch); +void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value); void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value); void EmitSetSampleMask(EmitContext& ctx, ScalarS32 value); -- cgit v1.2.3 From 2913ca811ea95527d0a0ae653348e3bdc90407fd Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:06:50 -0300 Subject: glasm: Implement TessellationEvaluationPoint --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index c3a2c6b70..a728225b0 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -77,6 +77,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); } break; + case IR::Attribute::TessellationEvaluationPointU: + case IR::Attribute::TessellationEvaluationPointV: + ctx.Add("MOV.F {}.x,vertex.tesscoord.{}", inst, swizzle); + break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.attrib_name, swizzle); -- cgit v1.2.3 From 9ec2303ad6a399cea9e66fa522f65671046f1879 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:18:39 -0300 Subject: glasm: Add tessellation shader declarations --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index b6b8d504e..476cdda54 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -347,6 +347,30 @@ std::string_view OutputPrimitive(OutputTopology topology) { } throw InvalidArgument("Invalid output topology {}", topology); } + +std::string_view GetTessMode(TessPrimitive primitive) { + switch (primitive) { + case TessPrimitive::Triangles: + return "TRIANGLES"; + case TessPrimitive::Quads: + return "QUADS"; + case TessPrimitive::Isolines: + return "ISOLINES"; + } + throw InvalidArgument("Invalid tessellation primitive {}", primitive); +} + +std::string_view GetTessSpacing(TessSpacing spacing) { + switch (spacing) { + case TessSpacing::Equal: + return "EQUAL"; + case TessSpacing::FractionalOdd: + return "FRACTIONAL_ODD"; + case TessSpacing::FractionalEven: + return "FRACTIONAL_EVEN"; + } + throw InvalidArgument("Invalid tessellation spacing {}", spacing); +} } // Anonymous namespace std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bindings) { @@ -356,6 +380,17 @@ std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bi std::string header{StageHeader(program.stage)}; SetupOptions(program, profile, header); switch (program.stage) { + case Stage::TessellationControl: + header += fmt::format("VERTICES_OUT {};", program.invocations); + break; + case Stage::TessellationEval: + header += + fmt::format("TESS_MODE {};" + "TESS_SPACING {};" + "TESS_VERTEX_ORDER {};", + GetTessMode(profile.tess_primitive), GetTessSpacing(profile.tess_spacing), + profile.tess_clockwise ? "CW" : "CCW"); + break; case Stage::Geometry: header += fmt::format("PRIMITIVE_IN {};" "PRIMITIVE_OUT {};" -- cgit v1.2.3 From 48d4e263264e9ae0214ad6f0064e8e32aba17fc4 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:39:45 -0300 Subject: glasm: Fix tessellation headers --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 476cdda54..4fc7d2f2f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -307,9 +307,9 @@ std::string_view StageHeader(Stage stage) { case Stage::VertexB: return "!!NVvp5.0\n"; case Stage::TessellationControl: - return "!!NVtcs5.0\n"; + return "!!NVtcp5.0\n"; case Stage::TessellationEval: - return "!!NVtes5.0\n"; + return "!!NVtep5.0\n"; case Stage::Geometry: return "!!NVgp5.0\n"; case Stage::Fragment: -- cgit v1.2.3 From 0d7d85c81eb3bb931916ec5b85bcb42761a00522 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:40:49 -0300 Subject: glasm: Add missing semicolon on tesscoord reading --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index a728225b0..cdba4fa89 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -79,7 +79,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal break; case IR::Attribute::TessellationEvaluationPointU: case IR::Attribute::TessellationEvaluationPointV: - ctx.Add("MOV.F {}.x,vertex.tesscoord.{}", inst, swizzle); + ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle); break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: -- cgit v1.2.3 From a5d978e91ec66d21764bb74047881cb614425935 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:48:09 -0300 Subject: glasm: Fix tessellation input attributes --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index cdba4fa89..7a084508d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -21,9 +21,12 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU } std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) { - if (ctx.stage == Stage::Geometry) { + switch (ctx.stage) { + case Stage::TessellationControl: + case Stage::TessellationEval: + case Stage::Geometry: return fmt::format("[{}]", vertex); - } else { + default: return ""; } } -- cgit v1.2.3 From 394b96a2fe0fb7c93052f043383889e46ff6202a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:54:02 -0300 Subject: glasm: Implement clip distance stores --- src/shader_recompiler/backend/glasm/emit_context.cpp | 3 +++ .../backend/glasm/emit_glasm_context_get_set.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index bb68b3d19..e82c8995a 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -86,6 +86,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile if (info.stores_tess_level_inner) { Add("OUTPUT result_patch_tessinner[]={{result.patch.tessinner[0..1]}};"); } + if (info.stores_clip_distance) { + Add("OUTPUT result_clip[]={{result.clip[0..7]}};"); + } for (size_t index = 0; index < info.uses_patches.size(); ++index) { if (!info.uses_patches[index]) { continue; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 7a084508d..b64025420 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -121,6 +121,18 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, case IR::Attribute::PositionW: ctx.Add("MOV.F result.position.{},{};", swizzle, value); break; + case IR::Attribute::ClipDistance0: + case IR::Attribute::ClipDistance1: + case IR::Attribute::ClipDistance2: + case IR::Attribute::ClipDistance3: + case IR::Attribute::ClipDistance4: + case IR::Attribute::ClipDistance5: + case IR::Attribute::ClipDistance6: + case IR::Attribute::ClipDistance7: { + const u32 index{static_cast(attr) - static_cast(IR::Attribute::ClipDistance0)}; + ctx.Add("MOV.F result.clip[{}].x,{};", index, value); + break; + } case IR::Attribute::ViewportIndex: if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { ctx.Add("MOV.F result.viewport.x,{};", value); -- cgit v1.2.3 From 3da7b98d376cc0b8ec00de80755d9e90fc90e3a8 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 21:56:40 -0300 Subject: glasm: Implement PrimitiveId attribute read --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index b64025420..116b42361 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -70,6 +70,9 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal return; } switch (attr) { + case IR::Attribute::PrimitiveId: + ctx.Add("MOV.S {}.x,primitive.id;", inst); + break; case IR::Attribute::PositionX: case IR::Attribute::PositionY: case IR::Attribute::PositionZ: -- cgit v1.2.3 From 36d040da7059e438fa35f1a5de5d5aed4cef5ca4 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 19 May 2021 01:00:51 -0400 Subject: glasm: Implement FSWZADD --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 16 +++++++++++++++- .../backend/glasm/emit_glasm_instructions.h | 3 ++- src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | 13 +++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 4fc7d2f2f..f110fd7f8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -281,7 +281,8 @@ void SetupOptions(const IR::Program& program, const Profile& profile, std::strin if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { header += "OPTION NV_shader_atomic_fp16_vector;"; } - if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote) { + if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote || + info.uses_fswzadd) { header += "OPTION NV_shader_thread_group;"; } if (info.uses_subgroup_shuffles) { @@ -416,12 +417,25 @@ std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bi if (program.local_memory_size > 0) { header += fmt::format("lmem[{}],", program.local_memory_size); } + if (program.info.uses_fswzadd) { + header += "FSWZA[4],FSWZB[4],"; + } header += "RC;" "LONG TEMP "; for (size_t index = 0; index < ctx.reg_alloc.NumUsedLongRegisters(); ++index) { header += fmt::format("D{},", index); } header += "DC;"; + if (program.info.uses_fswzadd) { + header += "MOV.F FSWZA[0],-1;" + "MOV.F FSWZA[1],1;" + "MOV.F FSWZA[2],-1;" + "MOV.F FSWZA[3],0;" + "MOV.F FSWZB[0],-1;" + "MOV.F FSWZB[1],-1;" + "MOV.F FSWZB[2],1;" + "MOV.F FSWZB[3],-1;"; + } ctx.code.insert(0, header); ctx.code += "END"; return ctx.code; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 2eb1eb123..15380a955 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -616,7 +616,8 @@ void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU3 const IR::Value& clamp, const IR::Value& segmentation_mask); void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, const IR::Value& clamp, const IR::Value& segmentation_mask); -void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); +void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a, ScalarF32 op_b, + ScalarU32 swizzle); void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index 0f987daeb..af0e13d43 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -95,8 +95,17 @@ void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, Sca Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "XOR"); } -void EmitFSwizzleAdd(EmitContext&, ScalarF32, ScalarF32, ScalarU32) { - throw NotImplementedException("GLASM instruction"); +void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a, ScalarF32 op_b, + ScalarU32 swizzle) { + const auto ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("AND.U RC.z,{}.threadid,3;" + "SHL.U RC.z,RC.z,1;" + "SHR.U RC.z,{},RC.z;" + "AND.U RC.z,RC.z,3;" + "MUL.F RC.x,{},FSWZA[RC.z];" + "MUL.F RC.y,{},FSWZB[RC.z];" + "ADD.F {}.x,RC.x,RC.y;", + ctx.stage_name, swizzle, op_a, op_b, ret); } void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { -- cgit v1.2.3 From 781a87175ce4b28d0048433a78567551c5f0815d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 May 2021 22:08:56 -0300 Subject: glasm: Fix patch attribute declarations --- src/shader_recompiler/backend/glasm/emit_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index e82c8995a..e42f186c1 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -93,7 +93,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile if (!info.uses_patches[index]) { continue; } - if (stage == Stage::TessellationEval) { + if (stage == Stage::TessellationControl) { Add("OUTPUT result_patch_attrib{}[]={{result.patch.attrib[{}..{}]}};", index, index, index); } else { -- cgit v1.2.3 From eb156679057340524c3e1e00d4910c88a2f3c6c2 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Thu, 20 May 2021 22:59:46 -0400 Subject: emit_glasm_context_get_and_set.cpp: Add missing semicolons --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 116b42361..34669160a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -164,14 +164,14 @@ void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { } const u32 index{IR::GenericPatchIndex(patch)}; const u32 element{IR::GenericPatchElement(patch)}; - ctx.Add("MOV.F {},result.patch.attrib[{}].{}", inst, index, "xyzw"[element]); + ctx.Add("MOV.F {},result.patch.attrib[{}].{};", inst, index, "xyzw"[element]); } void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value) { if (IR::IsGeneric(patch)) { const u32 index{IR::GenericPatchIndex(patch)}; const u32 element{IR::GenericPatchElement(patch)}; - ctx.Add("MOV.F result.patch.attrib[{}].{},{}", index, "xyzw"[element], value); + ctx.Add("MOV.F result.patch.attrib[{}].{},{};", index, "xyzw"[element], value); return; } switch (patch) { -- cgit v1.2.3 From 9e7b6622c25aa858b96bf0f1c7f94223a2f449a2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 02:12:32 -0300 Subject: shader: Split profile and runtime information in separate structs --- .../backend/glasm/emit_context.cpp | 40 ++++++++++++---------- src/shader_recompiler/backend/glasm/emit_context.h | 6 ++-- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 19 +++++----- src/shader_recompiler/backend/glasm/emit_glasm.h | 6 ++-- 4 files changed, 38 insertions(+), 33 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index e42f186c1..659ff6d17 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -23,23 +23,25 @@ std::string_view InterpDecorator(Interpolation interp) { } } // Anonymous namespace -EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_) - : info{program.info}, profile{profile_} { +EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, + const RuntimeInfo& runtime_info_) + : profile{profile_}, runtime_info{runtime_info_} { // FIXME: Temporary partial implementation + const auto& info{program.info}; u32 cbuf_index{}; - for (const auto& desc : program.info.constant_buffer_descriptors) { + for (const auto& desc : info.constant_buffer_descriptors) { if (desc.count != 1) { throw NotImplementedException("Constant buffer descriptor array"); } Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); ++cbuf_index; } - for (const auto& desc : program.info.storage_buffers_descriptors) { + for (const auto& desc : info.storage_buffers_descriptors) { if (desc.count != 1) { throw NotImplementedException("Storage buffer descriptor array"); } } - if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { + if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); } stage = program.stage; @@ -67,8 +69,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile break; } const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; - for (size_t index = 0; index < program.info.input_generics.size(); ++index) { - const auto& generic{program.info.input_generics[index]}; + for (size_t index = 0; index < info.input_generics.size(); ++index) { + const auto& generic{info.input_generics[index]}; if (generic.used) { Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", InterpDecorator(generic.interpolation), index, attr_stage, index, index); @@ -101,8 +103,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile index, index); } } - for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { - if (!program.info.stores_frag_color[index]) { + for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { + if (!info.stores_frag_color[index]) { continue; } if (index == 0) { @@ -111,28 +113,28 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile Add("OUTPUT frag_color{}=result.color[{}];", index, index); } } - for (size_t index = 0; index < program.info.stores_generics.size(); ++index) { - if (program.info.stores_generics[index]) { + for (size_t index = 0; index < info.stores_generics.size(); ++index) { + if (info.stores_generics[index]) { Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); } } - image_buffer_bindings.reserve(program.info.image_buffer_descriptors.size()); - for (const auto& desc : program.info.image_buffer_descriptors) { + image_buffer_bindings.reserve(info.image_buffer_descriptors.size()); + for (const auto& desc : info.image_buffer_descriptors) { image_buffer_bindings.push_back(bindings.image); bindings.image += desc.count; } - image_bindings.reserve(program.info.image_descriptors.size()); - for (const auto& desc : program.info.image_descriptors) { + image_bindings.reserve(info.image_descriptors.size()); + for (const auto& desc : info.image_descriptors) { image_bindings.push_back(bindings.image); bindings.image += desc.count; } - texture_buffer_bindings.reserve(program.info.texture_buffer_descriptors.size()); - for (const auto& desc : program.info.texture_buffer_descriptors) { + texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); + for (const auto& desc : 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.reserve(info.texture_descriptors.size()); + for (const auto& desc : 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 e76ed1d7c..1f057fdd5 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -16,6 +16,7 @@ namespace Shader { struct Info; struct Profile; +struct RuntimeInfo; } // namespace Shader namespace Shader::Backend { @@ -31,7 +32,8 @@ namespace Shader::Backend::GLASM { class EmitContext { public: - explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_); + explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, + const RuntimeInfo& runtime_info_); template void Add(const char* format_str, IR::Inst& inst, Args&&... args) { @@ -56,8 +58,8 @@ public: std::string code; RegAlloc reg_alloc{*this}; - const Info& info; const Profile& profile; + const RuntimeInfo& runtime_info; std::vector texture_buffer_bindings; std::vector image_buffer_bindings; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index f110fd7f8..edff04a44 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -374,8 +374,9 @@ std::string_view GetTessSpacing(TessSpacing spacing) { } } // Anonymous namespace -std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bindings) { - EmitContext ctx{program, bindings, profile}; +std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, + Bindings& bindings) { + EmitContext ctx{program, bindings, profile, runtime_info}; Precolor(ctx, program); EmitCode(ctx, program); std::string header{StageHeader(program.stage)}; @@ -385,18 +386,18 @@ std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bi header += fmt::format("VERTICES_OUT {};", program.invocations); break; case Stage::TessellationEval: - header += - fmt::format("TESS_MODE {};" - "TESS_SPACING {};" - "TESS_VERTEX_ORDER {};", - GetTessMode(profile.tess_primitive), GetTessSpacing(profile.tess_spacing), - profile.tess_clockwise ? "CW" : "CCW"); + header += fmt::format("TESS_MODE {};" + "TESS_SPACING {};" + "TESS_VERTEX_ORDER {};", + GetTessMode(runtime_info.tess_primitive), + GetTessSpacing(runtime_info.tess_spacing), + runtime_info.tess_clockwise ? "CW" : "CCW"); break; case Stage::Geometry: header += fmt::format("PRIMITIVE_IN {};" "PRIMITIVE_OUT {};" "VERTICES_OUT {};", - InputPrimitive(profile.input_topology), + InputPrimitive(runtime_info.input_topology), OutputPrimitive(program.output_topology), program.output_vertices); break; case Stage::Compute: diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h index a0dfdd818..3d02d873e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm.h @@ -12,12 +12,12 @@ namespace Shader::Backend::GLASM { -[[nodiscard]] std::string EmitGLASM(const Profile& profile, IR::Program& program, - Bindings& binding); +[[nodiscard]] std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, + IR::Program& program, Bindings& bindings); [[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { Bindings binding; - return EmitGLASM(profile, program, binding); + return EmitGLASM(profile, {}, program, binding); } } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From b382f57b286f72f89cff4e710ba6e6b34d22035d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 02:56:59 -0300 Subject: glasm: Fix output patch reads With this, Luigi's Mansion's sand renders properly. --- .../backend/glasm/emit_context.cpp | 12 ++++++++--- .../backend/glasm/emit_glasm_context_get_set.cpp | 23 ++++++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 659ff6d17..0f7d79843 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -21,6 +21,11 @@ std::string_view InterpDecorator(Interpolation interp) { } throw InvalidArgument("Invalid interpolation {}", interp); } + +bool IsInputArray(Stage stage) { + return stage == Stage::Geometry || stage == Stage::TessellationControl || + stage == Stage::TessellationEval; +} } // Anonymous namespace EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, @@ -76,7 +81,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile InterpDecorator(generic.interpolation), index, attr_stage, index, index); } } - if (stage == Stage::Geometry && info.loads_position) { + if (IsInputArray(stage) && info.loads_position) { Add("ATTRIB vertex_position=vertex.position;"); } if (info.uses_invocation_id) { @@ -96,8 +101,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile continue; } if (stage == Stage::TessellationControl) { - Add("OUTPUT result_patch_attrib{}[]={{result.patch.attrib[{}..{}]}};", index, index, - index); + Add("OUTPUT result_patch_attrib{}[]={{result.patch.attrib[{}..{}]}};" + "ATTRIB primitive_out_patch_attrib{}[]={{primitive.out.patch.attrib[{}..{}]}};", + index, index, index, index, index, index); } else { Add("ATTRIB primitive_patch_attrib{}[]={{primitive.patch.attrib[{}..{}]}};", index, index, index); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 34669160a..97b0e7409 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -20,15 +20,13 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset); } +bool IsInputArray(Stage stage) { + return stage == Stage::Geometry || stage == Stage::TessellationControl || + stage == Stage::TessellationEval; +} + std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) { - switch (ctx.stage) { - case Stage::TessellationControl: - case Stage::TessellationEval: - case Stage::Geometry: - return fmt::format("[{}]", vertex); - default: - return ""; - } + return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : ""; } } // Anonymous namespace @@ -77,7 +75,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal case IR::Attribute::PositionY: case IR::Attribute::PositionZ: case IR::Attribute::PositionW: - if (ctx.stage == Stage::Geometry) { + if (IsInputArray(ctx.stage)) { ctx.Add("MOV.F {}.x,vertex_position{}.{};", inst, VertexIndex(ctx, vertex), swizzle); } else { ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); @@ -164,7 +162,12 @@ void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { } const u32 index{IR::GenericPatchIndex(patch)}; const u32 element{IR::GenericPatchElement(patch)}; - ctx.Add("MOV.F {},result.patch.attrib[{}].{};", inst, index, "xyzw"[element]); + const char swizzle{"xyzw"[element]}; + if (ctx.stage == Stage::TessellationControl) { + ctx.Add("MOV.F {},primitive.out.patch.attrib[{}].{};", inst, index, swizzle); + } else { + ctx.Add("MOV.F {},primitive.patch.attrib[{}].{};", inst, index, swizzle); + } } void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value) { -- cgit v1.2.3 From 7dadb2bef3bd7f1038c61cb67c4248e1f7f324df Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 03:02:06 -0300 Subject: glasm: Simplify patch reads --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 97b0e7409..14fdc88f6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -163,11 +163,8 @@ void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { const u32 index{IR::GenericPatchIndex(patch)}; const u32 element{IR::GenericPatchElement(patch)}; const char swizzle{"xyzw"[element]}; - if (ctx.stage == Stage::TessellationControl) { - ctx.Add("MOV.F {},primitive.out.patch.attrib[{}].{};", inst, index, swizzle); - } else { - ctx.Add("MOV.F {},primitive.patch.attrib[{}].{};", inst, index, swizzle); - } + const std::string_view out{ctx.stage == Stage::TessellationControl ? ".out" : ""}; + ctx.Add("MOV.F {},primitive{}.patch.attrib[{}].{};", inst, out, index, swizzle); } void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value) { -- cgit v1.2.3 From 84feabac881443d27f84f8fec5eba6dc3b13b620 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 18:27:37 -0300 Subject: glasm: Implement forced early Z --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index edff04a44..0c2bbf284 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -261,7 +261,8 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } } -void SetupOptions(const IR::Program& program, const Profile& profile, std::string& header) { +void SetupOptions(const IR::Program& program, const Profile& profile, + const RuntimeInfo& runtime_info, std::string& header) { const Info& info{program.info}; const Stage stage{program.stage}; @@ -296,6 +297,9 @@ void SetupOptions(const IR::Program& program, const Profile& profile, std::strin header += "OPTION NV_viewport_array2;"; } } + if (stage == Stage::Fragment && runtime_info.force_early_z != 0) { + header += "OPTION NV_early_fragment_tests;"; + } const auto non_zero_frag_colors{info.stores_frag_color | std::views::drop(1)}; if (std::ranges::find(non_zero_frag_colors, true) != non_zero_frag_colors.end()) { header += "OPTION ARB_draw_buffers;"; @@ -380,7 +384,7 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I Precolor(ctx, program); EmitCode(ctx, program); std::string header{StageHeader(program.stage)}; - SetupOptions(program, profile, header); + SetupOptions(program, profile, runtime_info, header); switch (program.stage) { case Stage::TessellationControl: header += fmt::format("VERTICES_OUT {};", program.invocations); -- cgit v1.2.3 From c31521512fd49603ea42c93e2a6eac5d7985cd78 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 20:46:40 -0300 Subject: gl_shader_cache,glasm: Conditionally use typeless image reads extension --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0c2bbf284..8718cc7ec 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -271,8 +271,7 @@ void SetupOptions(const IR::Program& program, const Profile& profile, "OPTION NV_shader_storage_buffer;" "OPTION NV_gpu_program_fp64;" "OPTION NV_bindless_texture;" - "OPTION ARB_derivative_control;" - "OPTION EXT_shader_image_load_formatted;"; + "OPTION ARB_derivative_control;"; if (info.uses_int64_bit_atomics) { header += "OPTION NV_shader_atomic_int64;"; } @@ -297,6 +296,9 @@ void SetupOptions(const IR::Program& program, const Profile& profile, header += "OPTION NV_viewport_array2;"; } } + if (info.uses_typeless_image_reads && profile.support_typeless_image_loads) { + header += "OPTION EXT_shader_image_load_formatted;"; + } if (stage == Stage::Fragment && runtime_info.force_early_z != 0) { header += "OPTION NV_early_fragment_tests;"; } -- cgit v1.2.3 From ddf601919f0f415f19082be49f89c80eaba1352b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 20:55:04 -0300 Subject: glasm: Fix EmitVertex's optimization --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index b60c907df..962719ffb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -73,7 +73,7 @@ void EmitEpilogue(EmitContext& ctx) { } void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) { - if (stream.type == Type::U32 && stream.imm_u32) { + if (stream.type == Type::U32 && stream.imm_u32 == 0) { ctx.Add("EMIT;"); } else { ctx.Add("EMITS {};", stream); -- cgit v1.2.3 From 77d8c44b68c02bcea0ca07944fc6a87c336d72a5 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 20:59:24 -0300 Subject: glasm: Implement IsHelperInvocation --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 15380a955..4d2d7a928 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -70,7 +70,7 @@ void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst); void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitSampleId(EmitContext& ctx); -void EmitIsHelperInvocation(EmitContext& ctx); +void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst); void EmitYDirection(EmitContext& ctx); void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset); void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 962719ffb..1e236c487 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -168,8 +168,8 @@ void EmitSampleId(EmitContext& ctx) { NotImplemented(); } -void EmitIsHelperInvocation(EmitContext& ctx) { - NotImplemented(); +void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,fragment.helperthread.x;", inst); } void EmitYDirection(EmitContext& ctx) { -- cgit v1.2.3 From 89e341d56ab49ca38a83ba798c78453243006c12 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 21:01:05 -0300 Subject: glasm: Implement SampleId --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 4d2d7a928..2cc3acedf 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -69,7 +69,7 @@ void EmitSetOFlag(EmitContext& ctx); void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst); void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitInvocationId(EmitContext& ctx, IR::Inst& inst); -void EmitSampleId(EmitContext& ctx); +void EmitSampleId(EmitContext& ctx, IR::Inst& inst); void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst); void EmitYDirection(EmitContext& ctx); void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 1e236c487..756134d02 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -164,8 +164,8 @@ void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { ctx.Add("MOV.S {}.x,primitive_invocation.x;", inst); } -void EmitSampleId(EmitContext& ctx) { - NotImplemented(); +void EmitSampleId(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,fragment.sampleid.x;", inst); } void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) { -- cgit v1.2.3 From e565eb361a3518f61cc7c23cf4fbba3e0a0ea0f6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 21:14:11 -0300 Subject: glasm: Implement gl_Layer stores --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 14fdc88f6..7a7297801 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -134,6 +134,13 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ctx.Add("MOV.F result.clip[{}].x,{};", index, value); break; } + case IR::Attribute::Layer: + if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { + ctx.Add("MOV.F result.layer.x,{};", value); + } else { + // LOG_WARNING + } + break; case IR::Attribute::ViewportIndex: if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { ctx.Add("MOV.F result.viewport.x,{};", value); -- cgit v1.2.3 From 3a7ca6a7db5d9c895fceef21f9239dfcef2fcc8e Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 21:14:59 -0300 Subject: glasm: Reorder unreachable image atomic insts Reorder them to the bottom of the file for readability. --- .../backend/glasm/emit_glasm_image_atomic.cpp | 132 ++++++++++----------- 1 file changed, 66 insertions(+), 66 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp index a0b9866de..f82cf9ffc 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp @@ -8,6 +8,72 @@ namespace Shader::Backend::GLASM { +void EmitImageAtomicIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicInc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicDec32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, + [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitImageAtomicExchange32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& index, + [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { + throw NotImplementedException("GLASM instruction"); +} + void EmitBindlessImageAtomicIAdd32(EmitContext&) { throw LogicError("Unreachable instruction"); } @@ -96,70 +162,4 @@ void EmitBoundImageAtomicExchange32(EmitContext&) { throw LogicError("Unreachable instruction"); } -void EmitImageAtomicIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicInc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicDec32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicExchange32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From c8414e686f30b3bec7f179ee7ab800f223f8ece0 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 May 2021 21:42:48 -0300 Subject: glasm: Implement image atomics --- .../backend/glasm/emit_glasm_image.cpp | 153 +++++++++++++++++++ .../backend/glasm/emit_glasm_image_atomic.cpp | 165 --------------------- 2 files changed, 153 insertions(+), 165 deletions(-) delete mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 385ca51ac..a7def0897 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -205,6 +205,16 @@ std::string_view FormatStorage(ImageFormat format) { } throw InvalidArgument("Invalid image format {}", format); } + +template +void ImageAtomic(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, T value, + std::string_view op) { + const auto info{inst.Flags()}; + const std::string_view type{TextureType(info)}; + const std::string image{Image(ctx, info, index)}; + const Register ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("ATOMIM.{} {},{},{},{},{};", op, ret, value, coord, image, type); +} } // Anonymous namespace void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, @@ -590,6 +600,61 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Re ctx.Add("STOREIM.{} {},{},{},{};", format, image, color, coord, type); } +void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "ADD.U32"); +} + +void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarS32 value) { + ImageAtomic(ctx, inst, index, coord, value, "MIN.S32"); +} + +void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "MIN.U32"); +} + +void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarS32 value) { + ImageAtomic(ctx, inst, index, coord, value, "MAX.S32"); +} + +void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "MAX.U32"); +} + +void EmitImageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "IWRAP.U32"); +} + +void EmitImageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "DWRAP.U32"); +} + +void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "AND.U32"); +} + +void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "OR.U32"); +} + +void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord, + ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "XOR.U32"); +} + +void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, + Register coord, ScalarU32 value) { + ImageAtomic(ctx, inst, index, coord, value, "EXCH.U32"); +} + void EmitBindlessImageSampleImplicitLod(EmitContext&) { throw LogicError("Unreachable instruction"); } @@ -686,4 +751,92 @@ void EmitBoundImageWrite(EmitContext&) { throw LogicError("Unreachable instruction"); } +void EmitBindlessImageAtomicIAdd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicSMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicUMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicSMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicUMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicInc32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicDec32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicAnd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicOr32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicXor32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBindlessImageAtomicExchange32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicIAdd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicSMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicUMin32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicSMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicUMax32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicInc32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicDec32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicAnd32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicOr32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicXor32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitBoundImageAtomicExchange32(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp deleted file mode 100644 index f82cf9ffc..000000000 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image_atomic.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2021 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "shader_recompiler/backend/glasm/emit_context.h" -#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" -#include "shader_recompiler/frontend/ir/value.h" - -namespace Shader::Backend::GLASM { - -void EmitImageAtomicIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarS32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicInc32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicDec32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, [[maybe_unused]] Register coords, - [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitImageAtomicExchange32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& index, - [[maybe_unused]] Register coords, [[maybe_unused]] ScalarU32 value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitBindlessImageAtomicIAdd32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicSMin32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicUMin32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicSMax32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicUMax32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicInc32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicDec32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicAnd32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicOr32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicXor32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBindlessImageAtomicExchange32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicIAdd32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicSMin32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicUMin32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicSMax32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicUMax32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicInc32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicDec32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicAnd32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicOr32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicXor32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitBoundImageAtomicExchange32(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -} // namespace Shader::Backend::GLASM -- cgit v1.2.3 From e30d4fa976f608a79629e12cac25f7b951e6b8fb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 22 May 2021 18:29:43 -0300 Subject: glasm: Implement indirect attribute loads --- .../backend/glasm/emit_context.cpp | 3 +- src/shader_recompiler/backend/glasm/emit_context.h | 1 + .../backend/glasm/emit_glasm_context_get_set.cpp | 65 +++++++++++++++++++++- .../backend/glasm/emit_glasm_instructions.h | 2 +- 4 files changed, 65 insertions(+), 6 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 0f7d79843..b5b0e2204 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -30,9 +30,8 @@ bool IsInputArray(Stage stage) { EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, const RuntimeInfo& runtime_info_) - : profile{profile_}, runtime_info{runtime_info_} { + : info{program.info}, profile{profile_}, runtime_info{runtime_info_} { // FIXME: Temporary partial implementation - const auto& info{program.info}; u32 cbuf_index{}; for (const auto& desc : info.constant_buffer_descriptors) { if (desc.count != 1) { diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 1f057fdd5..057d74790 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -58,6 +58,7 @@ public: std::string code; RegAlloc reg_alloc{*this}; + const Info& info; const Profile& profile; const RuntimeInfo& runtime_info; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 7a7297801..b44c00c73 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -8,6 +8,7 @@ #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/shader_info.h" namespace Shader::Backend::GLASM { namespace { @@ -153,9 +154,67 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, } } -void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, - [[maybe_unused]] ScalarU32 vertex) { - throw NotImplementedException("GLASM instruction"); +void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex) { + // RC.x = base_index + // RC.y = masked_index + // RC.z = compare_index + ctx.Add("SHR.S RC.x,{},2;" + "AND.S RC.y,RC.x,3;" + "SHR.S RC.z,{},4;", + offset, offset); + + const Register ret{ctx.reg_alloc.Define(inst)}; + u32 num_endifs{}; + const auto read{[&](u32 compare_index, const std::array& values) { + ++num_endifs; + ctx.Add("SEQ.S.CC RC.w,RC.z,{};" // compare_index + "IF NE.w;" + // X + "SEQ.S.CC RC.w,RC.y,0;" + "IF NE.w;" + "MOV {}.x,{};" + "ELSE;" + // Y + "SEQ.S.CC RC.w,RC.y,1;" + "IF NE.w;" + "MOV {}.x,{};" + "ELSE;" + // Z + "SEQ.S.CC RC.w,RC.y,2;" + "IF NE.w;" + "MOV {}.x,{};" + "ELSE;" + // W + "MOV {}.x,{};" + "ENDIF;" + "ENDIF;" + "ENDIF;" + "ELSE;", + compare_index, ret, values[0], ret, values[1], ret, values[2], ret, values[3]); + }}; + const auto read_swizzled{[&](u32 compare_index, std::string_view value) { + const std::array values{fmt::format("{}.x", value), fmt::format("{}.y", value), + fmt::format("{}.z", value), fmt::format("{}.w", value)}; + read(compare_index, values); + }}; + if (ctx.info.loads_position) { + const u32 index{static_cast(IR::Attribute::PositionX)}; + if (IsInputArray(ctx.stage)) { + read_swizzled(index, fmt::format("vertex_position{}", VertexIndex(ctx, vertex))); + } else { + read_swizzled(index, fmt::format("{}.position", ctx.attrib_name)); + } + } + const u32 base_attribute_value{static_cast(IR::Attribute::Generic0X) >> 2}; + for (u32 index = 0; index < ctx.info.input_generics.size(); ++index) { + if (!ctx.info.input_generics[index].used) { + continue; + } + read_swizzled(index, fmt::format("in_attr{}{}[0]", index, VertexIndex(ctx, vertex))); + } + for (u32 i = 0; i < num_endifs; ++i) { + ctx.Add("ENDIF;"); + } } void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 2cc3acedf..e205c3d14 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -51,7 +51,7 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); -void EmitGetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarU32 vertex); +void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex); void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value); -- cgit v1.2.3 From 7fdf0d7d33ed1d0e860d6d1fca97bb66fee0d6a1 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sun, 23 May 2021 19:36:59 -0400 Subject: emit_glasm_context_get_set: Remove unused variable --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index b44c00c73..787612def 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -205,7 +205,6 @@ void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, read_swizzled(index, fmt::format("{}.position", ctx.attrib_name)); } } - const u32 base_attribute_value{static_cast(IR::Attribute::Generic0X) >> 2}; for (u32 index = 0; index < ctx.info.input_generics.size(); ++index) { if (!ctx.info.input_generics[index].used) { continue; -- cgit v1.2.3 From 0794273870dfc0ae9c217b6869845debfc8a8792 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 May 2021 20:16:09 -0300 Subject: glasm: Implement int64 add and subtract --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 4 ++-- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index e205c3d14..4dee9daf9 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -299,9 +299,9 @@ void EmitFPIsNan16(EmitContext& ctx, Register value); void EmitFPIsNan32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value); void EmitFPIsNan64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value); void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); -void EmitIAdd64(EmitContext& ctx, Register a, Register b); +void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); -void EmitISub64(EmitContext& ctx, Register a, Register b); +void EmitISub64(EmitContext& ctx, IR::Inst& inst, Register a, Register b); void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index f75fcba47..e5aac14c8 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -37,18 +37,16 @@ void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { } } -void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, - [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, Register a, Register b) { + ctx.LongAdd("ADD.S64 {}.x,{}.x,{}.x;", inst, a, b); } void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { ctx.Add("SUB.S {}.x,{},{};", inst, a, b); } -void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register a, - [[maybe_unused]] Register b) { - throw NotImplementedException("GLASM instruction"); +void EmitISub64(EmitContext& ctx, IR::Inst& inst, Register a, Register b) { + ctx.LongAdd("SUB.S64 {}.x,{}.x,{}.x;", inst, a, b); } void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { -- cgit v1.2.3 From c721767bccbcbd481c0e545b707754b270a7ea02 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 May 2021 20:17:05 -0300 Subject: 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(-) (limited to 'src/shader_recompiler/backend/glasm') 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 -- cgit v1.2.3 From 9fbfe7d676790dea160368eda6492e8feb6e2f4a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 24 May 2021 20:59:49 -0300 Subject: glasm: Fix usage counting on phi nodes --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 12 +++++++++--- .../backend/glasm/emit_glasm_instructions.h | 2 +- .../backend/glasm/emit_glasm_not_implemented.cpp | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8718cc7ec..2ce839059 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -178,6 +178,10 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { throw LogicError("Invalid opcode {}", inst->GetOpcode()); } +bool IsReference(IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::Reference; +} + void Precolor(EmitContext& ctx, const IR::Program& program) { for (IR::Block* const block : program.blocks) { for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { @@ -194,11 +198,13 @@ void Precolor(EmitContext& ctx, const IR::Program& program) { default: throw NotImplementedException("Phi node type {}", phi.Type()); } + // Insert phi moves before references to avoid overwritting them const size_t num_args{phi.NumArgs()}; for (size_t i = 0; i < num_args; ++i) { - IR::IREmitter{*phi.PhiBlock(i)}.PhiMove(phi, phi.Arg(i)); + IR::Block& phi_block{*phi.PhiBlock(i)}; + auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; + IR::IREmitter{phi_block, it}.PhiMove(phi, phi.Arg(i)); } - // Add reference to the phi node on the phi predecessor to avoid overwritting it for (size_t i = 0; i < num_args; ++i) { IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); } @@ -237,7 +243,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } } else { ctx.Add("MOV.S.CC RC,{};" - "BRK (EQ.x);" + "BRK(EQ.x);" "ENDREP;", eval(node.data.repeat.cond)); } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 5e038b332..cc7aa8e20 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -23,7 +23,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst); void EmitVoid(EmitContext& ctx); void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); -void EmitReference(EmitContext&); +void EmitReference(EmitContext&, const IR::Value& value); void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value); void EmitJoin(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 756134d02..3d7a3ebb4 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -17,18 +17,26 @@ namespace Shader::Backend::GLASM { #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) -void EmitPhi(EmitContext&, IR::Inst&) {} +void EmitPhi(EmitContext& ctx, IR::Inst& inst) { + const size_t num_args{inst.NumArgs()}; + for (size_t i = 0; i < num_args; ++i) { + ctx.reg_alloc.Consume(inst.Arg(i)); + } +} void EmitVoid(EmitContext&) {} -void EmitReference(EmitContext&) {} +void EmitReference(EmitContext& ctx, const IR::Value& value) { + ctx.reg_alloc.Consume(value); +} void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { + const Register phi_reg{ctx.reg_alloc.Consume(phi)}; + const Value eval_value{ctx.reg_alloc.Consume(value)}; + if (phi == value) { return; } - const Register phi_reg{ctx.reg_alloc.Consume(phi)}; - const Value eval_value{ctx.reg_alloc.Consume(value)}; switch (phi.Inst()->Flags()) { case IR::Type::U1: case IR::Type::U32: -- cgit v1.2.3 From ca05a13c62ad7693f8be924c168e400e8139b0d2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 25 May 2021 02:22:21 -0300 Subject: glasm: Catch more register leaks Add support for null registers. These are used when an instruction has no usages. This comes handy when an instruction is only used for its CC value, with the caveat of having to invalidate all pseudo-instructions before defining the instruction itself in the register allocator. This commits changes this. Workaround a bug on Nvidia's condition codes conditional execution using branches. --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 8 ++- .../glasm/emit_glasm_bitwise_conversion.cpp | 8 ++- .../backend/glasm/emit_glasm_composite.cpp | 4 +- .../backend/glasm/emit_glasm_image.cpp | 27 ++++++---- .../backend/glasm/emit_glasm_integer.cpp | 58 +++++++++++++++------- .../backend/glasm/emit_glasm_warp.cpp | 6 ++- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 28 +++++++++-- src/shader_recompiler/backend/glasm/reg_alloc.h | 16 ++++-- 8 files changed, 114 insertions(+), 41 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 2ce839059..4aa3682c2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -203,7 +203,13 @@ void Precolor(EmitContext& ctx, const IR::Program& program) { for (size_t i = 0; i < num_args; ++i) { IR::Block& phi_block{*phi.PhiBlock(i)}; auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; - IR::IREmitter{phi_block, it}.PhiMove(phi, phi.Arg(i)); + IR::IREmitter ir{phi_block, it}; + const IR::Value arg{phi.Arg(i)}; + if (arg.IsImmediate()) { + ir.PhiMove(phi, arg); + } else { + ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); + } } for (size_t i = 0; i < num_args; ++i) { IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp index 808c72105..9201ccd39 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp @@ -23,7 +23,13 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) { } void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { - ctx.Add("MOV.S {},{};", inst, ScalarS32{ctx.reg_alloc.Consume(value)}); + // Fake one usage to get a real register out of the condition + inst.DestructiveAddUsage(1); + const Register ret{ctx.reg_alloc.Define(inst)}; + const ScalarS32 input{ctx.reg_alloc.Consume(value)}; + if (ret != input) { + ctx.Add("MOV.S {},{};", ret, input); + } } void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index d829f05b3..bff0b7c1c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp @@ -52,7 +52,9 @@ void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, Objec // The input composite is not aliased with the return value so we have to copy it before // hand. But the insert object is not aliased with the return value, so we don't have to // worry about that - ctx.Add("MOV.{} {},{};MOV.{} {}.{},{};", type, ret, composite, type, ret, swizzle, object); + ctx.Add("MOV.{} {},{};" + "MOV.{} {}.{},{};", + type, ret, composite, type, ret, swizzle, object); } else { // The return value is alised so we can just insert the object, it doesn't matter if it's // aliased diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index a7def0897..34725b8c6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -181,7 +181,6 @@ void StoreSparse(EmitContext& ctx, IR::Inst* sparse_inst) { ctx.Add("MOV.S {},-1;" "MOV.S {}(NONRESIDENT),0;", sparse_ret, sparse_ret); - sparse_inst->Invalidate(); } std::string_view FormatStorage(ImageFormat format) { @@ -215,12 +214,20 @@ void ImageAtomic(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Regis const Register ret{ctx.reg_alloc.Define(inst)}; ctx.Add("ATOMIM.{} {},{},{},{},{};", op, ret, value, coord, image, type); } + +IR::Inst* PrepareSparse(IR::Inst& inst) { + const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + if (sparse_inst) { + sparse_inst->Invalidate(); + } + return sparse_inst; +} } // Anonymous namespace void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, Register bias_lc, const IR::Value& offset) { const auto info{inst.Flags()}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view lod_clamp_mod{info.has_lod_clamp ? ".LODCLAMP" : ""}; const std::string_view type{TextureType(info)}; @@ -259,7 +266,7 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, ScalarF32 lod, const IR::Value& offset) { const auto info{inst.Flags()}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -288,7 +295,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: } const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)}; const Register bias_lc_vec{ctx.reg_alloc.Consume(bias_lc)}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -393,7 +400,7 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR:: } const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)}; const ScalarF32 lod_val{ctx.reg_alloc.Consume(lod)}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -436,7 +443,7 @@ void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; const auto info{inst.Flags()}; const char comp{"xyzw"[info.gather_component]}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -462,7 +469,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde // Allocate offsets early so they don't overwrite any consumed register const auto [off_x, off_y]{AllocOffsetsRegs(ctx, offset2)}; const auto info{inst.Flags()}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -500,7 +507,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde 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 auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -547,7 +554,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, dpdx = ScopedRegister{ctx.reg_alloc}; dpdy = ScopedRegister{ctx.reg_alloc}; } - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; const std::string texture{Texture(ctx, info, index)}; @@ -581,7 +588,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord) { const auto info{inst.Flags()}; - const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; + const auto sparse_inst{PrepareSparse(inst)}; const std::string_view format{FormatStorage(info.image_format)}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view type{TextureType(info)}; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index e5aac14c8..e9d1bae05 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -9,6 +9,17 @@ namespace Shader::Backend::GLASM { void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { + const std::array flags{ + inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp), + inst.GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp), + }; + for (IR::Inst* const flag_inst : flags) { + if (flag_inst) { + flag_inst->Invalidate(); + } + } const bool cc{inst.HasAssociatedPseudoOperation()}; const std::string_view cc_mod{cc ? ".CC" : ""}; if (cc) { @@ -19,20 +30,22 @@ void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { if (!cc) { return; } - static constexpr std::array masks{"EQ", "SF", "CF", "OF"}; - const std::array flags{ - inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp), - inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp), - inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp), - inst.GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp), - }; - for (size_t i = 0; i < flags.size(); ++i) { - if (flags[i]) { - const auto flag_ret{ctx.reg_alloc.Define(*flags[i])}; - ctx.Add("MOV.S {},0;" - "MOV.S {}({}.x),-1;", - flag_ret, flag_ret, masks[i]); - flags[i]->Invalidate(); + static constexpr std::array masks{"", "SF", "CF", "OF"}; + for (size_t flag_index = 0; flag_index < flags.size(); ++flag_index) { + if (!flags[flag_index]) { + continue; + } + const auto flag_ret{ctx.reg_alloc.Define(*flags[flag_index])}; + if (flag_index == 0) { + ctx.Add("SEQ.S {}.x,{}.x,0;", flag_ret, ret); + } else { + // We could use conditional execution here, but it's broken on Nvidia's compiler + ctx.Add("IF {}.x;" + "MOV.S {}.x,-1;" + "ELSE;" + "MOV.S {}.x,0;" + "ENDIF;", + masks[flag_index], flag_ret, flag_ret); } } } @@ -136,6 +149,17 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scal void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset, ScalarU32 count) { + const auto zero = inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp); + const auto sign = inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp); + if (zero) { + zero->Invalidate(); + } + if (sign) { + sign->Invalidate(); + } + if (zero || sign) { + ctx.reg_alloc.InvalidateConditionCodes(); + } const Register ret{ctx.reg_alloc.Define(inst)}; if (count.type != Type::Register && offset.type != Type::Register) { ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base); @@ -145,13 +169,11 @@ void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, Scal "BFE.U {},RC,{};", count, offset, ret, base); } - if (const auto zero = inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)) { + if (zero) { ctx.Add("SEQ.S {},{},0;", *zero, ret); - zero->Invalidate(); } - if (const auto sign = inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)) { + if (sign) { ctx.Add("SLT.S {},{},0;", *sign, ret); - sign->Invalidate(); } } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index af0e13d43..6e30790bb 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -51,6 +51,10 @@ void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) { static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, const IR::Value& clamp, const IR::Value& segmentation_mask, std::string_view op) { + IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; + if (in_bounds) { + in_bounds->Invalidate(); + } std::string mask; if (clamp.IsImmediate() && segmentation_mask.IsImmediate()) { mask = fmt::to_string(clamp.U32() | (segmentation_mask.U32() << 8)); @@ -61,13 +65,11 @@ static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 ScalarU32{ctx.reg_alloc.Consume(clamp)}); } const Register value_ret{ctx.reg_alloc.Define(inst)}; - IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; if (in_bounds) { const Register bounds_ret{ctx.reg_alloc.Define(*in_bounds)}; ctx.Add("SHF{}.U {},{},{},{};" "MOV.U {}.x,{}.y;", op, bounds_ret, value, index, mask, value_ret, bounds_ret); - in_bounds->Invalidate(); } else { ctx.Add("SHF{}.U {},{},{},{};" "MOV.U {}.x,{}.y;", diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 707b22247..c55a833c6 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -22,11 +22,19 @@ Register RegAlloc::LongDefine(IR::Inst& inst) { } Value RegAlloc::Peek(const IR::Value& value) { - return value.IsImmediate() ? MakeImm(value) : PeekInst(*value.InstRecursive()); + if (value.IsImmediate()) { + return MakeImm(value); + } else { + return PeekInst(*value.Inst()); + } } Value RegAlloc::Consume(const IR::Value& value) { - return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive()); + if (value.IsImmediate()) { + return MakeImm(value); + } else { + return ConsumeInst(*value.Inst()); + } } void RegAlloc::Unref(IR::Inst& inst) { @@ -88,7 +96,14 @@ Value RegAlloc::MakeImm(const IR::Value& value) { } Register RegAlloc::Define(IR::Inst& inst, bool is_long) { - inst.SetDefinition(Alloc(is_long)); + if (inst.HasUses()) { + inst.SetDefinition(Alloc(is_long)); + } else { + Id id{}; + id.is_long.Assign(is_long ? 1 : 0); + id.is_null.Assign(1); + inst.SetDefinition(id); + } return Register{PeekInst(inst)}; } @@ -115,10 +130,12 @@ Id RegAlloc::Alloc(bool is_long) { num_regs = std::max(num_regs, reg + 1); use[reg] = true; Id ret{}; - ret.index.Assign(static_cast(reg)); + ret.is_valid.Assign(1); ret.is_long.Assign(is_long ? 1 : 0); ret.is_spill.Assign(0); ret.is_condition_code.Assign(0); + ret.is_null.Assign(0); + ret.index.Assign(static_cast(reg)); return ret; } } @@ -126,6 +143,9 @@ Id RegAlloc::Alloc(bool is_long) { } void RegAlloc::Free(Id id) { + if (id.is_valid == 0) { + throw LogicError("Freeing invalid register"); + } if (id.is_spill != 0) { throw NotImplementedException("Free spill"); } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 41b7c92be..b97c84146 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -35,10 +35,12 @@ enum class Type : u32 { struct Id { union { u32 raw; - BitField<0, 29, u32> index; - BitField<29, 1, u32> is_long; - BitField<30, 1, u32> is_spill; - BitField<31, 1, u32> is_condition_code; + BitField<0, 1, u32> is_valid; + BitField<1, 1, u32> is_long; + BitField<2, 1, u32> is_spill; + BitField<3, 1, u32> is_condition_code; + BitField<4, 1, u32> is_null; + BitField<5, 27, u32> index; }; bool operator==(Id rhs) const noexcept { @@ -164,12 +166,18 @@ auto FormatTo(FormatContext& ctx, Id id) { throw NotImplementedException("Spill emission"); } if constexpr (scalar) { + if (id.is_null != 0) { + return fmt::format_to(ctx.out(), "{}", id.is_long != 0 ? "DC.x" : "RC.x"); + } if (id.is_long != 0) { return fmt::format_to(ctx.out(), "D{}.x", id.index.Value()); } else { return fmt::format_to(ctx.out(), "R{}.x", id.index.Value()); } } else { + if (id.is_null != 0) { + return fmt::format_to(ctx.out(), "{}", id.is_long != 0 ? "DC" : "RC"); + } if (id.is_long != 0) { return fmt::format_to(ctx.out(), "D{}", id.index.Value()); } else { -- cgit v1.2.3 From 379b305b4bc09799d53981fa6e5d9cbe6be99561 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 25 May 2021 02:34:08 -0300 Subject: glasm: Throw when there are register leaks --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 +++ src/shader_recompiler/backend/glasm/reg_alloc.h | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 4aa3682c2..0e9dc06a6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -271,6 +271,9 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { break; } } + if (!ctx.reg_alloc.IsEmpty()) { + throw LogicError("Register allocator is not empty"); + } } void SetupOptions(const IR::Program& program, const Profile& profile, diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index b97c84146..019e1bc0f 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -128,6 +128,10 @@ public: return num_used_long_registers; } + [[nodiscard]] bool IsEmpty() const noexcept { + return register_use.none() && long_register_use.none(); + } + /// Returns true if the instruction is expected to be aliased to another static bool IsAliased(const IR::Inst& inst); -- cgit v1.2.3 From 75fd0079db9ac2f3bc6bcf182ed080a58538ed06 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 25 May 2021 02:46:51 -0300 Subject: glasm: Remove unnecessary value types --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 12 +------- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 8 +++--- src/shader_recompiler/backend/glasm/reg_alloc.h | 33 +--------------------- 3 files changed, 6 insertions(+), 47 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 0e9dc06a6..5ffefaad2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -49,8 +49,7 @@ public: inst = ir_value.InstRecursive(); reg = Register{value}; } else { - const bool is_long{value.type == Type::F64 || value.type == Type::U64}; - reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); + reg = value.type == Type::U64 ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); } switch (value.type) { case Type::Register: @@ -59,18 +58,9 @@ public: case Type::U32: ctx.Add("MOV.U {}.x,{};", reg, value.imm_u32); break; - case Type::S32: - ctx.Add("MOV.S {}.x,{};", reg, value.imm_s32); - break; - case Type::F32: - ctx.Add("MOV.F {}.x,{};", reg, value.imm_f32); - break; case Type::U64: ctx.Add("MOV.U64 {}.x,{};", reg, value.imm_u64); break; - case Type::F64: - ctx.Add("MOV.F64 {}.x,{};", reg, value.imm_f64); - break; } } diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index c55a833c6..4c046db6e 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -78,16 +78,16 @@ Value RegAlloc::MakeImm(const IR::Value& value) { ret.imm_u32 = value.U32(); break; case IR::Type::F32: - ret.type = Type::F32; - ret.imm_f32 = value.F32(); + ret.type = Type::U32; + ret.imm_u32 = Common::BitCast(value.F32()); break; case IR::Type::U64: ret.type = Type::U64; ret.imm_u64 = value.U64(); break; case IR::Type::F64: - ret.type = Type::F64; - ret.imm_f64 = value.F64(); + ret.type = Type::U64; + ret.imm_u64 = Common::BitCast(value.F64()); break; default: throw NotImplementedException("Immediate type {}", value.Type()); diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 019e1bc0f..5a703daf2 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -26,10 +26,7 @@ enum class Type : u32 { Void, Register, U32, - S32, - F32, U64, - F64, }; struct Id { @@ -57,10 +54,7 @@ struct Value { union { Id id; u32 imm_u32; - s32 imm_s32; - f32 imm_f32; u64 imm_u64; - f64 imm_f64; }; bool operator==(const Value& rhs) const noexcept { @@ -74,14 +68,8 @@ struct Value { return id == rhs.id; case Type::U32: return imm_u32 == rhs.imm_u32; - case Type::S32: - return imm_s32 == rhs.imm_s32; - case Type::F32: - return Common::BitCast(imm_f32) == Common::BitCast(rhs.imm_f32); case Type::U64: return imm_u64 == rhs.imm_u64; - case Type::F64: - return Common::BitCast(imm_f64) == Common::BitCast(rhs.imm_f64); } return false; } @@ -245,12 +233,7 @@ struct fmt::formatter { return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: return fmt::format_to(ctx.out(), "{}", value.imm_u32); - case Shader::Backend::GLASM::Type::S32: - return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_s32)); - case Shader::Backend::GLASM::Type::F32: - return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); case Shader::Backend::GLASM::Type::U64: - case Shader::Backend::GLASM::Type::F64: break; } throw Shader::InvalidArgument("Invalid value type {}", value.type); @@ -271,12 +254,7 @@ struct fmt::formatter { return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: return fmt::format_to(ctx.out(), "{}", static_cast(value.imm_u32)); - case Shader::Backend::GLASM::Type::S32: - return fmt::format_to(ctx.out(), "{}", value.imm_s32); - case Shader::Backend::GLASM::Type::F32: - return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_f32)); case Shader::Backend::GLASM::Type::U64: - case Shader::Backend::GLASM::Type::F64: break; } throw Shader::InvalidArgument("Invalid value type {}", value.type); @@ -296,13 +274,8 @@ struct fmt::formatter { case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: - return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u32)); - case Shader::Backend::GLASM::Type::S32: - return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_s32)); - case Shader::Backend::GLASM::Type::F32: - return fmt::format_to(ctx.out(), "{}", value.imm_f32); + return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u32)); case Shader::Backend::GLASM::Type::U64: - case Shader::Backend::GLASM::Type::F64: break; } throw Shader::InvalidArgument("Invalid value type {}", value.type); @@ -322,13 +295,9 @@ struct fmt::formatter { case Shader::Backend::GLASM::Type::Register: return Shader::Backend::GLASM::FormatTo(ctx, value.id); case Shader::Backend::GLASM::Type::U32: - case Shader::Backend::GLASM::Type::S32: - case Shader::Backend::GLASM::Type::F32: break; case Shader::Backend::GLASM::Type::U64: return fmt::format_to(ctx.out(), "{}", Common::BitCast(value.imm_u64)); - case Shader::Backend::GLASM::Type::F64: - return fmt::format_to(ctx.out(), "{}", value.imm_f64); } throw Shader::InvalidArgument("Invalid value type {}", value.type); } -- cgit v1.2.3 From 70c9281fbffbf5f68a267ba85f6e4b3c122fa3ac Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 25 May 2021 02:48:03 -0300 Subject: glasm: Fix INeg32 on negative immediates --- src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index e9d1bae05..cea45a3e0 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -67,7 +67,11 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { } void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { - ctx.Add("MOV.S {},-{};", inst, value); + if (value.type != Type::Register && static_cast(value.imm_u32) < 0) { + ctx.Add("MOV.S {},{};", inst, -static_cast(value.imm_u32)); + } else { + ctx.Add("MOV.S {},-{};", inst, value); + } } void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value) { -- cgit v1.2.3 From 48aafe0961a2ddfb52b627c6ba6bce8276330550 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 25 May 2021 17:37:35 -0300 Subject: glasm: Release phi node registers after they are no longer needed --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 53 +++++++++------------- .../backend/glasm/emit_glasm_not_implemented.cpp | 39 +++++++++++++--- 2 files changed, 54 insertions(+), 38 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 5ffefaad2..4f838b699 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -172,38 +172,29 @@ bool IsReference(IR::Inst& inst) { return inst.GetOpcode() == IR::Opcode::Reference; } -void Precolor(EmitContext& ctx, const IR::Program& program) { +void PrecolorInst(IR::Inst& phi) { + // Insert phi moves before references to avoid overwritting other phis + const size_t num_args{phi.NumArgs()}; + for (size_t i = 0; i < num_args; ++i) { + IR::Block& phi_block{*phi.PhiBlock(i)}; + auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; + IR::IREmitter ir{phi_block, it}; + const IR::Value arg{phi.Arg(i)}; + if (arg.IsImmediate()) { + ir.PhiMove(phi, arg); + } else { + ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); + } + } + for (size_t i = 0; i < num_args; ++i) { + IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); + } +} + +void Precolor(const IR::Program& program) { for (IR::Block* const block : program.blocks) { for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { - switch (phi.Arg(0).Type()) { - case IR::Type::U1: - case IR::Type::U32: - case IR::Type::F32: - ctx.reg_alloc.Define(phi); - break; - case IR::Type::U64: - case IR::Type::F64: - ctx.reg_alloc.LongDefine(phi); - break; - default: - throw NotImplementedException("Phi node type {}", phi.Type()); - } - // Insert phi moves before references to avoid overwritting them - const size_t num_args{phi.NumArgs()}; - for (size_t i = 0; i < num_args; ++i) { - IR::Block& phi_block{*phi.PhiBlock(i)}; - auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; - IR::IREmitter ir{phi_block, it}; - const IR::Value arg{phi.Arg(i)}; - if (arg.IsImmediate()) { - ir.PhiMove(phi, arg); - } else { - ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); - } - } - for (size_t i = 0; i < num_args; ++i) { - IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); - } + PrecolorInst(phi); } } } @@ -388,7 +379,7 @@ std::string_view GetTessSpacing(TessSpacing spacing) { std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, Bindings& bindings) { EmitContext ctx{program, bindings, profile, runtime_info}; - Precolor(ctx, program); + Precolor(program); EmitCode(ctx, program); std::string header{StageHeader(program.stage)}; SetupOptions(program, profile, runtime_info, header); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 3d7a3ebb4..e9d1e0d6b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -17,10 +17,30 @@ namespace Shader::Backend::GLASM { #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) -void EmitPhi(EmitContext& ctx, IR::Inst& inst) { - const size_t num_args{inst.NumArgs()}; +static void DefinePhi(EmitContext& ctx, IR::Inst& phi) { + switch (phi.Arg(0).Type()) { + case IR::Type::U1: + case IR::Type::U32: + case IR::Type::F32: + ctx.reg_alloc.Define(phi); + break; + case IR::Type::U64: + case IR::Type::F64: + ctx.reg_alloc.LongDefine(phi); + break; + default: + throw NotImplementedException("Phi node type {}", phi.Type()); + } +} + +void EmitPhi(EmitContext& ctx, IR::Inst& phi) { + const size_t num_args{phi.NumArgs()}; for (size_t i = 0; i < num_args; ++i) { - ctx.reg_alloc.Consume(inst.Arg(i)); + ctx.reg_alloc.Consume(phi.Arg(i)); + } + if (!phi.Definition().is_valid) { + // The phi node wasn't forward defined + DefinePhi(ctx, phi); } } @@ -30,14 +50,19 @@ void EmitReference(EmitContext& ctx, const IR::Value& value) { ctx.reg_alloc.Consume(value); } -void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { - const Register phi_reg{ctx.reg_alloc.Consume(phi)}; +void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) { + IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())}; + if (!phi.Definition().is_valid) { + // The phi node wasn't forward defined + DefinePhi(ctx, phi); + } + const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})}; const Value eval_value{ctx.reg_alloc.Consume(value)}; - if (phi == value) { + if (phi_reg == eval_value) { return; } - switch (phi.Inst()->Flags()) { + switch (phi.Flags()) { case IR::Type::U1: case IR::Type::U32: case IR::Type::F32: -- cgit v1.2.3 From 8763cc1ff7909cb72902db7988f9e205dd0953d3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 03:34:59 -0300 Subject: glasm: Fix global memory callbacks --- src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 33af83212..26b03587e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -37,8 +37,8 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e 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 + 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 @@ -48,9 +48,10 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e "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); + "{}" + "ELSE;", + ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address, + address, address, index, then_expr); } if (!else_expr.empty()) { ctx.Add("{}", else_expr); -- cgit v1.2.3 From b9c8814ea978d2192522f9c85c07c00280bc1696 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 15:40:16 -0300 Subject: glasm: Implement undef instructions --- .../backend/glasm/emit_glasm_instructions.h | 10 +++++----- .../backend/glasm/emit_glasm_not_implemented.cpp | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index cc7aa8e20..c24c7a71d 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -74,11 +74,11 @@ void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst); void EmitYDirection(EmitContext& ctx); void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset); void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value); -void EmitUndefU1(EmitContext& ctx); -void EmitUndefU8(EmitContext& ctx); -void EmitUndefU16(EmitContext& ctx); -void EmitUndefU32(EmitContext& ctx); -void EmitUndefU64(EmitContext& ctx); +void EmitUndefU1(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU8(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU16(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU32(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU64(EmitContext& ctx, IR::Inst& inst); 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); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index e9d1e0d6b..c76b45b8b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -209,24 +209,24 @@ void EmitYDirection(EmitContext& ctx) { NotImplemented(); } -void EmitUndefU1(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,0;", inst); } -void EmitUndefU8(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU8(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,0;", inst); } -void EmitUndefU16(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,0;", inst); } -void EmitUndefU32(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) { + ctx.Add("MOV.S {}.x,0;\n", inst); } -void EmitUndefU64(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) { + ctx.LongAdd("MOV.S64 {}.x,0;", inst); } void EmitGetZeroFromOp(EmitContext& ctx) { -- cgit v1.2.3 From 586c785366307cb3c648bd33345b431b8312612d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 15:41:53 -0300 Subject: glasm: Skip phi moves on undefined instructions --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index c76b45b8b..022b6584c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -58,7 +58,9 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& } const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})}; const Value eval_value{ctx.reg_alloc.Consume(value)}; - + if (!value.IsImmediate() && IR::IsUndef(RegAlloc::AliasInst(*value.Inst()))) { + return; + } if (phi_reg == eval_value) { return; } -- cgit v1.2.3 From f58f79c85dad7ad018a015cc6913f2789540ec22 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 16:00:36 -0300 Subject: glasm: Implement Y direction --- src/shader_recompiler/backend/glasm/emit_context.h | 2 ++ src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 +++ src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 5 +++-- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 057d74790..cd4213cb7 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -70,6 +70,8 @@ public: Stage stage{}; std::string_view stage_name = "invalid"; std::string_view attrib_name = "invalid"; + + bool uses_y_direction{}; }; } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 4f838b699..2a0524609 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -439,6 +439,9 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I "MOV.F FSWZB[2],1;" "MOV.F FSWZB[3],-1;"; } + if (ctx.uses_y_direction) { + header += "PARAM y_direction[1]={state.material.front.ambient};"; + } ctx.code.insert(0, header); ctx.code += "END"; return ctx.code; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index c24c7a71d..7b0f75405 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -71,7 +71,7 @@ void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitInvocationId(EmitContext& ctx, IR::Inst& inst); void EmitSampleId(EmitContext& ctx, IR::Inst& inst); void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst); -void EmitYDirection(EmitContext& ctx); +void EmitYDirection(EmitContext& ctx, IR::Inst& inst); void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset); void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value); void EmitUndefU1(EmitContext& ctx, IR::Inst& inst); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 022b6584c..2a92d9df5 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -207,8 +207,9 @@ void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) { ctx.Add("MOV.S {}.x,fragment.helperthread.x;", inst); } -void EmitYDirection(EmitContext& ctx) { - NotImplemented(); +void EmitYDirection(EmitContext& ctx, IR::Inst& inst) { + ctx.uses_y_direction = true; + ctx.Add("MOV.F {}.x,y_direction[0].w;", inst); } void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) { -- cgit v1.2.3 From adb591a757ccb289634920d51cf519b515ca32b6 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 18:32:59 -0300 Subject: glasm: Use storage buffers instead of global memory when possible --- .../backend/glasm/emit_context.cpp | 13 +- src/shader_recompiler/backend/glasm/emit_glasm.h | 5 +- .../backend/glasm/emit_glasm_atomic.cpp | 351 ------------------- .../backend/glasm/emit_glasm_memory.cpp | 380 ++++++++++++++++++++- 4 files changed, 380 insertions(+), 369 deletions(-) delete mode 100644 src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index b5b0e2204..e18526816 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -7,6 +7,7 @@ #include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/profile.h" namespace Shader::Backend::GLASM { namespace { @@ -40,13 +41,21 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); ++cbuf_index; } + u32 ssbo_index{}; for (const auto& desc : info.storage_buffers_descriptors) { if (desc.count != 1) { throw NotImplementedException("Storage buffer descriptor array"); } + if (runtime_info.glasm_use_storage_buffers) { + Add("STORAGE ssbo{}[]={{program.storage[{}]}};", ssbo_index, bindings.storage_buffer); + ++bindings.storage_buffer; + ++ssbo_index; + } } - if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { - Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); + if (!runtime_info.glasm_use_storage_buffers) { + if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { + Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); + } } stage = program.stage; switch (program.stage) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h index 3d02d873e..3df32a4a6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm.h @@ -15,9 +15,10 @@ namespace Shader::Backend::GLASM { [[nodiscard]] std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, Bindings& bindings); -[[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { +[[nodiscard]] inline std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, + IR::Program& program) { Bindings binding; - return EmitGLASM(profile, {}, program, binding); + return EmitGLASM(profile, runtime_info, program, binding); } } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp deleted file mode 100644 index e72b252a3..000000000 --- a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2021 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "shader_recompiler/backend/glasm/emit_context.h" -#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" -#include "shader_recompiler/frontend/ir/value.h" - -namespace Shader::Backend::GLASM { -namespace { -void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, - std::string_view then_expr, std::string_view else_expr = {}) { - // Operate on bindless SSBO, call the expression with bounds checking - // address = c[binding].xy - // length = c[binding].z - const u32 sb_binding{binding.U32()}; - ctx.Add("PK64.U DC,c[{}];" // pointer = address - "CVT.U64.U32 DC.z,{};" // offset = uint64_t(offset) - "ADD.U64 DC.x,DC.x,DC.z;" // pointer += offset - "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length - sb_binding, offset, offset, sb_binding); - if (else_expr.empty()) { - ctx.Add("IF NE.x;{}ENDIF;", then_expr); - } else { - ctx.Add("IF NE.x;{}ELSE;{}ENDIF;", then_expr, else_expr); - } -} - -template -void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, - ValueType value, std::string_view operation, std::string_view size) { - const Register ret{ctx.reg_alloc.Define(inst)}; - StorageOp(ctx, binding, offset, - fmt::format("ATOM.{}.{} {},{},DC.x;", operation, size, ret, value)); -} -} // namespace - -void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.ADD.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarS32 value) { - ctx.Add("ATOMS.MIN.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.MIN.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarS32 value) { - ctx.Add("ATOMS.MAX.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.MAX.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.IWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.DWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.AND.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.OR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.XOR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - ScalarU32 value) { - ctx.Add("ATOMS.EXCH.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, - Register value) { - ctx.LongAdd("ATOMS.EXCH.U64 {}.x,{},shared_mem[{}];", inst, value, pointer_offset); -} - -void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "ADD", "U32"); -} - -void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarS32 value) { - Atom(ctx, inst, binding, offset, value, "MIN", "S32"); -} - -void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "MIN", "U32"); -} - -void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarS32 value) { - Atom(ctx, inst, binding, offset, value, "MAX", "S32"); -} - -void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "MAX", "U32"); -} - -void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "IWRAP", "U32"); -} - -void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "DWRAP", "U32"); -} - -void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "AND", "U32"); -} - -void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "OR", "U32"); -} - -void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "XOR", "U32"); -} - -void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarU32 value) { - Atom(ctx, inst, binding, offset, value, "EXCH", "U32"); -} - -void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "ADD", "U64"); -} - -void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MIN", "S64"); -} - -void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MIN", "U64"); -} - -void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MAX", "S64"); -} - -void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MAX", "U64"); -} - -void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "AND", "U64"); -} - -void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "OR", "U64"); -} - -void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "XOR", "U64"); -} - -void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "EXCH", "U64"); -} - -void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, ScalarF32 value) { - Atom(ctx, inst, binding, offset, value, "ADD", "F32"); -} - -void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "ADD", "F16x2"); -} - -void EmitStorageAtomicAddF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& binding, - [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MIN", "F16x2"); -} - -void EmitStorageAtomicMinF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& binding, - [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, - ScalarU32 offset, Register value) { - Atom(ctx, inst, binding, offset, value, "MAX", "F16x2"); -} - -void EmitStorageAtomicMaxF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, - [[maybe_unused]] const IR::Value& binding, - [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicIAdd32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicSMin32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicUMin32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicSMax32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicUMax32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicInc32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicDec32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicAnd32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicOr32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicXor32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicExchange32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicIAdd64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicSMin64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicUMin64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicSMax64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicUMax64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicInc64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicDec64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicAnd64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicOr64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicXor64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicExchange64(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicAddF32(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicAddF16x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicAddF32x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicMinF16x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicMinF32x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicMaxF16x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} - -void EmitGlobalAtomicMaxF32x2(EmitContext&) { - throw NotImplementedException("GLASM instruction"); -} -} // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 26b03587e..90dbb80d2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -8,6 +8,7 @@ #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/frontend/ir/value.h" +#include "shader_recompiler/profile.h" namespace Shader::Backend::GLASM { namespace { @@ -29,7 +30,7 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, } } -void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_expr, +void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std::string_view 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) { @@ -44,14 +45,22 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e "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;", + "IF NE.x;" // a && b + "SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address, - address, address, index, then_expr); + address, address); + if (pointer_based) { + ctx.Add("PK64.U DC.y,c[{}];" // host_ssbo = cbuf + "ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset + "{}" + "ELSE;", + index, expr); + } else { + ctx.Add("CVT.U32.U64 RC.x,DC.x;" + "{},ssbo{}[RC.x];" + "ELSE;", + expr, index); + } } if (!else_expr.empty()) { ctx.Add("{}", else_expr); @@ -64,25 +73,54 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e template 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)); + if (ctx.runtime_info.glasm_use_storage_buffers) { + ctx.Add("STB.{} {},ssbo{}[{}];", size, value, binding.U32(), offset); + } else { + StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, value)); + } } void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, std::string_view size) { const Register ret{ctx.reg_alloc.Define(inst)}; - StorageOp(ctx, binding, offset, fmt::format("LOAD.{} {},DC.x;", size, ret), - fmt::format("MOV.U {},{{0,0,0,0}};", ret)); + if (ctx.runtime_info.glasm_use_storage_buffers) { + ctx.Add("LDB.{} {},ssbo{}[{}];", size, ret, binding.U32(), offset); + } else { + 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)); + if (ctx.runtime_info.glasm_use_storage_buffers) { + GlobalStorageOp(ctx, address, false, fmt::format("STB.{} {}", size, value)); + } else { + GlobalStorageOp(ctx, address, true, 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)); + if (ctx.runtime_info.glasm_use_storage_buffers) { + GlobalStorageOp(ctx, address, false, fmt::format("LDB.{} {}", size, ret)); + } else { + GlobalStorageOp(ctx, address, true, fmt::format("LOAD.{} {},DC.x;", size, ret), + fmt::format("MOV.S {},0;", ret)); + } +} + +template +void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, + ValueType value, std::string_view operation, std::string_view size) { + const Register ret{ctx.reg_alloc.Define(inst)}; + if (ctx.runtime_info.glasm_use_storage_buffers) { + ctx.Add("ATOMB.{}.{} {},{},ssbo{}[{}];", operation, size, ret, value, binding.U32(), + offset); + } else { + StorageOp(ctx, binding, offset, + fmt::format("ATOM.{}.{} {},{},DC.x;", operation, size, ret, value)); + } } } // Anonymous namespace @@ -212,4 +250,318 @@ void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 o Write(ctx, binding, offset, value, "U32X4"); } +void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.ADD.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value) { + ctx.Add("ATOMS.MIN.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.MIN.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarS32 value) { + ctx.Add("ATOMS.MAX.S32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.MAX.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.IWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.DWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.AND.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.OR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.XOR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + ScalarU32 value) { + ctx.Add("ATOMS.EXCH.U32 {},{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset, + Register value) { + ctx.LongAdd("ATOMS.EXCH.U64 {}.x,{},shared_mem[{}];", inst, value, pointer_offset); +} + +void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "ADD", "U32"); +} + +void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value) { + Atom(ctx, inst, binding, offset, value, "MIN", "S32"); +} + +void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "MIN", "U32"); +} + +void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarS32 value) { + Atom(ctx, inst, binding, offset, value, "MAX", "S32"); +} + +void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "MAX", "U32"); +} + +void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "IWRAP", "U32"); +} + +void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "DWRAP", "U32"); +} + +void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "AND", "U32"); +} + +void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "OR", "U32"); +} + +void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "XOR", "U32"); +} + +void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarU32 value) { + Atom(ctx, inst, binding, offset, value, "EXCH", "U32"); +} + +void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "ADD", "U64"); +} + +void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "S64"); +} + +void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "U64"); +} + +void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "S64"); +} + +void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "U64"); +} + +void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "AND", "U64"); +} + +void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "OR", "U64"); +} + +void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "XOR", "U64"); +} + +void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "EXCH", "U64"); +} + +void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, ScalarF32 value) { + Atom(ctx, inst, binding, offset, value, "ADD", "F32"); +} + +void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "ADD", "F16x2"); +} + +void EmitStorageAtomicAddF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MIN", "F16x2"); +} + +void EmitStorageAtomicMinF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, + ScalarU32 offset, Register value) { + Atom(ctx, inst, binding, offset, value, "MAX", "F16x2"); +} + +void EmitStorageAtomicMaxF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] const IR::Value& binding, + [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicIAdd32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMin32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMin32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMax32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMax32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicInc32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicDec32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAnd32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicOr32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicXor32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicExchange32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicIAdd64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMin64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMin64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicSMax64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicUMax64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicInc64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicDec64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAnd64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicOr64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicXor64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicExchange64(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF32(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicAddF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMinF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMinF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMaxF16x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + +void EmitGlobalAtomicMaxF32x2(EmitContext&) { + throw NotImplementedException("GLASM instruction"); +} + } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 2aa30353b7990789a613fe22525e0a3a19a78656 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 18:33:34 -0300 Subject: glasm: Remove unintentional '\n' on Undef32 --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 2a92d9df5..e6a880a36 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -225,7 +225,7 @@ void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) { } void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) { - ctx.Add("MOV.S {}.x,0;\n", inst); + ctx.Add("MOV.S {}.x,0;", inst); } void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) { -- cgit v1.2.3 From 8f3043c3cf6f6baa1d235e6789533fbf567d1c2d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 18:42:37 -0300 Subject: Revert "glasm: Skip phi moves on undefined instructions" Causes regressions on Bowser's Fury. --- src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index e6a880a36..95bcbd750 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -58,9 +58,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& } const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})}; const Value eval_value{ctx.reg_alloc.Consume(value)}; - if (!value.IsImmediate() && IR::IsUndef(RegAlloc::AliasInst(*value.Inst()))) { - return; - } + if (phi_reg == eval_value) { return; } -- cgit v1.2.3 From e240a62017f240160896b617bb109a0bcea08516 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 May 2021 21:24:30 -0300 Subject: glasm: Fix global memory fallbacks --- .../backend/glasm/emit_glasm_memory.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index 90dbb80d2..cafb5c92a 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -38,14 +38,14 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std 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 + 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 : 0 + "SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 0 + "AND.U.CC RC.x,RC.x,RC.y;" // cond = a && b + "IF NE.x;" // if cond "SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address, address, address); @@ -65,7 +65,8 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std if (!else_expr.empty()) { ctx.Add("{}", else_expr); } - for (size_t index = 0; index < num_buffers; ++index) { + const size_t num_used_buffers{ctx.info.nvn_buffer_used.count()}; + for (size_t index = 0; index < num_used_buffers; ++index) { ctx.Add("ENDIF;"); } } -- cgit v1.2.3 From 83db7abae6550f89ba907789efdf818d93be1b5d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 May 2021 17:49:29 -0300 Subject: glasm: Use integer lod for TXQ --- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 34725b8c6..1c8c70661 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -529,7 +529,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, } void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - ScalarF32 lod) { + ScalarS32 lod) { const auto info{inst.Flags()}; const std::string texture{Texture(ctx, info, index)}; const std::string_view type{TextureType(info)}; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 7b0f75405..c9f4826ce 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -546,7 +546,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde 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); + ScalarS32 lod); void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, const IR::Value& derivatives, -- cgit v1.2.3 From b6c087496b14f1f5b253c3ecb82c00ded743418a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 May 2021 17:54:08 -0300 Subject: glasm: Reduce reg allocation leaks from an exception to a log --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 2a0524609..e23208d2c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -253,7 +253,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } } if (!ctx.reg_alloc.IsEmpty()) { - throw LogicError("Register allocator is not empty"); + // LOG_WARNING ...; } } -- cgit v1.2.3 From eb8464cb3d3cd4a3b5a03d8194ec7b34d8becd75 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 28 May 2021 20:47:31 -0300 Subject: glasm: Fix immediate texture coordinate --- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 1c8c70661..81d5fe72c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -161,6 +161,7 @@ std::string GradOffset(const IR::Value& offset) { std::pair Coord(EmitContext& ctx, const IR::Value& coord) { if (coord.IsImmediate()) { ScopedRegister scoped_reg(ctx.reg_alloc); + ctx.Add("MOV.U {}.x,{};", scoped_reg.reg, ScalarU32{ctx.reg_alloc.Consume(coord)}); return {fmt::to_string(scoped_reg.reg), std::move(scoped_reg)}; } std::string coord_vec{fmt::to_string(Register{ctx.reg_alloc.Consume(coord)})}; -- cgit v1.2.3 From 916ca7432474e891864524dcbc6c879d5cdbfb72 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 30 May 2021 03:40:19 -0300 Subject: opengl: Declare fragment outputs even if they are not used Fixes Ori and the Blind Forest's menu on GLASM. For some reason (probably high level optimizations) it is not sanitized on SPIR-V for OpenGL. Vulkan is unaffected by this change. --- src/shader_recompiler/backend/glasm/emit_context.cpp | 10 +++------- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 +-- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index e18526816..08918a5c2 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -117,13 +117,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile index, index); } } - for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { - if (!info.stores_frag_color[index]) { - continue; - } - if (index == 0) { - Add("OUTPUT frag_color0=result.color;"); - } else { + if (stage == Stage::Fragment) { + Add("OUTPUT frag_color0=result.color;"); + for (size_t index = 1; index < info.stores_frag_color.size(); ++index) { Add("OUTPUT frag_color{}=result.color[{}];", index, index); } } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index e23208d2c..70ca6f621 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -298,8 +298,7 @@ void SetupOptions(const IR::Program& program, const Profile& profile, if (stage == Stage::Fragment && runtime_info.force_early_z != 0) { header += "OPTION NV_early_fragment_tests;"; } - const auto non_zero_frag_colors{info.stores_frag_color | std::views::drop(1)}; - if (std::ranges::find(non_zero_frag_colors, true) != non_zero_frag_colors.end()) { + if (stage == Stage::Fragment) { header += "OPTION ARB_draw_buffers;"; } } -- cgit v1.2.3 From 05d41fa9b70af6d469f2f6f1474436c9255e9bc3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 30 May 2021 23:08:17 -0300 Subject: shader: Add support for "negative" and unaligned offsets "Negative" offsets don't exist. They are shown as such due to a bug in nvdisasm. Unaligned offsets have been proved to read the aligned offset. For example, when reading an U32, if the offset is 6, the offset read will be 4. --- .../backend/glasm/emit_glasm_context_get_set.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 787612def..9ad668b86 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -18,6 +18,14 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU throw NotImplementedException("Indirect constant buffer loading"); } const Register ret{ctx.reg_alloc.Define(inst)}; + if (offset.type == Type::U32) { + // Avoid reading arrays out of bounds, matching hardware's behavior + const u32 imm_offset{offset.imm_u32}; + if (offset.imm_u32 >= 0x10'000) { + ctx.Add("MOV.S {},0;", ret); + return; + } + } ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset); } -- cgit v1.2.3 From cf9f88e5a7b884a417c91725b5cb9e500792e206 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 31 May 2021 04:20:09 -0300 Subject: glasm: Implement legacy varyings --- .../backend/glasm/emit_glasm_context_get_set.cpp | 73 +++++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 9ad668b86..3236def25 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -90,14 +90,20 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle); } break; - case IR::Attribute::TessellationEvaluationPointU: - case IR::Attribute::TessellationEvaluationPointV: - ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle); + case IR::Attribute::ColorFrontDiffuseR: + case IR::Attribute::ColorFrontDiffuseG: + case IR::Attribute::ColorFrontDiffuseB: + case IR::Attribute::ColorFrontDiffuseA: + ctx.Add("MOV.F {}.x,{}.color.{};", inst, ctx.attrib_name, swizzle); break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.attrib_name, swizzle); break; + case IR::Attribute::TessellationEvaluationPointU: + case IR::Attribute::TessellationEvaluationPointV: + ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle); + break; case IR::Attribute::InstanceId: ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name); break; @@ -121,7 +127,27 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ctx.Add("MOV.F out_attr{}[0].{},{};", index, swizzle, value); return; } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9R) { + const u32 index{ + (static_cast(attr) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4}; + ctx.Add("MOV.F result.texcoord[{}].{},{};", index, swizzle, value); + return; + } switch (attr) { + case IR::Attribute::Layer: + if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { + ctx.Add("MOV.F result.layer.x,{};", value); + } else { + // LOG_WARNING + } + break; + case IR::Attribute::ViewportIndex: + if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { + ctx.Add("MOV.F result.viewport.x,{};", value); + } else { + // LOG_WARNING + } + break; case IR::Attribute::PointSize: ctx.Add("MOV.F result.pointsize.x,{};", value); break; @@ -131,6 +157,33 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, case IR::Attribute::PositionW: ctx.Add("MOV.F result.position.{},{};", swizzle, value); break; + case IR::Attribute::ColorFrontDiffuseR: + case IR::Attribute::ColorFrontDiffuseG: + case IR::Attribute::ColorFrontDiffuseB: + case IR::Attribute::ColorFrontDiffuseA: + ctx.Add("MOV.F result.color.{},{};", swizzle, value); + break; + case IR::Attribute::ColorFrontSpecularR: + case IR::Attribute::ColorFrontSpecularG: + case IR::Attribute::ColorFrontSpecularB: + case IR::Attribute::ColorFrontSpecularA: + ctx.Add("MOV.F result.color.secondary.{},{};", swizzle, value); + break; + case IR::Attribute::ColorBackDiffuseR: + case IR::Attribute::ColorBackDiffuseG: + case IR::Attribute::ColorBackDiffuseB: + case IR::Attribute::ColorBackDiffuseA: + ctx.Add("MOV.F result.color.back.{},{};", swizzle, value); + break; + case IR::Attribute::ColorBackSpecularR: + case IR::Attribute::ColorBackSpecularG: + case IR::Attribute::ColorBackSpecularB: + case IR::Attribute::ColorBackSpecularA: + ctx.Add("MOV.F result.color.back.secondary.{},{};", swizzle, value); + break; + case IR::Attribute::FogCoordinate: + ctx.Add("MOV.F result.fogcoord.x,{};", value); + break; case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance1: case IR::Attribute::ClipDistance2: @@ -143,20 +196,6 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ctx.Add("MOV.F result.clip[{}].x,{};", index, value); break; } - case IR::Attribute::Layer: - if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { - ctx.Add("MOV.F result.layer.x,{};", value); - } else { - // LOG_WARNING - } - break; - case IR::Attribute::ViewportIndex: - if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { - ctx.Add("MOV.F result.viewport.x,{};", value); - } else { - // LOG_WARNING - } - break; default: throw NotImplementedException("Set attribute {}", attr); } -- cgit v1.2.3 From 5539b13c5a696de553be86bb7c4ae61a0cdcc754 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 31 May 2021 05:34:53 -0300 Subject: shader,glasm: Implement legacy texcoord loads --- .../backend/glasm/emit_glasm_context_get_set.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 3236def25..3b73e8757 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -37,6 +37,10 @@ bool IsInputArray(Stage stage) { std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) { return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : ""; } + +u32 TexCoordIndex(IR::Attribute attr) { + return (static_cast(attr) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4; +} } // Anonymous namespace void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) { @@ -76,6 +80,11 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal ctx.Add("MOV.F {}.x,in_attr{}{}[0].{};", inst, index, VertexIndex(ctx, vertex), swizzle); return; } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + const u32 index{TexCoordIndex(attr)}; + ctx.Add("MOV.F {}.x,{}.texcoord[{}].{};", inst, ctx.attrib_name, index, swizzle); + return; + } switch (attr) { case IR::Attribute::PrimitiveId: ctx.Add("MOV.S {}.x,primitive.id;", inst); @@ -128,8 +137,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, return; } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9R) { - const u32 index{ - (static_cast(attr) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4}; + const u32 index{TexCoordIndex(attr)}; ctx.Add("MOV.F result.texcoord[{}].{},{};", index, swizzle, value); return; } -- cgit v1.2.3 From 22f0c4f002b1d215fe5accde7a25dfb724889ee8 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Mon, 31 May 2021 16:57:11 -0400 Subject: emit_glasm_context_get_set: Remove unused variable --- src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 3b73e8757..c1df7a342 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -20,7 +20,6 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU const Register ret{ctx.reg_alloc.Define(inst)}; if (offset.type == Type::U32) { // Avoid reading arrays out of bounds, matching hardware's behavior - const u32 imm_offset{offset.imm_u32}; if (offset.imm_u32 >= 0x10'000) { ctx.Add("MOV.S {},0;", ret); return; -- cgit v1.2.3 From 79f2fe1a39120f498e915fa0c740b15dc0f09793 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 2 Jun 2021 03:02:33 -0300 Subject: glasm: Use ARB_derivative_control conditionally --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 7 +++--- .../backend/glasm/emit_glasm_warp.cpp | 29 +++++++++++++++++++--- 2 files changed, 29 insertions(+), 7 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 70ca6f621..fc01797b6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -265,9 +265,7 @@ void SetupOptions(const IR::Program& program, const Profile& profile, // TODO: Track the shared atomic ops header += "OPTION NV_internal;" "OPTION NV_shader_storage_buffer;" - "OPTION NV_gpu_program_fp64;" - "OPTION NV_bindless_texture;" - "OPTION ARB_derivative_control;"; + "OPTION NV_gpu_program_fp64;"; if (info.uses_int64_bit_atomics) { header += "OPTION NV_shader_atomic_int64;"; } @@ -295,6 +293,9 @@ void SetupOptions(const IR::Program& program, const Profile& profile, if (info.uses_typeless_image_reads && profile.support_typeless_image_loads) { header += "OPTION EXT_shader_image_load_formatted;"; } + if (profile.support_derivative_control) { + header += "OPTION ARB_derivative_control;"; + } if (stage == Stage::Fragment && runtime_info.force_early_z != 0) { header += "OPTION NV_early_fragment_tests;"; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index 6e30790bb..8cec5ee7e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -5,6 +5,7 @@ #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/value.h" +#include "shader_recompiler/profile.h" namespace Shader::Backend::GLASM { @@ -111,19 +112,39 @@ void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a, ScalarF32 } void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { - ctx.Add("DDX.FINE {}.x,{};", inst, p); + if (ctx.profile.support_derivative_control) { + ctx.Add("DDX.FINE {}.x,{};", inst, p); + } else { + // LOG_WARNING + ctx.Add("DDX {}.x,{};", inst, p); + } } void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { - ctx.Add("DDY.FINE {}.x,{};", inst, p); + if (ctx.profile.support_derivative_control) { + ctx.Add("DDY.FINE {}.x,{};", inst, p); + } else { + // LOG_WARNING + ctx.Add("DDY {}.x,{};", inst, p); + } } void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { - ctx.Add("DDX.COARSE {}.x,{};", inst, p); + if (ctx.profile.support_derivative_control) { + ctx.Add("DDX.COARSE {}.x,{};", inst, p); + } else { + // LOG_WARNING + ctx.Add("DDX {}.x,{};", inst, p); + } } void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { - ctx.Add("DDY.COARSE {}.x,{};", inst, p); + if (ctx.profile.support_derivative_control) { + ctx.Add("DDY.COARSE {}.x,{};", inst, p); + } else { + // LOG_WARNING + ctx.Add("DDY {}.x,{};", inst, p); + } } } // namespace Shader::Backend::GLASM -- cgit v1.2.3 From 373f75d944473731408d7a72c967d5c4b37af5bb Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:22:31 -0400 Subject: shader: Add shader loop safety check settings Also add a setting for enable Nsight Aftermath. --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 ++ .../backend/glasm/emit_glasm_not_implemented.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index c9f4826ce..fef9ff9be 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -42,6 +42,8 @@ void EmitSetGotoVariable(EmitContext& ctx); void EmitGetGotoVariable(EmitContext& ctx); void EmitSetIndirectBranchVariable(EmitContext& ctx); void EmitGetIndirectBranchVariable(EmitContext& ctx); +void EmitSetLoopSafetyVariable(EmitContext& ctx); +void EmitGetLoopSafetyVariable(EmitContext& ctx); void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 95bcbd750..60735fe31 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -153,6 +153,14 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { NotImplemented(); } +void EmitSetLoopSafetyVariable(EmitContext& ctx) { + NotImplemented(); +} + +void EmitGetLoopSafetyVariable(EmitContext& ctx) { + NotImplemented(); +} + void EmitGetZFlag(EmitContext& ctx) { NotImplemented(); } -- cgit v1.2.3 From 61cd7dd30128633b656ce3264da74bef1ba00bb5 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 14 Jun 2021 02:27:49 -0300 Subject: shader: Add logging --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 2 +- .../backend/glasm/emit_glasm_context_get_set.cpp | 6 ++++-- src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | 4 ++-- .../backend/glasm/emit_glasm_not_implemented.cpp | 2 +- src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | 8 ++++---- 5 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index fc01797b6..832b4fd40 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -253,7 +253,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } } if (!ctx.reg_alloc.IsEmpty()) { - // LOG_WARNING ...; + LOG_WARNING(Shader_GLASM, "Register leak after generating code"); } } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index c1df7a342..20b925877 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -145,14 +145,16 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { ctx.Add("MOV.F result.layer.x,{};", value); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, + "Layer stored outside of geometry shader not supported by device"); } break; case IR::Attribute::ViewportIndex: if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) { ctx.Add("MOV.F result.viewport.x,{};", value); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, + "Viewport stored outside of geometry shader not supported by device"); } break; case IR::Attribute::PointSize: diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index 81d5fe72c..09e3a9b82 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -139,12 +139,12 @@ void SwizzleOffsets(EmitContext& ctx, Register off_x, Register off_y, const IR:: std::string GradOffset(const IR::Value& offset) { if (offset.IsImmediate()) { - // LOG_WARNING immediate + LOG_WARNING(Shader_GLASM, "Gradient offset is a scalar immediate"); return ""; } IR::Inst* const vector{offset.InstRecursive()}; if (!vector->AreAllArgsImmediates()) { - // LOG_WARNING elements not immediate + LOG_WARNING(Shader_GLASM, "Gradient offset vector is not immediate"); return ""; } switch (vector->NumArgs()) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 60735fe31..a487a0744 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -115,7 +115,7 @@ void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) { void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { if (!stream.IsImmediate()) { - // LOG_WARNING not immediate + LOG_WARNING(Shader_GLASM, "Stream is not immediate"); } ctx.reg_alloc.Consume(stream); ctx.Add("ENDPRIM;"); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index 8cec5ee7e..544d475b4 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp @@ -115,7 +115,7 @@ void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { if (ctx.profile.support_derivative_control) { ctx.Add("DDX.FINE {}.x,{};", inst, p); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, "Fine derivatives not supported by device"); ctx.Add("DDX {}.x,{};", inst, p); } } @@ -124,7 +124,7 @@ void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { if (ctx.profile.support_derivative_control) { ctx.Add("DDY.FINE {}.x,{};", inst, p); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, "Fine derivatives not supported by device"); ctx.Add("DDY {}.x,{};", inst, p); } } @@ -133,7 +133,7 @@ void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { if (ctx.profile.support_derivative_control) { ctx.Add("DDX.COARSE {}.x,{};", inst, p); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, "Coarse derivatives not supported by device"); ctx.Add("DDX {}.x,{};", inst, p); } } @@ -142,7 +142,7 @@ void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { if (ctx.profile.support_derivative_control) { ctx.Add("DDY.COARSE {}.x,{};", inst, p); } else { - // LOG_WARNING + LOG_WARNING(Shader_GLASM, "Coarse derivatives not supported by device"); ctx.Add("DDY {}.x,{};", inst, p); } } -- cgit v1.2.3 From 0ffea97e2ea2c8f58928e13dc2488d620ea98ea8 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 16 Jun 2021 03:22:56 -0300 Subject: shader: Split profile and runtime info headers --- src/shader_recompiler/backend/glasm/emit_context.cpp | 1 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 1 + src/shader_recompiler/backend/glasm/emit_glasm.h | 1 + src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 08918a5c2..21e14867c 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -8,6 +8,7 @@ #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::GLASM { namespace { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 832b4fd40..66e4aea04 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -13,6 +13,7 @@ #include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::GLASM { namespace { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h index 3df32a4a6..bcb55f062 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm.h @@ -9,6 +9,7 @@ #include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::GLASM { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp index cafb5c92a..af9fac7c1 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp @@ -8,7 +8,7 @@ #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/frontend/ir/value.h" -#include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::GLASM { namespace { -- cgit v1.2.3 From 3a2dd1b48310e2912e7f7f90da15bff555ef7256 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 20 Jun 2021 01:40:21 -0400 Subject: glasm: Implement SetAttribute ViewportMask --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 3 ++- .../backend/glasm/emit_glasm_context_get_set.cpp | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 66e4aea04..f39b02f77 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -286,7 +286,8 @@ void SetupOptions(const IR::Program& program, const Profile& profile, if (info.uses_sparse_residency) { header += "OPTION EXT_sparse_texture2;"; } - if ((info.stores_viewport_index || info.stores_layer) && stage != Stage::Geometry) { + if (((info.stores_viewport_index || info.stores_layer) && stage != Stage::Geometry) || + info.stores_viewport_mask) { if (profile.support_viewport_index_layer_non_geometry) { header += "OPTION NV_viewport_array2;"; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 20b925877..bc195d248 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -157,6 +157,14 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, "Viewport stored outside of geometry shader not supported by device"); } break; + case IR::Attribute::ViewportMask: + // NV_viewport_array2 is required to access result.viewportmask, regardless of shader stage. + if (ctx.profile.support_viewport_index_layer_non_geometry) { + ctx.Add("MOV.F result.viewportmask[0].x,{};", value); + } else { + LOG_WARNING(Shader_GLASM, "Device does not support storing to ViewportMask"); + } + break; case IR::Attribute::PointSize: ctx.Add("MOV.F result.pointsize.x,{};", value); break; -- cgit v1.2.3 From 808ef97a086e7cc58a3ceded1de516ad6a6be5d3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 21 Jun 2021 01:07:10 -0300 Subject: shader: Move loop safety tests to code emission --- src/shader_recompiler/backend/glasm/emit_context.h | 1 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 17 +++++++++++++++++ .../backend/glasm/emit_glasm_instructions.h | 2 -- .../backend/glasm/emit_glasm_not_implemented.cpp | 8 -------- 4 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index cd4213cb7..9f86e55d3 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -71,6 +71,7 @@ public: std::string_view stage_name = "invalid"; std::string_view attrib_name = "invalid"; + u32 num_safety_loop_vars{}; bool uses_y_direction{}; }; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index f39b02f77..79314f130 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -6,6 +6,8 @@ #include #include +#include "common/div_ceil.h" +#include "common/settings.h" #include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/backend/glasm/emit_context.h" #include "shader_recompiler/backend/glasm/emit_glasm.h" @@ -222,6 +224,14 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { ctx.Add("REP;"); break; case IR::AbstractSyntaxNode::Type::Repeat: + if (!Settings::values.disable_shader_loop_safety_checks) { + const u32 loop_index{ctx.num_safety_loop_vars++}; + const u32 vector_index{loop_index / 4}; + const char component{"xyzw"[loop_index % 4]}; + ctx.Add("SUB.S.CC loop{}.{},loop{}.{},1;" + "BRK(LT.{});", + vector_index, component, vector_index, component, component); + } if (node.data.repeat.cond.IsImmediate()) { if (node.data.repeat.cond.U1()) { ctx.Add("ENDREP;"); @@ -425,6 +435,10 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I if (program.info.uses_fswzadd) { header += "FSWZA[4],FSWZB[4],"; } + const u32 num_safety_loop_vectors{Common::DivCeil(ctx.num_safety_loop_vars, 4u)}; + for (u32 index = 0; index < num_safety_loop_vectors; ++index) { + header += fmt::format("loop{},", index); + } header += "RC;" "LONG TEMP "; for (size_t index = 0; index < ctx.reg_alloc.NumUsedLongRegisters(); ++index) { @@ -441,6 +455,9 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I "MOV.F FSWZB[2],1;" "MOV.F FSWZB[3],-1;"; } + for (u32 index = 0; index < num_safety_loop_vectors; ++index) { + header += fmt::format("MOV.S loop{},{{0x2000,0x2000,0x2000,0x2000}};", index); + } if (ctx.uses_y_direction) { header += "PARAM y_direction[1]={state.material.front.ambient};"; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index fef9ff9be..c9f4826ce 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -42,8 +42,6 @@ void EmitSetGotoVariable(EmitContext& ctx); void EmitGetGotoVariable(EmitContext& ctx); void EmitSetIndirectBranchVariable(EmitContext& ctx); void EmitGetIndirectBranchVariable(EmitContext& ctx); -void EmitSetLoopSafetyVariable(EmitContext& ctx); -void EmitGetLoopSafetyVariable(EmitContext& ctx); void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index a487a0744..ff64c6924 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -153,14 +153,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { NotImplemented(); } -void EmitSetLoopSafetyVariable(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGetLoopSafetyVariable(EmitContext& ctx) { - NotImplemented(); -} - void EmitGetZFlag(EmitContext& ctx) { NotImplemented(); } -- cgit v1.2.3 From 4397053d5c848deae00d6599f91b1e5c137a9639 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 22 Jun 2021 18:28:21 -0300 Subject: shader: Remove IAbs64 --- src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 1 - src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp | 4 ---- 2 files changed, 5 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index c9f4826ce..12afda43b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -306,7 +306,6 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b); void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value); -void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, Register value); void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, ScalarU32 shift); void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift); diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index cea45a3e0..587bbfe06 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -82,10 +82,6 @@ void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) { ctx.Add("ABS.S {},{};", inst, value); } -void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, Register value) { - ctx.LongAdd("MOV.S64 {},|{}|;", inst, value); -} - void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) { ctx.Add("SHL.U {}.x,{},{};", inst, base, shift); } -- cgit v1.2.3 From 7dafa96ab59892b7f1fbffdb61e4326e6443955f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 24 Jun 2021 02:41:09 -0300 Subject: shader: Rework varyings and implement passthrough geometry shaders Put all varyings into a single std::bitset with helpers to access it. Implement passthrough geometry shaders using host's. --- src/shader_recompiler/backend/glasm/emit_context.cpp | 15 +++++++-------- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 6 ++++-- .../backend/glasm/emit_glasm_context_get_set.cpp | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 21e14867c..80dad9ff3 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -83,14 +83,13 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile break; } const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; - for (size_t index = 0; index < info.input_generics.size(); ++index) { - const auto& generic{info.input_generics[index]}; - if (generic.used) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (info.loads.Generic(index)) { Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", - InterpDecorator(generic.interpolation), index, attr_stage, index, index); + InterpDecorator(info.interpolation[index]), index, attr_stage, index, index); } } - if (IsInputArray(stage) && info.loads_position) { + if (IsInputArray(stage) && info.loads.AnyComponent(IR::Attribute::PositionX)) { Add("ATTRIB vertex_position=vertex.position;"); } if (info.uses_invocation_id) { @@ -102,7 +101,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile if (info.stores_tess_level_inner) { Add("OUTPUT result_patch_tessinner[]={{result.patch.tessinner[0..1]}};"); } - if (info.stores_clip_distance) { + if (info.stores.ClipDistances()) { Add("OUTPUT result_clip[]={{result.clip[0..7]}};"); } for (size_t index = 0; index < info.uses_patches.size(); ++index) { @@ -124,8 +123,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile Add("OUTPUT frag_color{}=result.color[{}];", index, index); } } - for (size_t index = 0; index < info.stores_generics.size(); ++index) { - if (info.stores_generics[index]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (info.stores.Generic(index)) { Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); } } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 79314f130..2b96977b3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -296,8 +296,10 @@ void SetupOptions(const IR::Program& program, const Profile& profile, if (info.uses_sparse_residency) { header += "OPTION EXT_sparse_texture2;"; } - if (((info.stores_viewport_index || info.stores_layer) && stage != Stage::Geometry) || - info.stores_viewport_mask) { + const bool stores_viewport_layer{info.stores[IR::Attribute::ViewportIndex] || + info.stores[IR::Attribute::Layer]}; + if ((stage != Stage::Geometry && stores_viewport_layer) || + info.stores[IR::Attribute::ViewportMask]) { if (profile.support_viewport_index_layer_non_geometry) { header += "OPTION NV_viewport_array2;"; } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index bc195d248..02c9dc6d7 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -261,7 +261,7 @@ void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, fmt::format("{}.z", value), fmt::format("{}.w", value)}; read(compare_index, values); }}; - if (ctx.info.loads_position) { + if (ctx.info.loads.AnyComponent(IR::Attribute::PositionX)) { const u32 index{static_cast(IR::Attribute::PositionX)}; if (IsInputArray(ctx.stage)) { read_swizzled(index, fmt::format("vertex_position{}", VertexIndex(ctx, vertex))); @@ -269,8 +269,8 @@ void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, read_swizzled(index, fmt::format("{}.position", ctx.attrib_name)); } } - for (u32 index = 0; index < ctx.info.input_generics.size(); ++index) { - if (!ctx.info.input_generics[index].used) { + for (u32 index = 0; index < static_cast(IR::NUM_GENERICS); ++index) { + if (!ctx.info.loads.Generic(index)) { continue; } read_swizzled(index, fmt::format("in_attr{}{}[0]", index, VertexIndex(ctx, vertex))); -- cgit v1.2.3 From 8a3427a4c857aa08e365d1776d1f0d9f32639c9c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 24 Jun 2021 17:40:24 -0300 Subject: glasm: Add passthrough geometry shader support --- .../backend/glasm/emit_context.cpp | 5 ++-- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 28 ++++++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 80dad9ff3..069c019ad 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp @@ -83,13 +83,14 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile break; } const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; + const VaryingState loads{info.loads.mask | info.passthrough.mask}; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { - if (info.loads.Generic(index)) { + if (loads.Generic(index)) { Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", InterpDecorator(info.interpolation[index]), index, attr_stage, index, index); } } - if (IsInputArray(stage) && info.loads.AnyComponent(IR::Attribute::PositionX)) { + if (IsInputArray(stage) && loads.AnyComponent(IR::Attribute::PositionX)) { Add("ATTRIB vertex_position=vertex.position;"); } if (info.uses_invocation_id) { diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 2b96977b3..64787b353 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -304,6 +304,9 @@ void SetupOptions(const IR::Program& program, const Profile& profile, header += "OPTION NV_viewport_array2;"; } } + if (program.is_geometry_passthrough && profile.support_geometry_shader_passthrough) { + header += "OPTION NV_geometry_shader_passthrough;"; + } if (info.uses_typeless_image_reads && profile.support_typeless_image_loads) { header += "OPTION EXT_shader_image_load_formatted;"; } @@ -410,11 +413,26 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I runtime_info.tess_clockwise ? "CW" : "CCW"); break; case Stage::Geometry: - header += fmt::format("PRIMITIVE_IN {};" - "PRIMITIVE_OUT {};" - "VERTICES_OUT {};", - InputPrimitive(runtime_info.input_topology), - OutputPrimitive(program.output_topology), program.output_vertices); + header += fmt::format("PRIMITIVE_IN {};", InputPrimitive(runtime_info.input_topology)); + if (program.is_geometry_passthrough) { + if (profile.support_geometry_shader_passthrough) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (program.info.passthrough.Generic(index)) { + header += fmt::format("PASSTHROUGH result.attrib[{}];", index); + } + } + if (program.info.passthrough.AnyComponent(IR::Attribute::PositionX)) { + header += "PASSTHROUGH result.position;"; + } + } else { + LOG_WARNING(Shader_GLASM, "Passthrough geometry program used but not supported"); + } + } else { + header += + fmt::format("VERTICES_OUT {};" + "PRIMITIVE_OUT {};", + program.output_vertices, OutputPrimitive(program.output_topology)); + } break; case Stage::Compute: header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], -- cgit v1.2.3 From 8289eb108fefa9bfbb445c9f6b3f423a5d0eb771 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Fri, 25 Jun 2021 13:09:45 -0400 Subject: opengl: Implement LOP.CC Used by MH:Rise --- .../backend/glasm/emit_glasm_integer.cpp | 30 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp index 587bbfe06..f55c26b76 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp @@ -7,6 +7,30 @@ #include "shader_recompiler/frontend/ir/value.h" namespace Shader::Backend::GLASM { +namespace { +void BitwiseLogicalOp(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b, + std::string_view lop) { + const auto zero = inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp); + const auto sign = inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp); + if (zero) { + zero->Invalidate(); + } + if (sign) { + sign->Invalidate(); + } + if (zero || sign) { + ctx.reg_alloc.InvalidateConditionCodes(); + } + const auto ret{ctx.reg_alloc.Define(inst)}; + ctx.Add("{}.S {}.x,{},{};", lop, ret, a, b); + if (zero) { + ctx.Add("SEQ.S {},{},0;", *zero, ret); + } + if (sign) { + ctx.Add("SLT.S {},{},0;", *sign, ret); + } +} +} // Anonymous namespace void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { const std::array flags{ @@ -110,15 +134,15 @@ void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, ScalarRegister } void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { - ctx.Add("AND.S {}.x,{},{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, "AND"); } void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { - ctx.Add("OR.S {}.x,{},{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, "OR"); } void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) { - ctx.Add("XOR.S {}.x,{},{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, "XOR"); } void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert, -- cgit v1.2.3 From 2e5af95541adf581364ee3864be57f9b2b9a230f Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Mon, 28 Jun 2021 23:44:03 -0400 Subject: shader: GCC fmt 8.0.0 fixes --- src/shader_recompiler/backend/glasm/emit_context.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 9f86e55d3..1da51a996 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -37,21 +37,23 @@ public: template void Add(const char* format_str, IR::Inst& inst, Args&&... args) { - code += fmt::format(format_str, reg_alloc.Define(inst), std::forward(args)...); + code += fmt::format(fmt::runtime(format_str), reg_alloc.Define(inst), + std::forward(args)...); // TODO: Remove this code += '\n'; } template void LongAdd(const char* format_str, IR::Inst& inst, Args&&... args) { - code += fmt::format(format_str, reg_alloc.LongDefine(inst), std::forward(args)...); + code += fmt::format(fmt::runtime(format_str), reg_alloc.LongDefine(inst), + std::forward(args)...); // TODO: Remove this code += '\n'; } template void Add(const char* format_str, Args&&... args) { - code += fmt::format(format_str, std::forward(args)...); + code += fmt::format(fmt::runtime(format_str), std::forward(args)...); // TODO: Remove this code += '\n'; } -- cgit v1.2.3 From 49946cf780c317b4c5ccabb52ec433eba01c1970 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sun, 11 Jul 2021 22:10:38 -0400 Subject: shader_recompiler, video_core: Resolve clang errors Silences the following warnings-turned-errors: -Wsign-conversion -Wunused-private-field -Wbraced-scalar-init -Wunused-variable And some other errors --- src/shader_recompiler/backend/glasm/emit_context.h | 2 +- src/shader_recompiler/backend/glasm/reg_alloc.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 1da51a996..8433e5c00 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h @@ -59,7 +59,7 @@ public: } std::string code; - RegAlloc reg_alloc{*this}; + RegAlloc reg_alloc{}; const Info& info; const Profile& profile; const RuntimeInfo& runtime_info; diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h index 5a703daf2..82aec66c6 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.h +++ b/src/shader_recompiler/backend/glasm/reg_alloc.h @@ -86,7 +86,7 @@ struct ScalarF64 : Value {}; class RegAlloc { public: - RegAlloc(EmitContext& ctx_) : ctx{ctx_} {} + RegAlloc() = default; Register Define(IR::Inst& inst); @@ -142,7 +142,6 @@ private: void Free(Id id); - EmitContext& ctx; size_t num_used_registers{}; size_t num_used_long_registers{}; std::bitset register_use{}; -- cgit v1.2.3 From bf2956d77ab0ad06c4b5505cc9906e51e5878274 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 12 Jul 2021 05:22:01 -0300 Subject: shader: Avoid usage of C++20 ranges to build in clang --- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 64787b353..a5e8c9b6e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include #include @@ -196,7 +196,10 @@ void PrecolorInst(IR::Inst& phi) { void Precolor(const IR::Program& program) { for (IR::Block* const block : program.blocks) { - for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { + for (IR::Inst& phi : block->Instructions()) { + if (!IR::IsPhi(phi)) { + break; + } PrecolorInst(phi); } } -- cgit v1.2.3