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 +-------------------- src/shader_recompiler/frontend/ir/value.h | 6 + 10 files changed, 1175 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(); diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index c73851d11..beaf149f3 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -224,6 +224,12 @@ public: --use_count; } + /// Destructively add usages to the instruction + /// Useful for register allocation + void DestructiveAddUsage(int count) { + use_count += count; + } + private: struct NonTriviallyDummy { NonTriviallyDummy() noexcept {} -- 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 +++++++++++++++++++++ .../backend/spirv/emit_context.cpp | 2 +- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 4 +- .../ir_opt/collect_shader_info_pass.cpp | 4 +- src/shader_recompiler/shader_info.h | 1 + 10 files changed, 166 insertions(+), 100 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 diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index be88b76f7..9759591bd 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1168,7 +1168,7 @@ void EmitContext::DefineInputs(const Info& info) { subgroup_mask_gt = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGtMaskKHR); subgroup_mask_ge = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGeMaskKHR); } - if (info.uses_subgroup_invocation_id || + if (info.uses_subgroup_invocation_id || info.uses_subgroup_shuffles || (profile.warp_size_potentially_larger_than_guest && (info.uses_subgroup_vote || info.uses_subgroup_mask))) { subgroup_local_invocation_id = diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 0681dfd16..2dad87e87 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -318,7 +318,9 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct ctx.AddExtension("SPV_KHR_shader_draw_parameters"); ctx.AddCapability(spv::Capability::DrawParameters); } - if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id) && profile.support_vote) { + if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id || + info.uses_subgroup_shuffles) && + profile.support_vote) { ctx.AddExtension("SPV_KHR_shader_ballot"); ctx.AddCapability(spv::Capability::SubgroupBallotKHR); if (!profile.warp_size_potentially_larger_than_guest) { diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 13b793d57..ea08aacc3 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -504,11 +504,13 @@ void VisitUsages(Info& info, IR::Inst& inst) { info.uses_is_helper_invocation = true; break; case IR::Opcode::LaneId: + info.uses_subgroup_invocation_id = true; + break; case IR::Opcode::ShuffleIndex: case IR::Opcode::ShuffleUp: case IR::Opcode::ShuffleDown: case IR::Opcode::ShuffleButterfly: - info.uses_subgroup_invocation_id = true; + info.uses_subgroup_shuffles = true; break; case IR::Opcode::GetCbufU8: case IR::Opcode::GetCbufS8: diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index a50a9a18c..d6c32fbe5 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -116,6 +116,7 @@ struct Info { bool uses_sample_id{}; bool uses_is_helper_invocation{}; bool uses_subgroup_invocation_id{}; + bool uses_subgroup_shuffles{}; std::array uses_patches{}; std::array input_generics{}; -- 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/CMakeLists.txt | 1 + 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 +-- .../backend/spirv/emit_context.cpp | 9 - src/shader_recompiler/backend/spirv/emit_context.h | 1 - src/shader_recompiler/backend/spirv/emit_spirv.cpp | 71 ++++++- .../backend/spirv/emit_spirv_control_flow.cpp | 33 +-- .../backend/spirv/emit_spirv_instructions.h | 9 +- .../frontend/ir/abstract_syntax_list.h | 56 +++++ src/shader_recompiler/frontend/ir/basic_block.cpp | 56 ++--- src/shader_recompiler/frontend/ir/basic_block.h | 51 +---- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 60 ++---- src/shader_recompiler/frontend/ir/ir_emitter.h | 11 +- .../frontend/ir/microinstruction.cpp | 11 +- src/shader_recompiler/frontend/ir/opcodes.h | 1 - src/shader_recompiler/frontend/ir/opcodes.inc | 21 +- src/shader_recompiler/frontend/ir/post_order.cpp | 36 ++-- src/shader_recompiler/frontend/ir/post_order.h | 3 +- src/shader_recompiler/frontend/ir/program.h | 4 +- src/shader_recompiler/frontend/ir/type.h | 49 +++-- src/shader_recompiler/frontend/ir/value.cpp | 8 - src/shader_recompiler/frontend/ir/value.h | 9 - src/shader_recompiler/frontend/maxwell/program.cpp | 24 ++- .../frontend/maxwell/structured_control_flow.cpp | 235 ++++++++++++--------- .../frontend/maxwell/structured_control_flow.h | 12 +- .../frontend/maxwell/translate/translate.cpp | 7 +- .../frontend/maxwell/translate/translate.h | 2 +- .../ir_opt/constant_propagation_pass.cpp | 20 -- src/shader_recompiler/ir_opt/dual_vertex_pass.cpp | 56 +---- .../ir_opt/identity_removal_pass.cpp | 1 - src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 4 +- 33 files changed, 437 insertions(+), 505 deletions(-) create mode 100644 src/shader_recompiler/frontend/ir/abstract_syntax_list.h (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index f829b8d32..0d55924a7 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -51,6 +51,7 @@ add_library(shader_recompiler STATIC backend/spirv/emit_spirv_warp.cpp environment.h exception.h + frontend/ir/abstract_syntax_list.h frontend/ir/attribute.cpp frontend/ir/attribute.h frontend/ir/basic_block.cpp 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(); } diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 9759591bd..a98e08392 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -463,7 +463,6 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, Bindings DefineImages(program.info, image_binding); DefineAttributeMemAccess(program.info); DefineGlobalMemoryFunctions(program.info); - DefineLabels(program); } EmitContext::~EmitContext() = default; @@ -487,8 +486,6 @@ Id EmitContext::Def(const IR::Value& value) { return Const(value.F32()); case IR::Type::F64: return Constant(F64[1], value.F64()); - case IR::Type::Label: - return value.Label()->Definition(); default: throw NotImplementedException("Immediate type {}", value.Type()); } @@ -1139,12 +1136,6 @@ void EmitContext::DefineImages(const Info& info, u32& binding) { } } -void EmitContext::DefineLabels(IR::Program& program) { - for (IR::Block* const block : program.blocks) { - block->SetDefinition(OpLabel()); - } -} - void EmitContext::DefineInputs(const Info& info) { if (info.uses_workgroup_id) { workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId); diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 8b000f1ec..d2b79f6c1 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -296,7 +296,6 @@ private: void DefineImages(const Info& info, u32& binding); void DefineAttributeMemAccess(const Info& info); void DefineGlobalMemoryFunctions(const Info& info); - void DefineLabels(IR::Program& program); void DefineInputs(const Info& info); void DefineOutputs(const IR::Program& program); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 2dad87e87..c22edfec2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -41,8 +41,6 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) { 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) { @@ -109,15 +107,74 @@ Id TypeId(const EmitContext& ctx, IR::Type type) { } } +void Traverse(EmitContext& ctx, IR::Program& program) { + IR::Block* current_block{}; + for (const IR::AbstractSyntaxNode& node : program.syntax_list) { + switch (node.type) { + case IR::AbstractSyntaxNode::Type::Block: + const Id label{node.block->Definition()}; + if (current_block) { + ctx.OpBranch(label); + } + current_block = node.block; + ctx.AddLabel(label); + for (IR::Inst& inst : node.block->Instructions()) { + EmitInst(ctx, &inst); + } + break; + case IR::AbstractSyntaxNode::Type::If: { + const Id if_label{node.if_node.body->Definition()}; + const Id endif_label{node.if_node.merge->Definition()}; + ctx.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone); + ctx.OpBranchConditional(ctx.Def(node.if_node.cond), if_label, endif_label); + break; + } + case IR::AbstractSyntaxNode::Type::Loop: { + const Id body_label{node.loop.body->Definition()}; + const Id continue_label{node.loop.continue_block->Definition()}; + const Id endloop_label{node.loop.merge->Definition()}; + + ctx.OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone); + ctx.OpBranch(node.loop.body->Definition()); + break; + } + case IR::AbstractSyntaxNode::Type::Break: { + const Id break_label{node.break_node.merge->Definition()}; + const Id skip_label{node.break_node.skip->Definition()}; + ctx.OpBranchConditional(ctx.Def(node.break_node.cond), break_label, skip_label); + break; + } + case IR::AbstractSyntaxNode::Type::EndIf: + if (current_block) { + ctx.OpBranch(node.end_if.merge->Definition()); + } + break; + case IR::AbstractSyntaxNode::Type::Repeat: { + const Id loop_header_label{node.repeat.loop_header->Definition()}; + const Id merge_label{node.repeat.merge->Definition()}; + ctx.OpBranchConditional(ctx.Def(node.repeat.cond), loop_header_label, merge_label); + break; + } + case IR::AbstractSyntaxNode::Type::Return: + ctx.OpReturn(); + break; + case IR::AbstractSyntaxNode::Type::Unreachable: + ctx.OpUnreachable(); + break; + } + if (node.type != IR::AbstractSyntaxNode::Type::Block) { + current_block = nullptr; + } + } +} + Id DefineMain(EmitContext& ctx, IR::Program& program) { const Id void_function{ctx.TypeFunction(ctx.void_id)}; const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; for (IR::Block* const block : program.blocks) { - ctx.AddLabel(block->Definition()); - for (IR::Inst& inst : block->Instructions()) { - EmitInst(ctx, &inst); - } + block->SetDefinition(ctx.OpLabel()); } + Traverse(ctx, program); ctx.OpFunctionEnd(); return main; } @@ -411,6 +468,8 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { return id; } +void EmitBranchConditionRef(EmitContext&) {} + void EmitGetZeroFromOp(EmitContext&) { throw LogicError("Unreachable instruction"); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp index 6154c46be..d33486f28 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp @@ -7,40 +7,21 @@ namespace Shader::Backend::SPIRV { -void EmitBranch(EmitContext& ctx, Id label) { - ctx.OpBranch(label); -} - -void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label) { - ctx.OpBranchConditional(condition, true_label, false_label); -} - -void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label) { - ctx.OpLoopMerge(merge_label, continue_label, spv::LoopControlMask::MaskNone); -} - -void EmitSelectionMerge(EmitContext& ctx, Id merge_label) { - ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); -} - -void EmitReturn(EmitContext& ctx) { - ctx.OpReturn(); -} - void EmitJoin(EmitContext&) { throw NotImplementedException("Join shouldn't be emitted"); } -void EmitUnreachable(EmitContext& ctx) { - ctx.OpUnreachable(); -} - -void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label) { +void EmitDemoteToHelperInvocation(EmitContext& ctx) { if (ctx.profile.support_demote_to_helper_invocation) { ctx.OpDemoteToHelperInvocationEXT(); - ctx.OpBranch(continue_label); } else { + const Id kill_label{ctx.OpLabel()}; + const Id impossible_label{ctx.OpLabel()}; + ctx.OpSelectionMerge(impossible_label, spv::SelectionControlMask::MaskNone); + ctx.OpBranchConditional(ctx.true_value, kill_label, impossible_label); + ctx.AddLabel(kill_label); ctx.OpKill(); + ctx.AddLabel(impossible_label); } } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index a1ca3f43d..2f4f6e59e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -23,14 +23,9 @@ class EmitContext; Id EmitPhi(EmitContext& ctx, IR::Inst* inst); void EmitVoid(EmitContext& ctx); Id EmitIdentity(EmitContext& ctx, const IR::Value& value); -void EmitBranch(EmitContext& ctx, Id label); -void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label); -void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label); -void EmitSelectionMerge(EmitContext& ctx, Id merge_label); -void EmitReturn(EmitContext& ctx); +void EmitBranchConditionRef(EmitContext&); void EmitJoin(EmitContext& ctx); -void EmitUnreachable(EmitContext& ctx); -void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); +void EmitDemoteToHelperInvocation(EmitContext& ctx); void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); diff --git a/src/shader_recompiler/frontend/ir/abstract_syntax_list.h b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h new file mode 100644 index 000000000..1366414c2 --- /dev/null +++ b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h @@ -0,0 +1,56 @@ +// 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/frontend/ir/value.h" + +namespace Shader::IR { + +class Block; + +struct AbstractSyntaxNode { + enum class Type { + Block, + If, + EndIf, + Loop, + Repeat, + Break, + Return, + Unreachable, + }; + Type type{}; + union { + Block* block{}; + struct { + U1 cond; + Block* body; + Block* merge; + } if_node; + struct { + Block* merge; + } end_if; + struct { + Block* body; + Block* continue_block; + Block* merge; + } loop; + struct { + U1 cond; + Block* loop_header; + Block* merge; + } repeat; + struct { + U1 cond; + Block* merge; + Block* skip; + } break_node; + }; +}; +using AbstractSyntaxList = std::vector; + +} // namespace Shader::IR diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp index f92fc2571..7c08b25ce 100644 --- a/src/shader_recompiler/frontend/ir/basic_block.cpp +++ b/src/shader_recompiler/frontend/ir/basic_block.cpp @@ -14,10 +14,7 @@ namespace Shader::IR { -Block::Block(ObjectPool& inst_pool_, u32 begin, u32 end) - : inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {} - -Block::Block(ObjectPool& inst_pool_) : Block{inst_pool_, 0, 0} {} +Block::Block(ObjectPool& inst_pool_) : inst_pool{&inst_pool_} {} Block::~Block() = default; @@ -40,39 +37,15 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op, return result_it; } -void Block::SetBranches(Condition cond, Block* branch_true_, Block* branch_false_) { - branch_cond = cond; - branch_true = branch_true_; - branch_false = branch_false_; -} - -void Block::SetBranch(Block* branch) { - branch_cond = Condition{true}; - branch_true = branch; -} - -void Block::SetReturn() { - branch_cond = Condition{true}; - branch_true = nullptr; - branch_false = nullptr; -} - -bool Block::IsVirtual() const noexcept { - return location_begin == location_end; -} - -u32 Block::LocationBegin() const noexcept { - return location_begin; -} - -u32 Block::LocationEnd() const noexcept { - return location_end; -} - -void Block::AddImmediatePredecessor(Block* block) { - if (std::ranges::find(imm_predecessors, block) == imm_predecessors.end()) { - imm_predecessors.push_back(block); +void Block::AddBranch(Block* block) { + if (std::ranges::find(imm_successors, block) != imm_successors.end()) { + throw LogicError("Successor already inserted"); + } + if (std::ranges::find(block->imm_predecessors, this) != block->imm_predecessors.end()) { + throw LogicError("Predecessor already inserted"); } + imm_successors.push_back(block); + block->imm_predecessors.push_back(this); } static std::string BlockToIndex(const std::map& block_to_index, @@ -92,15 +65,11 @@ static size_t InstIndex(std::map& inst_to_index, size_t& in return it->second; } -static std::string ArgToIndex(const std::map& block_to_index, - std::map& inst_to_index, size_t& inst_index, +static std::string ArgToIndex(std::map& inst_to_index, size_t& inst_index, const Value& arg) { if (arg.IsEmpty()) { return ""; } - if (arg.IsLabel()) { - return BlockToIndex(block_to_index, arg.Label()); - } if (!arg.IsImmediate() || arg.IsIdentity()) { return fmt::format("%{}", InstIndex(inst_to_index, inst_index, arg.Inst())); } @@ -140,8 +109,7 @@ std::string DumpBlock(const Block& block, const std::map& if (const auto it{block_to_index.find(&block)}; it != block_to_index.end()) { ret += fmt::format(" ${}", it->second); } - ret += fmt::format(": begin={:04x} end={:04x}\n", block.LocationBegin(), block.LocationEnd()); - + ret += '\n'; for (const Inst& inst : block) { const Opcode op{inst.GetOpcode()}; ret += fmt::format("[{:016x}] ", reinterpret_cast(&inst)); @@ -153,7 +121,7 @@ std::string DumpBlock(const Block& block, const std::map& const size_t arg_count{inst.NumArgs()}; for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) { const Value arg{inst.Arg(arg_index)}; - const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, inst_index, arg)}; + const std::string arg_str{ArgToIndex(inst_to_index, inst_index, arg)}; ret += arg_index != 0 ? ", " : " "; if (op == Opcode::Phi) { ret += fmt::format("[ {}, {} ]", arg_str, diff --git a/src/shader_recompiler/frontend/ir/basic_block.h b/src/shader_recompiler/frontend/ir/basic_block.h index 0b0c97af6..7e134b4c7 100644 --- a/src/shader_recompiler/frontend/ir/basic_block.h +++ b/src/shader_recompiler/frontend/ir/basic_block.h @@ -12,6 +12,7 @@ #include #include "common/bit_cast.h" +#include "common/common_types.h" #include "shader_recompiler/frontend/ir/condition.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/object_pool.h" @@ -27,7 +28,6 @@ public: using reverse_iterator = InstructionList::reverse_iterator; using const_reverse_iterator = InstructionList::const_reverse_iterator; - explicit Block(ObjectPool& inst_pool_, u32 begin, u32 end); explicit Block(ObjectPool& inst_pool_); ~Block(); @@ -44,22 +44,8 @@ public: iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list args = {}, u32 flags = 0); - /// Set the branches to jump to when all instructions have executed. - void SetBranches(Condition cond, Block* branch_true, Block* branch_false); - /// Set the branch to unconditionally jump to when all instructions have executed. - void SetBranch(Block* branch); - /// Mark the block as a return block. - void SetReturn(); - - /// Returns true when the block does not implement any guest instructions directly. - [[nodiscard]] bool IsVirtual() const noexcept; - /// Gets the starting location of this basic block. - [[nodiscard]] u32 LocationBegin() const noexcept; - /// Gets the end location for this basic block. - [[nodiscard]] u32 LocationEnd() const noexcept; - - /// Adds a new immediate predecessor to this basic block. - void AddImmediatePredecessor(Block* block); + /// Adds a new branch to this basic block. + void AddBranch(Block* block); /// Gets a mutable reference to the instruction list for this basic block. [[nodiscard]] InstructionList& Instructions() noexcept { @@ -71,9 +57,13 @@ public: } /// Gets an immutable span to the immediate predecessors. - [[nodiscard]] std::span ImmediatePredecessors() const noexcept { + [[nodiscard]] std::span ImmPredecessors() const noexcept { return imm_predecessors; } + /// Gets an immutable span to the immediate successors. + [[nodiscard]] std::span ImmSuccessors() const noexcept { + return imm_successors; + } /// Intrusively store the host definition of this instruction. template @@ -87,19 +77,6 @@ public: return Common::BitCast(definition); } - [[nodiscard]] Condition BranchCondition() const noexcept { - return branch_cond; - } - [[nodiscard]] bool IsTerminationBlock() const noexcept { - return !branch_true && !branch_false; - } - [[nodiscard]] Block* TrueBranch() const noexcept { - return branch_true; - } - [[nodiscard]] Block* FalseBranch() const noexcept { - return branch_false; - } - void SetSsaRegValue(IR::Reg reg, const Value& value) noexcept { ssa_reg_values[RegIndex(reg)] = value; } @@ -178,22 +155,14 @@ public: private: /// Memory pool for instruction list ObjectPool* inst_pool; - /// Starting location of this block - u32 location_begin; - /// End location of this block - u32 location_end; /// List of instructions in this block InstructionList instructions; - /// Condition to choose the branch to take - Condition branch_cond{true}; - /// Block to jump into when the branch condition evaluates as true - Block* branch_true{nullptr}; - /// Block to jump into when the branch condition evaluates as false - Block* branch_false{nullptr}; /// Block immediate predecessors std::vector imm_predecessors; + /// Block immediate successors + std::vector imm_successors; /// Intrusively store the value of a register in the block. std::array ssa_reg_values; diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index ce6c9af07..eb45aa477 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -61,25 +61,28 @@ F64 IREmitter::Imm64(f64 value) const { return F64{Value{value}}; } -void IREmitter::Branch(Block* label) { - label->AddImmediatePredecessor(block); - block->SetBranch(label); - Inst(Opcode::Branch, label); +void IREmitter::Prologue() { + Inst(Opcode::Prologue); } -void IREmitter::BranchConditional(const U1& condition, Block* true_label, Block* false_label) { - block->SetBranches(IR::Condition{true}, true_label, false_label); - true_label->AddImmediatePredecessor(block); - false_label->AddImmediatePredecessor(block); - Inst(Opcode::BranchConditional, condition, true_label, false_label); +void IREmitter::Epilogue() { + Inst(Opcode::Epilogue); } -void IREmitter::LoopMerge(Block* merge_block, Block* continue_target) { - Inst(Opcode::LoopMerge, merge_block, continue_target); +void IREmitter::BranchConditionRef(const U1& cond) { + Inst(Opcode::BranchConditionRef, cond); } -void IREmitter::SelectionMerge(Block* merge_block) { - Inst(Opcode::SelectionMerge, merge_block); +void IREmitter::DemoteToHelperInvocation() { + Inst(Opcode::DemoteToHelperInvocation); +} + +void IREmitter::EmitVertex(const U32& stream) { + Inst(Opcode::EmitVertex, stream); +} + +void IREmitter::EndPrimitive(const U32& stream) { + Inst(Opcode::EndPrimitive, stream); } void IREmitter::Barrier() { @@ -94,37 +97,6 @@ void IREmitter::DeviceMemoryBarrier() { Inst(Opcode::DeviceMemoryBarrier); } -void IREmitter::Return() { - block->SetReturn(); - Inst(Opcode::Return); -} - -void IREmitter::Unreachable() { - Inst(Opcode::Unreachable); -} - -void IREmitter::DemoteToHelperInvocation(Block* continue_label) { - block->SetBranch(continue_label); - continue_label->AddImmediatePredecessor(block); - Inst(Opcode::DemoteToHelperInvocation, continue_label); -} - -void IREmitter::Prologue() { - Inst(Opcode::Prologue); -} - -void IREmitter::Epilogue() { - Inst(Opcode::Epilogue); -} - -void IREmitter::EmitVertex(const U32& stream) { - Inst(Opcode::EmitVertex, stream); -} - -void IREmitter::EndPrimitive(const U32& stream) { - Inst(Opcode::EndPrimitive, stream); -} - U32 IREmitter::GetReg(IR::Reg reg) { return Inst(Opcode::GetRegister, reg); } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index fd41b7e89..7a83c33d3 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -32,17 +32,10 @@ public: [[nodiscard]] U64 Imm64(s64 value) const; [[nodiscard]] F64 Imm64(f64 value) const; - void Branch(Block* label); - void BranchConditional(const U1& condition, Block* true_label, Block* false_label); - void LoopMerge(Block* merge_block, Block* continue_target); - void SelectionMerge(Block* merge_block); - void Return(); - void Unreachable(); - void DemoteToHelperInvocation(Block* continue_label); - void Prologue(); void Epilogue(); - + void BranchConditionRef(const U1& cond); + void DemoteToHelperInvocation(); void EmitVertex(const U32& stream); void EndPrimitive(const U32& stream); diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 616ef17d4..364574240 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -56,19 +56,14 @@ Inst::~Inst() { bool Inst::MayHaveSideEffects() const noexcept { switch (op) { - case Opcode::Branch: - case Opcode::BranchConditional: - case Opcode::LoopMerge: - case Opcode::SelectionMerge: - case Opcode::Return: + case Opcode::Prologue: + case Opcode::Epilogue: + case Opcode::BranchConditionRef: case Opcode::Join: - case Opcode::Unreachable: case Opcode::DemoteToHelperInvocation: case Opcode::Barrier: case Opcode::WorkgroupMemoryBarrier: case Opcode::DeviceMemoryBarrier: - case Opcode::Prologue: - case Opcode::Epilogue: case Opcode::EmitVertex: case Opcode::EndPrimitive: case Opcode::SetAttribute: diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h index 2b9c0ed8c..56b001902 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.h +++ b/src/shader_recompiler/frontend/ir/opcodes.h @@ -30,7 +30,6 @@ struct OpcodeMeta { // using enum Type; constexpr Type Void{Type::Void}; constexpr Type Opaque{Type::Opaque}; -constexpr Type Label{Type::Label}; constexpr Type Reg{Type::Reg}; constexpr Type Pred{Type::Pred}; constexpr Type Attribute{Type::Attribute}; diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 9165421f8..75ddb6b6f 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -7,27 +7,20 @@ OPCODE(Phi, Opaque, OPCODE(Identity, Opaque, Opaque, ) OPCODE(Void, Void, ) -// Control flow -OPCODE(Branch, Void, Label, ) -OPCODE(BranchConditional, Void, U1, Label, Label, ) -OPCODE(LoopMerge, Void, Label, Label, ) -OPCODE(SelectionMerge, Void, Label, ) -OPCODE(Return, Void, ) +// Special operations +OPCODE(Prologue, Void, ) +OPCODE(Epilogue, Void, ) +OPCODE(BranchConditionRef, Void, U1, ) OPCODE(Join, Void, ) -OPCODE(Unreachable, Void, ) -OPCODE(DemoteToHelperInvocation, Void, Label, ) +OPCODE(DemoteToHelperInvocation, Void, ) +OPCODE(EmitVertex, Void, U32, ) +OPCODE(EndPrimitive, Void, U32, ) // Barriers OPCODE(Barrier, Void, ) OPCODE(WorkgroupMemoryBarrier, Void, ) OPCODE(DeviceMemoryBarrier, Void, ) -// Special operations -OPCODE(Prologue, Void, ) -OPCODE(Epilogue, Void, ) -OPCODE(EmitVertex, Void, U32, ) -OPCODE(EndPrimitive, Void, U32, ) - // Context getters/setters OPCODE(GetRegister, U32, Reg, ) OPCODE(SetRegister, Void, Reg, U32, ) diff --git a/src/shader_recompiler/frontend/ir/post_order.cpp b/src/shader_recompiler/frontend/ir/post_order.cpp index 8709a2ea1..1a28df7fb 100644 --- a/src/shader_recompiler/frontend/ir/post_order.cpp +++ b/src/shader_recompiler/frontend/ir/post_order.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include #include @@ -10,35 +12,31 @@ namespace Shader::IR { -BlockList PostOrder(const BlockList& blocks) { +BlockList PostOrder(const AbstractSyntaxNode& root) { boost::container::small_vector block_stack; boost::container::flat_set visited; - BlockList post_order_blocks; - post_order_blocks.reserve(blocks.size()); - Block* const first_block{blocks.front()}; + if (root.type != AbstractSyntaxNode::Type::Block) { + throw LogicError("First node in abstract syntax list root is not a block"); + } + Block* const first_block{root.block}; visited.insert(first_block); block_stack.push_back(first_block); - const auto visit_branch = [&](Block* block, Block* branch) { - if (!branch) { - return false; - } - if (!visited.insert(branch).second) { - return false; - } - // Calling push_back twice is faster than insert on MSVC - block_stack.push_back(block); - block_stack.push_back(branch); - return true; - }; while (!block_stack.empty()) { Block* const block{block_stack.back()}; + const auto visit{[&](Block* branch) { + if (!visited.insert(branch).second) { + return false; + } + // Calling push_back twice is faster than insert on MSVC + block_stack.push_back(block); + block_stack.push_back(branch); + return true; + }}; block_stack.pop_back(); - - if (!visit_branch(block, block->TrueBranch()) && - !visit_branch(block, block->FalseBranch())) { + if (std::ranges::none_of(block->ImmSuccessors(), visit)) { post_order_blocks.push_back(block); } } diff --git a/src/shader_recompiler/frontend/ir/post_order.h b/src/shader_recompiler/frontend/ir/post_order.h index 30137ff57..58a0467a0 100644 --- a/src/shader_recompiler/frontend/ir/post_order.h +++ b/src/shader_recompiler/frontend/ir/post_order.h @@ -5,9 +5,10 @@ #pragma once #include "shader_recompiler/frontend/ir/basic_block.h" +#include "shader_recompiler/frontend/ir/abstract_syntax_list.h" namespace Shader::IR { -BlockList PostOrder(const BlockList& blocks); +BlockList PostOrder(const AbstractSyntaxNode& root); } // namespace Shader::IR diff --git a/src/shader_recompiler/frontend/ir/program.h b/src/shader_recompiler/frontend/ir/program.h index 51e1a8c77..9ede5b48d 100644 --- a/src/shader_recompiler/frontend/ir/program.h +++ b/src/shader_recompiler/frontend/ir/program.h @@ -7,8 +7,7 @@ #include #include -#include - +#include "shader_recompiler/frontend/ir/abstract_syntax_list.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/program_header.h" #include "shader_recompiler/shader_info.h" @@ -17,6 +16,7 @@ namespace Shader::IR { struct Program { + AbstractSyntaxList syntax_list; BlockList blocks; BlockList post_order_blocks; Info info; diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h index 8b3b33852..294b230c4 100644 --- a/src/shader_recompiler/frontend/ir/type.h +++ b/src/shader_recompiler/frontend/ir/type.h @@ -16,31 +16,30 @@ namespace Shader::IR { enum class Type { Void = 0, Opaque = 1 << 0, - Label = 1 << 1, - Reg = 1 << 2, - Pred = 1 << 3, - Attribute = 1 << 4, - Patch = 1 << 5, - U1 = 1 << 6, - U8 = 1 << 7, - U16 = 1 << 8, - U32 = 1 << 9, - U64 = 1 << 10, - F16 = 1 << 11, - F32 = 1 << 12, - F64 = 1 << 13, - U32x2 = 1 << 14, - U32x3 = 1 << 15, - U32x4 = 1 << 16, - F16x2 = 1 << 17, - F16x3 = 1 << 18, - F16x4 = 1 << 19, - F32x2 = 1 << 20, - F32x3 = 1 << 21, - F32x4 = 1 << 22, - F64x2 = 1 << 23, - F64x3 = 1 << 24, - F64x4 = 1 << 25, + Reg = 1 << 1, + Pred = 1 << 2, + Attribute = 1 << 3, + Patch = 1 << 4, + U1 = 1 << 5, + U8 = 1 << 6, + U16 = 1 << 7, + U32 = 1 << 8, + U64 = 1 << 9, + F16 = 1 << 10, + F32 = 1 << 11, + F64 = 1 << 12, + U32x2 = 1 << 13, + U32x3 = 1 << 14, + U32x4 = 1 << 15, + F16x2 = 1 << 16, + F16x3 = 1 << 17, + F16x4 = 1 << 18, + F32x2 = 1 << 19, + F32x3 = 1 << 20, + F32x4 = 1 << 21, + F64x2 = 1 << 22, + F64x3 = 1 << 23, + F64x4 = 1 << 24, }; DECLARE_ENUM_FLAG_OPERATORS(Type) diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp index b962f170d..d365ea1bc 100644 --- a/src/shader_recompiler/frontend/ir/value.cpp +++ b/src/shader_recompiler/frontend/ir/value.cpp @@ -9,8 +9,6 @@ namespace Shader::IR { Value::Value(IR::Inst* value) noexcept : type{Type::Opaque}, inst{value} {} -Value::Value(IR::Block* value) noexcept : type{Type::Label}, label{value} {} - Value::Value(IR::Reg value) noexcept : type{Type::Reg}, reg{value} {} Value::Value(IR::Pred value) noexcept : type{Type::Pred}, pred{value} {} @@ -33,10 +31,6 @@ Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {} Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {} -bool Value::IsLabel() const noexcept { - return type == Type::Label; -} - IR::Type Value::Type() const noexcept { if (IsPhi()) { // The type of a phi node is stored in its flags @@ -60,8 +54,6 @@ bool Value::operator==(const Value& other) const { return true; case Type::Opaque: return inst == other.inst; - case Type::Label: - return label == other.label; case Type::Reg: return reg == other.reg; case Type::Pred: diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index beaf149f3..2ce49f953 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -37,7 +37,6 @@ class Value { public: Value() noexcept = default; explicit Value(IR::Inst* value) noexcept; - explicit Value(IR::Block* value) noexcept; explicit Value(IR::Reg value) noexcept; explicit Value(IR::Pred value) noexcept; explicit Value(IR::Attribute value) noexcept; @@ -54,11 +53,9 @@ public: [[nodiscard]] bool IsPhi() const noexcept; [[nodiscard]] bool IsEmpty() const noexcept; [[nodiscard]] bool IsImmediate() const noexcept; - [[nodiscard]] bool IsLabel() const noexcept; [[nodiscard]] IR::Type Type() const noexcept; [[nodiscard]] IR::Inst* Inst() const; - [[nodiscard]] IR::Block* Label() const; [[nodiscard]] IR::Inst* InstRecursive() const; [[nodiscard]] IR::Value Resolve() const; [[nodiscard]] IR::Reg Reg() const; @@ -80,7 +77,6 @@ private: IR::Type type{}; union { IR::Inst* inst{}; - IR::Block* label; IR::Reg reg; IR::Pred pred; IR::Attribute attribute; @@ -304,11 +300,6 @@ inline IR::Inst* Value::Inst() const { return inst; } -inline IR::Block* Value::Label() const { - DEBUG_ASSERT(type == Type::Label); - return label; -} - inline IR::Inst* Value::InstRecursive() const { DEBUG_ASSERT(type == Type::Opaque); if (IsIdentity()) { diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp index 0d3f00699..017c4b8fd 100644 --- a/src/shader_recompiler/frontend/maxwell/program.cpp +++ b/src/shader_recompiler/frontend/maxwell/program.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "shader_recompiler/frontend/ir/basic_block.h" @@ -15,6 +16,16 @@ namespace Shader::Maxwell { namespace { +IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { + auto syntax_blocks{syntax_list | std::views::filter([](const auto& node) { + return node.type == IR::AbstractSyntaxNode::Type::Block; + })}; + IR::BlockList blocks(std::ranges::distance(syntax_blocks)); + std::ranges::transform(syntax_blocks, blocks.begin(), + [](const IR::AbstractSyntaxNode& node) { return node.block; }); + return blocks; +} + void RemoveUnreachableBlocks(IR::Program& program) { // Some blocks might be unreachable if a function call exists unconditionally // If this happens the number of blocks and post order blocks will mismatch @@ -23,7 +34,7 @@ void RemoveUnreachableBlocks(IR::Program& program) { } const auto begin{program.blocks.begin() + 1}; const auto end{program.blocks.end()}; - const auto pred{[](IR::Block* block) { return block->ImmediatePredecessors().empty(); }}; + const auto pred{[](IR::Block* block) { return block->ImmPredecessors().empty(); }}; program.blocks.erase(std::remove_if(begin, end, pred), end); } @@ -110,8 +121,9 @@ void AddNVNStorageBuffers(IR::Program& program) { IR::Program TranslateProgram(ObjectPool& inst_pool, ObjectPool& block_pool, Environment& env, Flow::CFG& cfg) { IR::Program program; - program.blocks = VisitAST(inst_pool, block_pool, env, cfg); - program.post_order_blocks = PostOrder(program.blocks); + program.syntax_list = BuildASL(inst_pool, block_pool, env, cfg); + program.blocks = GenerateBlocks(program.syntax_list); + program.post_order_blocks = PostOrder(program.syntax_list.front()); program.stage = env.ShaderStage(); program.local_memory_size = env.LocalMemorySize(); switch (program.stage) { @@ -159,9 +171,7 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b Optimization::VertexATransformPass(vertex_a); Optimization::VertexBTransformPass(vertex_b); std::swap(result.blocks, vertex_a.blocks); - for (IR::Block* block : vertex_b.blocks) { - result.blocks.push_back(block); - } + result.blocks.insert(result.blocks.end(), vertex_b.blocks.begin(), vertex_b.blocks.end()); result.stage = Stage::VertexB; result.info = vertex_a.info; result.local_memory_size = std::max(vertex_a.local_memory_size, vertex_b.local_memory_size); @@ -173,7 +183,7 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b Optimization::JoinTextureInfo(result.info, vertex_b.info); Optimization::JoinStorageInfo(result.info, vertex_b.info); Optimization::DualVertexJoinPass(result); - result.post_order_blocks = PostOrder(result.blocks); + result.post_order_blocks = PostOrder(result.syntax_list.front()); Optimization::DeadCodeEliminationPass(result); Optimization::VerificationPass(result); Optimization::CollectShaderInfoPass(env_vertex_b, result); diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index cc5410c6d..e7e2e9c82 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -36,7 +36,6 @@ using Tree = boost::intrusive::list>; using Node = Tree::iterator; -using ConstNode = Tree::const_iterator; enum class StatementType { Code, @@ -91,7 +90,8 @@ struct IndirectBranchCond {}; #pragma warning(disable : 26495) // Always initialize a member variable, expected in Statement #endif struct Statement : ListBaseHook { - Statement(IR::Block* code_, Statement* up_) : code{code_}, up{up_}, type{StatementType::Code} {} + Statement(const Flow::Block* block_, Statement* up_) + : block{block_}, up{up_}, type{StatementType::Code} {} Statement(Goto, Statement* cond_, Node label_, Statement* up_) : label{label_}, cond{cond_}, up{up_}, type{StatementType::Goto} {} Statement(Label, u32 id_, Statement* up_) : id{id_}, up{up_}, type{StatementType::Label} {} @@ -125,7 +125,7 @@ struct Statement : ListBaseHook { } union { - IR::Block* code; + const Flow::Block* block; Node label; Tree children; IR::Condition guest_cond; @@ -171,8 +171,8 @@ std::string DumpTree(const Tree& tree, u32 indentation = 0) { switch (stmt->type) { case StatementType::Code: ret += fmt::format("{} Block {:04x} -> {:04x} (0x{:016x});\n", indent, - stmt->code->LocationBegin(), stmt->code->LocationEnd(), - reinterpret_cast(stmt->code)); + stmt->block->begin, stmt->block->end, + reinterpret_cast(stmt->block)); break; case StatementType::Goto: ret += fmt::format("{} if ({}) goto L{};\n", indent, DumpExpr(stmt->cond), @@ -407,11 +407,7 @@ private: }}; root.push_front(make_reset_variable()); root.insert(ip, make_reset_variable()); - - const u32 begin_offset{block.begin.Offset()}; - const u32 end_offset{block.end.Offset()}; - IR::Block* const ir_block{block_pool.Create(inst_pool, begin_offset, end_offset)}; - root.insert(ip, *pool.Create(ir_block, &root_stmt)); + root.insert(ip, *pool.Create(&block, &root_stmt)); switch (block.end_class) { case Flow::EndClass::Branch: { @@ -620,13 +616,13 @@ private: Statement root_stmt{FunctionTag{}}; }; -IR::Block* TryFindForwardBlock(const Statement& stmt) { - const Tree& tree{stmt.up->children}; - const ConstNode end{tree.cend()}; - ConstNode forward_node{std::next(Tree::s_iterator_to(stmt))}; +[[nodiscard]] Statement* TryFindForwardBlock(Statement& stmt) { + Tree& tree{stmt.up->children}; + const Node end{tree.end()}; + Node forward_node{std::next(Tree::s_iterator_to(stmt))}; while (forward_node != end && !HasChildren(forward_node->type)) { if (forward_node->type == StatementType::Code) { - return forward_node->code; + return &*forward_node; } ++forward_node; } @@ -654,21 +650,29 @@ class TranslatePass { public: TranslatePass(ObjectPool& inst_pool_, ObjectPool& block_pool_, ObjectPool& stmt_pool_, Environment& env_, Statement& root_stmt, - IR::BlockList& block_list_) + IR::AbstractSyntaxList& syntax_list_) : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, env{env_}, - block_list{block_list_} { + syntax_list{syntax_list_} { Visit(root_stmt, nullptr, nullptr); - IR::Block& first_block{*block_list.front()}; + IR::Block& first_block{*syntax_list.front().block}; IR::IREmitter ir{first_block, first_block.begin()}; ir.Prologue(); } private: - void Visit(Statement& parent, IR::Block* continue_block, IR::Block* break_block) { + void Visit(Statement& parent, IR::Block* break_block, IR::Block* fallthrough_block) { + IR::Block* current_block{}; + const auto ensure_block{[&] { + if (current_block) { + return; + } + current_block = block_pool.Create(inst_pool); + auto& node{syntax_list.emplace_back()}; + node.type = IR::AbstractSyntaxNode::Type::Block; + node.block = current_block; + }}; Tree& tree{parent.children}; - IR::Block* current_block{nullptr}; - for (auto it = tree.begin(); it != tree.end(); ++it) { Statement& stmt{*it}; switch (stmt.type) { @@ -676,124 +680,157 @@ private: // Labels can be ignored break; case StatementType::Code: { - if (current_block && current_block != stmt.code) { - IR::IREmitter{*current_block}.Branch(stmt.code); - } - current_block = stmt.code; - Translate(env, stmt.code); - block_list.push_back(stmt.code); + ensure_block(); + Translate(env, current_block, stmt.block->begin.Offset(), stmt.block->end.Offset()); break; } case StatementType::SetVariable: { - if (!current_block) { - current_block = MergeBlock(parent, stmt); - } + ensure_block(); IR::IREmitter ir{*current_block}; ir.SetGotoVariable(stmt.id, VisitExpr(ir, *stmt.op)); break; } case StatementType::SetIndirectBranchVariable: { - if (!current_block) { - current_block = MergeBlock(parent, stmt); - } + ensure_block(); IR::IREmitter ir{*current_block}; IR::U32 address{ir.IAdd(ir.GetReg(stmt.branch_reg), ir.Imm32(stmt.branch_offset))}; ir.SetIndirectBranchVariable(address); break; } case StatementType::If: { - if (!current_block) { - current_block = block_pool.Create(inst_pool); - block_list.push_back(current_block); - } + ensure_block(); IR::Block* const merge_block{MergeBlock(parent, stmt)}; - // Visit children - const size_t first_block_index{block_list.size()}; - Visit(stmt, merge_block, break_block); - // Implement if header block - IR::Block* const first_if_block{block_list.at(first_block_index)}; IR::IREmitter ir{*current_block}; const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.SelectionMerge(merge_block); - ir.BranchConditional(cond, first_if_block, merge_block); + ir.BranchConditionRef(cond); + const size_t if_node_index{syntax_list.size()}; + syntax_list.emplace_back(); + + // Visit children + const size_t then_block_index{syntax_list.size()}; + Visit(stmt, break_block, merge_block); + + IR::Block* const then_block{syntax_list.at(then_block_index).block}; + current_block->AddBranch(then_block); + current_block->AddBranch(merge_block); current_block = merge_block; + + auto& if_node{syntax_list[if_node_index]}; + if_node.type = IR::AbstractSyntaxNode::Type::If; + if_node.if_node.cond = cond; + if_node.if_node.body = then_block; + if_node.if_node.merge = merge_block; + + auto& endif_node{syntax_list.emplace_back()}; + endif_node.type = IR::AbstractSyntaxNode::Type::EndIf; + endif_node.end_if.merge = merge_block; + + auto& merge{syntax_list.emplace_back()}; + merge.type = IR::AbstractSyntaxNode::Type::Block; + merge.block = merge_block; break; } case StatementType::Loop: { IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; if (current_block) { - IR::IREmitter{*current_block}.Branch(loop_header_block); + current_block->AddBranch(loop_header_block); } - block_list.push_back(loop_header_block); + auto& header_node{syntax_list.emplace_back()}; + header_node.type = IR::AbstractSyntaxNode::Type::Block; + header_node.block = loop_header_block; - IR::Block* const new_continue_block{block_pool.Create(inst_pool)}; + IR::Block* const continue_block{block_pool.Create(inst_pool)}; IR::Block* const merge_block{MergeBlock(parent, stmt)}; + const size_t loop_node_index{syntax_list.size()}; + syntax_list.emplace_back(); + // Visit children - const size_t first_block_index{block_list.size()}; - Visit(stmt, new_continue_block, merge_block); + const size_t body_block_index{syntax_list.size()}; + Visit(stmt, merge_block, continue_block); // The continue block is located at the end of the loop - block_list.push_back(new_continue_block); + IR::IREmitter ir{*continue_block}; + const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; + ir.BranchConditionRef(cond); - // Implement loop header block - IR::Block* const first_loop_block{block_list.at(first_block_index)}; - IR::IREmitter ir{*loop_header_block}; - ir.LoopMerge(merge_block, new_continue_block); - ir.Branch(first_loop_block); + IR::Block* const body_block{syntax_list.at(body_block_index).block}; + loop_header_block->AddBranch(body_block); - // Implement continue block - IR::IREmitter continue_ir{*new_continue_block}; - const IR::U1 continue_cond{VisitExpr(continue_ir, *stmt.cond)}; - continue_ir.BranchConditional(continue_cond, ir.block, merge_block); + continue_block->AddBranch(loop_header_block); + continue_block->AddBranch(merge_block); current_block = merge_block; + + auto& loop{syntax_list[loop_node_index]}; + loop.type = IR::AbstractSyntaxNode::Type::Loop; + loop.loop.body = body_block; + loop.loop.continue_block = continue_block; + loop.loop.merge = merge_block; + + auto& continue_block_node{syntax_list.emplace_back()}; + continue_block_node.type = IR::AbstractSyntaxNode::Type::Block; + continue_block_node.block = continue_block; + + auto& repeat{syntax_list.emplace_back()}; + repeat.type = IR::AbstractSyntaxNode::Type::Repeat; + repeat.repeat.cond = cond; + repeat.repeat.loop_header = loop_header_block; + repeat.repeat.merge = merge_block; + + auto& merge{syntax_list.emplace_back()}; + merge.type = IR::AbstractSyntaxNode::Type::Block; + merge.block = merge_block; break; } case StatementType::Break: { - if (!current_block) { - current_block = block_pool.Create(inst_pool); - block_list.push_back(current_block); - } + ensure_block(); IR::Block* const skip_block{MergeBlock(parent, stmt)}; IR::IREmitter ir{*current_block}; - ir.BranchConditional(VisitExpr(ir, *stmt.cond), break_block, skip_block); - + const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; + ir.BranchConditionRef(cond); + current_block->AddBranch(break_block); + current_block->AddBranch(skip_block); current_block = skip_block; + + auto& break_node{syntax_list.emplace_back()}; + break_node.type = IR::AbstractSyntaxNode::Type::Break; + break_node.break_node.cond = cond; + break_node.break_node.merge = break_block; + break_node.break_node.skip = skip_block; + + auto& merge{syntax_list.emplace_back()}; + merge.type = IR::AbstractSyntaxNode::Type::Block; + merge.block = skip_block; break; } case StatementType::Return: { - if (!current_block) { - current_block = block_pool.Create(inst_pool); - block_list.push_back(current_block); - } - IR::IREmitter ir{*current_block}; - ir.Epilogue(); - ir.Return(); + ensure_block(); + IR::IREmitter{*current_block}.Epilogue(); current_block = nullptr; + syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Return; break; } case StatementType::Kill: { - if (!current_block) { - current_block = block_pool.Create(inst_pool); - block_list.push_back(current_block); - } + ensure_block(); IR::Block* demote_block{MergeBlock(parent, stmt)}; - IR::IREmitter{*current_block}.DemoteToHelperInvocation(demote_block); + IR::IREmitter{*current_block}.DemoteToHelperInvocation(); + current_block->AddBranch(demote_block); current_block = demote_block; + + auto& merge{syntax_list.emplace_back()}; + merge.type = IR::AbstractSyntaxNode::Type::Block; + merge.block = demote_block; break; } case StatementType::Unreachable: { - if (!current_block) { - current_block = block_pool.Create(inst_pool); - block_list.push_back(current_block); - } - IR::IREmitter{*current_block}.Unreachable(); + ensure_block(); current_block = nullptr; + syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Unreachable; break; } default: @@ -801,42 +838,42 @@ private: } } if (current_block) { - IR::IREmitter ir{*current_block}; - if (continue_block) { - ir.Branch(continue_block); + if (fallthrough_block) { + current_block->AddBranch(fallthrough_block); } else { - ir.Unreachable(); + syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Unreachable; } } } IR::Block* MergeBlock(Statement& parent, Statement& stmt) { - if (IR::Block* const block{TryFindForwardBlock(stmt)}) { - return block; + Statement* merge_stmt{TryFindForwardBlock(stmt)}; + if (!merge_stmt) { + // Create a merge block we can visit later + merge_stmt = stmt_pool.Create(&dummy_flow_block, &parent); + parent.children.insert(std::next(Tree::s_iterator_to(stmt)), *merge_stmt); } - // Create a merge block we can visit later - IR::Block* const block{block_pool.Create(inst_pool)}; - Statement* const merge_stmt{stmt_pool.Create(block, &parent)}; - parent.children.insert(std::next(Tree::s_iterator_to(stmt)), *merge_stmt); - return block; + return block_pool.Create(inst_pool); } ObjectPool& stmt_pool; ObjectPool& inst_pool; ObjectPool& block_pool; Environment& env; - IR::BlockList& block_list; + IR::AbstractSyntaxList& syntax_list; + // TODO: Make this constexpr when std::vector is constexpr + const Flow::Block dummy_flow_block; }; } // Anonymous namespace -IR::BlockList VisitAST(ObjectPool& inst_pool, ObjectPool& block_pool, - Environment& env, Flow::CFG& cfg) { +IR::AbstractSyntaxList BuildASL(ObjectPool& inst_pool, ObjectPool& block_pool, + Environment& env, Flow::CFG& cfg) { ObjectPool stmt_pool{64}; GotoPass goto_pass{cfg, inst_pool, block_pool, stmt_pool}; Statement& root{goto_pass.RootStatement()}; - IR::BlockList block_list; - TranslatePass{inst_pool, block_pool, stmt_pool, env, root, block_list}; - return block_list; + IR::AbstractSyntaxList syntax_list; + TranslatePass{inst_pool, block_pool, stmt_pool, env, root, syntax_list}; + return syntax_list; } } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.h b/src/shader_recompiler/frontend/maxwell/structured_control_flow.h index a6be12ba2..88b083649 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.h +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.h @@ -4,12 +4,8 @@ #pragma once -#include -#include - -#include - #include "shader_recompiler/environment.h" +#include "shader_recompiler/frontend/ir/abstract_syntax_list.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/frontend/maxwell/control_flow.h" @@ -17,8 +13,8 @@ namespace Shader::Maxwell { -[[nodiscard]] IR::BlockList VisitAST(ObjectPool& inst_pool, - ObjectPool& block_pool, Environment& env, - Flow::CFG& cfg); +[[nodiscard]] IR::AbstractSyntaxList BuildASL(ObjectPool& inst_pool, + ObjectPool& block_pool, Environment& env, + Flow::CFG& cfg); } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/translate/translate.cpp b/src/shader_recompiler/frontend/maxwell/translate/translate.cpp index f1230f58f..0f4e7a251 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/translate.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/translate.cpp @@ -23,13 +23,12 @@ static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) { } } -void Translate(Environment& env, IR::Block* block) { - if (block->IsVirtual()) { +void Translate(Environment& env, IR::Block* block, u32 location_begin, u32 location_end) { + if (location_begin == location_end) { return; } TranslatorVisitor visitor{env, *block}; - const Location pc_end{block->LocationEnd()}; - for (Location pc = block->LocationBegin(); pc != pc_end; ++pc) { + for (Location pc = location_begin; pc != location_end; ++pc) { const u64 insn{env.ReadInstruction(pc.Offset())}; const Opcode opcode{Decode(insn)}; switch (opcode) { diff --git a/src/shader_recompiler/frontend/maxwell/translate/translate.h b/src/shader_recompiler/frontend/maxwell/translate/translate.h index e1aa2e0f4..a3edd2e46 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/translate.h +++ b/src/shader_recompiler/frontend/maxwell/translate/translate.h @@ -9,6 +9,6 @@ namespace Shader::Maxwell { -void Translate(Environment& env, IR::Block* block); +void Translate(Environment& env, IR::Block* block, u32 location_begin, u32 location_end); } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index b1c45d13a..66f1391db 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -353,24 +353,6 @@ IR::Value EvalImmediates(const IR::Inst& inst, Func&& func, std::index_sequence< return IR::Value{func(Arg>(inst.Arg(I))...)}; } -void FoldBranchConditional(IR::Inst& inst) { - const IR::U1 cond{inst.Arg(0)}; - if (cond.IsImmediate()) { - // TODO: Convert to Branch - return; - } - const IR::Inst* cond_inst{cond.InstRecursive()}; - if (cond_inst->GetOpcode() == IR::Opcode::LogicalNot) { - const IR::Value true_label{inst.Arg(1)}; - const IR::Value false_label{inst.Arg(2)}; - // Remove negation on the conditional (take the parameter out of LogicalNot) and swap - // the branches - inst.SetArg(0, cond_inst->Arg(0)); - inst.SetArg(1, false_label); - inst.SetArg(2, true_label); - } -} - std::optional FoldCompositeExtractImpl(IR::Value inst_value, IR::Opcode insert, IR::Opcode construct, u32 first_index) { IR::Inst* const inst{inst_value.InstRecursive()}; @@ -581,8 +563,6 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { return (base & ~(~(~0u << bits) << offset)) | (insert << offset); }); return; - case IR::Opcode::BranchConditional: - return FoldBranchConditional(inst); case IR::Opcode::CompositeExtractF32x2: return FoldCompositeExtract(inst, IR::Opcode::CompositeConstructF32x2, IR::Opcode::CompositeInsertF32x2); diff --git a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp index f2d7db0e6..b0a9f5258 100644 --- a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp +++ b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp @@ -13,60 +13,16 @@ namespace Shader::Optimization { -void VertexATransformPass(IR::Program& program) { - bool replaced_join{}; - bool eliminated_epilogue{}; - for (IR::Block* const block : program.post_order_blocks) { - for (IR::Inst& inst : block->Instructions()) { - switch (inst.GetOpcode()) { - case IR::Opcode::Return: - inst.ReplaceOpcode(IR::Opcode::Join); - replaced_join = true; - break; - case IR::Opcode::Epilogue: - inst.Invalidate(); - eliminated_epilogue = true; - break; - default: - break; - } - if (replaced_join && eliminated_epilogue) { - return; - } - } - } +void VertexATransformPass(IR::Program&) { + throw NotImplementedException("VertexA pass"); } -void VertexBTransformPass(IR::Program& program) { - for (IR::Block* const block : program.blocks) { - for (IR::Inst& inst : block->Instructions()) { - if (inst.GetOpcode() == IR::Opcode::Prologue) { - return inst.Invalidate(); - } - } - } +void VertexBTransformPass(IR::Program&) { + throw NotImplementedException("VertexA pass"); } -void DualVertexJoinPass(IR::Program& program) { - const auto& blocks = program.blocks; - const s64 sub_size = static_cast(blocks.size()) - 1; - if (sub_size < 1) { - throw LogicError("Dual Vertex Join pass failed, expected atleast 2 blocks"); - } - for (s64 index = 0; index < sub_size; ++index) { - IR::Block* const current_block{blocks[index]}; - IR::Block* const next_block{blocks[index + 1]}; - for (IR::Inst& inst : current_block->Instructions()) { - if (inst.GetOpcode() == IR::Opcode::Join) { - IR::IREmitter ir{*current_block, IR::Block::InstructionList::s_iterator_to(inst)}; - ir.Branch(next_block); - inst.Invalidate(); - // Only 1 join should exist - return; - } - } - } - throw LogicError("Dual Vertex Join pass failed, no join present"); +void DualVertexJoinPass(IR::Program&) { + throw NotImplementedException("VertexA pass"); } } // namespace Shader::Optimization diff --git a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp index 6afbe24f7..e9b55f835 100644 --- a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp +++ b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp @@ -12,7 +12,6 @@ namespace Shader::Optimization { void IdentityRemovalPass(IR::Program& program) { std::vector to_invalidate; - for (IR::Block* const block : program.blocks) { for (auto inst = block->begin(); inst != block->end();) { const size_t num_args{inst->NumArgs()}; diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index a8064a5d0..26eb3a3ab 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -202,7 +202,7 @@ public: incomplete_phis[block].insert_or_assign(variable, phi); stack.back().result = IR::Value{&*phi}; - } else if (const std::span imm_preds{block->ImmediatePredecessors()}; + } else if (const std::span imm_preds = block->ImmPredecessors(); imm_preds.size() == 1) { // Optimize the common case of one predecessor: no phi needed stack.back().pc = Status::SetValue; @@ -257,7 +257,7 @@ public: private: template IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { - for (IR::Block* const imm_pred : block->ImmediatePredecessors()) { + for (IR::Block* const imm_pred : block->ImmPredecessors()) { phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred)); } return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); -- 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 ++++++++-- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 6 ++- .../backend/spirv/emit_spirv_instructions.h | 3 +- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 18 +++++-- src/shader_recompiler/frontend/ir/ir_emitter.h | 4 +- .../frontend/ir/microinstruction.cpp | 3 +- src/shader_recompiler/frontend/ir/opcodes.inc | 3 +- src/shader_recompiler/frontend/ir/value.h | 4 ++ .../frontend/maxwell/structured_control_flow.cpp | 6 +-- src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 6 +-- 12 files changed, 117 insertions(+), 25 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(); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index c22edfec2..7bf8c78de 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -468,7 +468,11 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { return id; } -void EmitBranchConditionRef(EmitContext&) {} +void EmitDummyReference(EmitContext&) {} + +void EmitPhiMove(EmitContext&) { + throw LogicError("Unreachable instruction"); +} void EmitGetZeroFromOp(EmitContext&) { throw LogicError("Unreachable instruction"); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 2f4f6e59e..0a2b31772 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -23,7 +23,8 @@ class EmitContext; Id EmitPhi(EmitContext& ctx, IR::Inst* inst); void EmitVoid(EmitContext& ctx); Id EmitIdentity(EmitContext& ctx, const IR::Value& value); -void EmitBranchConditionRef(EmitContext&); +void EmitDummyReference(EmitContext&); +void EmitPhiMove(EmitContext&); void EmitJoin(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); void EmitBarrier(EmitContext& ctx); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index eb45aa477..def29143e 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -61,6 +61,14 @@ F64 IREmitter::Imm64(f64 value) const { return F64{Value{value}}; } +void IREmitter::DummyReference(const Value& value) { + Inst(Opcode::DummyReference, value); +} + +void IREmitter::PhiMove(IR::Inst& phi, const Value& value) { + Inst(Opcode::PhiMove, Value{&phi}, value); +} + void IREmitter::Prologue() { Inst(Opcode::Prologue); } @@ -69,10 +77,6 @@ void IREmitter::Epilogue() { Inst(Opcode::Epilogue); } -void IREmitter::BranchConditionRef(const U1& cond) { - Inst(Opcode::BranchConditionRef, cond); -} - void IREmitter::DemoteToHelperInvocation() { Inst(Opcode::DemoteToHelperInvocation); } @@ -106,6 +110,9 @@ void IREmitter::SetReg(IR::Reg reg, const U32& value) { } U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) { + if (pred == Pred::PT) { + return Imm1(!is_negated); + } const U1 value{Inst(Opcode::GetPred, pred)}; if (is_negated) { return Inst(Opcode::LogicalNot, value); @@ -264,6 +271,9 @@ static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { U1 IREmitter::Condition(IR::Condition cond) { const FlowTest flow_test{cond.GetFlowTest()}; const auto [pred, is_negated]{cond.GetPred()}; + if (flow_test == FlowTest::T) { + return GetPred(pred, is_negated); + } return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test)); } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 7a83c33d3..4f7c820fe 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -32,9 +32,11 @@ public: [[nodiscard]] U64 Imm64(s64 value) const; [[nodiscard]] F64 Imm64(f64 value) const; + void DummyReference(const Value& value); + void PhiMove(IR::Inst& phi, const Value& value); + void Prologue(); void Epilogue(); - void BranchConditionRef(const U1& cond); void DemoteToHelperInvocation(); void EmitVertex(const U32& stream); void EndPrimitive(const U32& stream); diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 364574240..267aebc61 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -56,9 +56,10 @@ Inst::~Inst() { bool Inst::MayHaveSideEffects() const noexcept { switch (op) { + case Opcode::DummyReference: + case Opcode::PhiMove: case Opcode::Prologue: case Opcode::Epilogue: - case Opcode::BranchConditionRef: case Opcode::Join: case Opcode::DemoteToHelperInvocation: case Opcode::Barrier: diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 75ddb6b6f..6196b867d 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -6,11 +6,12 @@ OPCODE(Phi, Opaque, ) OPCODE(Identity, Opaque, Opaque, ) OPCODE(Void, Void, ) +OPCODE(DummyReference, Void, Opaque, ) +OPCODE(PhiMove, Void, Opaque, Opaque, ) // Special operations OPCODE(Prologue, Void, ) OPCODE(Epilogue, Void, ) -OPCODE(BranchConditionRef, Void, U1, ) OPCODE(Join, Void, ) OPCODE(DemoteToHelperInvocation, Void, ) OPCODE(EmitVertex, Void, U32, ) diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 2ce49f953..0c6bf684d 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -391,4 +391,8 @@ inline f64 Value::F64() const { return imm_f64; } +[[nodiscard]] inline bool IsPhi(const Inst& inst) { + return inst.GetOpcode() == Opcode::Phi; +} + } // namespace Shader::IR diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index e7e2e9c82..836d4b8aa 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -704,7 +704,7 @@ private: // Implement if header block IR::IREmitter ir{*current_block}; const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.BranchConditionRef(cond); + ir.DummyReference(cond); const size_t if_node_index{syntax_list.size()}; syntax_list.emplace_back(); @@ -755,7 +755,7 @@ private: // The continue block is located at the end of the loop IR::IREmitter ir{*continue_block}; const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.BranchConditionRef(cond); + ir.DummyReference(cond); IR::Block* const body_block{syntax_list.at(body_block_index).block}; loop_header_block->AddBranch(body_block); @@ -792,7 +792,7 @@ private: IR::IREmitter ir{*current_block}; const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.BranchConditionRef(cond); + ir.DummyReference(cond); current_block->AddBranch(break_block); current_block->AddBranch(skip_block); current_block = skip_block; diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index 26eb3a3ab..e54499ba5 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -138,10 +138,6 @@ IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { return IR::Opcode::UndefU32; } -[[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept { - return inst.GetOpcode() == IR::Opcode::Phi; -} - enum class Status { Start, SetValue, @@ -283,7 +279,7 @@ private: list.erase(IR::Block::InstructionList::s_iterator_to(phi)); // Find the first non-phi instruction and use it as an insertion point - IR::Block::iterator reinsert_point{std::ranges::find_if_not(list, IsPhi)}; + IR::Block::iterator reinsert_point{std::ranges::find_if_not(list, IR::IsPhi)}; if (same.IsEmpty()) { // The phi is unreachable or in the start block // Insert an undefined instruction and make it the phi node replacement -- 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 ++++---- .../backend/glasm/emit_glasm_image.cpp | 2 +- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 32 +++++++-------- .../frontend/ir/abstract_syntax_list.h | 11 ++--- src/shader_recompiler/frontend/ir/post_order.cpp | 2 +- src/shader_recompiler/frontend/maxwell/program.cpp | 2 +- .../frontend/maxwell/structured_control_flow.cpp | 48 +++++++++++----------- 7 files changed, 55 insertions(+), 58 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); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 881a5dc4c..9ed2af991 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -112,48 +112,48 @@ void Traverse(EmitContext& ctx, IR::Program& program) { for (const IR::AbstractSyntaxNode& node : program.syntax_list) { switch (node.type) { case IR::AbstractSyntaxNode::Type::Block: { - const Id label{node.block->Definition()}; + const Id label{node.data.block->Definition()}; if (current_block) { ctx.OpBranch(label); } - current_block = node.block; + current_block = node.data.block; ctx.AddLabel(label); - for (IR::Inst& inst : node.block->Instructions()) { + for (IR::Inst& inst : node.data.block->Instructions()) { EmitInst(ctx, &inst); } break; } case IR::AbstractSyntaxNode::Type::If: { - const Id if_label{node.if_node.body->Definition()}; - const Id endif_label{node.if_node.merge->Definition()}; + const Id if_label{node.data.if_node.body->Definition()}; + const Id endif_label{node.data.if_node.merge->Definition()}; ctx.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone); - ctx.OpBranchConditional(ctx.Def(node.if_node.cond), if_label, endif_label); + ctx.OpBranchConditional(ctx.Def(node.data.if_node.cond), if_label, endif_label); break; } case IR::AbstractSyntaxNode::Type::Loop: { - const Id body_label{node.loop.body->Definition()}; - const Id continue_label{node.loop.continue_block->Definition()}; - const Id endloop_label{node.loop.merge->Definition()}; + const Id body_label{node.data.loop.body->Definition()}; + const Id continue_label{node.data.loop.continue_block->Definition()}; + const Id endloop_label{node.data.loop.merge->Definition()}; ctx.OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone); ctx.OpBranch(body_label); break; } case IR::AbstractSyntaxNode::Type::Break: { - const Id break_label{node.break_node.merge->Definition()}; - const Id skip_label{node.break_node.skip->Definition()}; - ctx.OpBranchConditional(ctx.Def(node.break_node.cond), break_label, skip_label); + const Id break_label{node.data.break_node.merge->Definition()}; + const Id skip_label{node.data.break_node.skip->Definition()}; + ctx.OpBranchConditional(ctx.Def(node.data.break_node.cond), break_label, skip_label); break; } case IR::AbstractSyntaxNode::Type::EndIf: if (current_block) { - ctx.OpBranch(node.end_if.merge->Definition()); + ctx.OpBranch(node.data.end_if.merge->Definition()); } break; case IR::AbstractSyntaxNode::Type::Repeat: { - const Id loop_header_label{node.repeat.loop_header->Definition()}; - const Id merge_label{node.repeat.merge->Definition()}; - ctx.OpBranchConditional(ctx.Def(node.repeat.cond), loop_header_label, merge_label); + const Id loop_header_label{node.data.repeat.loop_header->Definition()}; + const Id merge_label{node.data.repeat.merge->Definition()}; + ctx.OpBranchConditional(ctx.Def(node.data.repeat.cond), loop_header_label, merge_label); break; } case IR::AbstractSyntaxNode::Type::Return: diff --git a/src/shader_recompiler/frontend/ir/abstract_syntax_list.h b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h index e9afb4d92..b61773487 100644 --- a/src/shader_recompiler/frontend/ir/abstract_syntax_list.h +++ b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h @@ -13,10 +13,6 @@ namespace Shader::IR { class Block; struct AbstractSyntaxNode { - struct NonTrivialDummy { - NonTrivialDummy() {} - }; - enum class Type { Block, If, @@ -27,9 +23,7 @@ struct AbstractSyntaxNode { Return, Unreachable, }; - Type type{}; - union { - NonTrivialDummy dummy{}; + union Data { Block* block; struct { U1 cond; @@ -55,6 +49,9 @@ struct AbstractSyntaxNode { Block* skip; } break_node; }; + + Data data{}; + Type type{}; }; using AbstractSyntaxList = std::vector; diff --git a/src/shader_recompiler/frontend/ir/post_order.cpp b/src/shader_recompiler/frontend/ir/post_order.cpp index 1a28df7fb..16bc44101 100644 --- a/src/shader_recompiler/frontend/ir/post_order.cpp +++ b/src/shader_recompiler/frontend/ir/post_order.cpp @@ -20,7 +20,7 @@ BlockList PostOrder(const AbstractSyntaxNode& root) { if (root.type != AbstractSyntaxNode::Type::Block) { throw LogicError("First node in abstract syntax list root is not a block"); } - Block* const first_block{root.block}; + Block* const first_block{root.data.block}; visited.insert(first_block); block_stack.push_back(first_block); diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp index 017c4b8fd..ccdab1dad 100644 --- a/src/shader_recompiler/frontend/maxwell/program.cpp +++ b/src/shader_recompiler/frontend/maxwell/program.cpp @@ -22,7 +22,7 @@ IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { })}; IR::BlockList blocks(std::ranges::distance(syntax_blocks)); std::ranges::transform(syntax_blocks, blocks.begin(), - [](const IR::AbstractSyntaxNode& node) { return node.block; }); + [](const IR::AbstractSyntaxNode& node) { return node.data.block; }); return blocks; } diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 836d4b8aa..83554a953 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -655,8 +655,8 @@ public: syntax_list{syntax_list_} { Visit(root_stmt, nullptr, nullptr); - IR::Block& first_block{*syntax_list.front().block}; - IR::IREmitter ir{first_block, first_block.begin()}; + IR::Block& first_block{*syntax_list.front().data.block}; + IR::IREmitter ir = IR::IREmitter(first_block, first_block.begin()); ir.Prologue(); } @@ -670,7 +670,7 @@ private: current_block = block_pool.Create(inst_pool); auto& node{syntax_list.emplace_back()}; node.type = IR::AbstractSyntaxNode::Type::Block; - node.block = current_block; + node.data.block = current_block; }}; Tree& tree{parent.children}; for (auto it = tree.begin(); it != tree.end(); ++it) { @@ -713,24 +713,24 @@ private: const size_t then_block_index{syntax_list.size()}; Visit(stmt, break_block, merge_block); - IR::Block* const then_block{syntax_list.at(then_block_index).block}; + IR::Block* const then_block{syntax_list.at(then_block_index).data.block}; current_block->AddBranch(then_block); current_block->AddBranch(merge_block); current_block = merge_block; auto& if_node{syntax_list[if_node_index]}; if_node.type = IR::AbstractSyntaxNode::Type::If; - if_node.if_node.cond = cond; - if_node.if_node.body = then_block; - if_node.if_node.merge = merge_block; + if_node.data.if_node.cond = cond; + if_node.data.if_node.body = then_block; + if_node.data.if_node.merge = merge_block; auto& endif_node{syntax_list.emplace_back()}; endif_node.type = IR::AbstractSyntaxNode::Type::EndIf; - endif_node.end_if.merge = merge_block; + endif_node.data.end_if.merge = merge_block; auto& merge{syntax_list.emplace_back()}; merge.type = IR::AbstractSyntaxNode::Type::Block; - merge.block = merge_block; + merge.data.block = merge_block; break; } case StatementType::Loop: { @@ -740,7 +740,7 @@ private: } auto& header_node{syntax_list.emplace_back()}; header_node.type = IR::AbstractSyntaxNode::Type::Block; - header_node.block = loop_header_block; + header_node.data.block = loop_header_block; IR::Block* const continue_block{block_pool.Create(inst_pool)}; IR::Block* const merge_block{MergeBlock(parent, stmt)}; @@ -757,7 +757,7 @@ private: const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; ir.DummyReference(cond); - IR::Block* const body_block{syntax_list.at(body_block_index).block}; + IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; loop_header_block->AddBranch(body_block); continue_block->AddBranch(loop_header_block); @@ -767,23 +767,23 @@ private: auto& loop{syntax_list[loop_node_index]}; loop.type = IR::AbstractSyntaxNode::Type::Loop; - loop.loop.body = body_block; - loop.loop.continue_block = continue_block; - loop.loop.merge = merge_block; + loop.data.loop.body = body_block; + loop.data.loop.continue_block = continue_block; + loop.data.loop.merge = merge_block; auto& continue_block_node{syntax_list.emplace_back()}; continue_block_node.type = IR::AbstractSyntaxNode::Type::Block; - continue_block_node.block = continue_block; + continue_block_node.data.block = continue_block; auto& repeat{syntax_list.emplace_back()}; repeat.type = IR::AbstractSyntaxNode::Type::Repeat; - repeat.repeat.cond = cond; - repeat.repeat.loop_header = loop_header_block; - repeat.repeat.merge = merge_block; + repeat.data.repeat.cond = cond; + repeat.data.repeat.loop_header = loop_header_block; + repeat.data.repeat.merge = merge_block; auto& merge{syntax_list.emplace_back()}; merge.type = IR::AbstractSyntaxNode::Type::Block; - merge.block = merge_block; + merge.data.block = merge_block; break; } case StatementType::Break: { @@ -799,13 +799,13 @@ private: auto& break_node{syntax_list.emplace_back()}; break_node.type = IR::AbstractSyntaxNode::Type::Break; - break_node.break_node.cond = cond; - break_node.break_node.merge = break_block; - break_node.break_node.skip = skip_block; + break_node.data.break_node.cond = cond; + break_node.data.break_node.merge = break_block; + break_node.data.break_node.skip = skip_block; auto& merge{syntax_list.emplace_back()}; merge.type = IR::AbstractSyntaxNode::Type::Block; - merge.block = skip_block; + merge.data.block = skip_block; break; } case StatementType::Return: { @@ -824,7 +824,7 @@ private: auto& merge{syntax_list.emplace_back()}; merge.type = IR::AbstractSyntaxNode::Type::Block; - merge.block = demote_block; + merge.data.block = demote_block; break; } case StatementType::Unreachable: { -- 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 +- .../backend/spirv/emit_spirv_image.cpp | 8 +- .../backend/spirv/emit_spirv_instructions.h | 4 +- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 11 +- src/shader_recompiler/frontend/ir/ir_emitter.h | 5 +- .../maxwell/translate/impl/texture_fetch.cpp | 5 +- .../translate/impl/texture_fetch_swizzled.cpp | 18 +- 10 files changed, 275 insertions(+), 69 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 diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 5832104df..99b883746 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -337,9 +337,9 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& } Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id lod_lc, const IR::Value& offset) { + Id lod, const IR::Value& offset) { const auto info{inst->Flags()}; - const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); + const ImageOperands operands(ctx, false, true, false, lod, offset); return Emit(&EmitContext::OpImageSparseSampleExplicitLod, &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); @@ -356,9 +356,9 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va } Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, - Id coords, Id dref, Id lod_lc, const IR::Value& offset) { + Id coords, Id dref, Id lod, const IR::Value& offset) { const auto info{inst->Flags()}; - const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); + const ImageOperands operands(ctx, false, true, false, lod, offset); return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1], Texture(ctx, info, index), coords, dref, operands.Mask(), operands.Span()); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 0a2b31772..22260d2a9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -491,11 +491,11 @@ Id EmitBoundImageWrite(EmitContext&); Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id bias_lc, const IR::Value& offset); Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id lod_lc, const IR::Value& offset); + Id lod, const IR::Value& offset); Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id dref, Id bias_lc, const IR::Value& offset); Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, - Id coords, Id dref, Id lod_lc, const IR::Value& offset); + Id coords, Id dref, Id lod, const IR::Value& offset); Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, const IR::Value& offset, const IR::Value& offset2); Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index def29143e..94bdbe39c 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -1778,12 +1778,10 @@ Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& coords } Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod, - const Value& offset, const F32& lod_clamp, - TextureInstInfo info) { - const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)}; + const Value& offset, TextureInstInfo info) { const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleExplicitLod : Opcode::BindlessImageSampleExplicitLod}; - return Inst(op, Flags{info}, handle, coords, lod_lc, offset); + return Inst(op, Flags{info}, handle, coords, lod, offset); } F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, const F32& dref, @@ -1796,12 +1794,11 @@ F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coor } F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, const F32& dref, - const F32& lod, const Value& offset, const F32& lod_clamp, + const F32& lod, const Value& offset, TextureInstInfo info) { - const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)}; const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleDrefExplicitLod : Opcode::BindlessImageSampleDrefExplicitLod}; - return Inst(op, Flags{info}, handle, coords, dref, lod_lc, offset); + return Inst(op, Flags{info}, handle, coords, dref, lod, offset); } Value IREmitter::ImageGather(const Value& handle, const Value& coords, const Value& offset, diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 4f7c820fe..4ae69b788 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -302,15 +302,14 @@ public: const F32& lod_clamp, TextureInstInfo info); [[nodiscard]] Value ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod, const Value& offset, - const F32& lod_clamp, TextureInstInfo info); + TextureInstInfo info); [[nodiscard]] F32 ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, const F32& dref, const F32& bias, const Value& offset, const F32& lod_clamp, TextureInstInfo info); [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, const F32& dref, const F32& lod, - const Value& offset, const F32& lod_clamp, - TextureInstInfo info); + const Value& offset, TextureInstInfo info); [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod); [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp index 9671d115e..0046b5edd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp @@ -177,14 +177,13 @@ void Impl(TranslatorVisitor& v, u64 insn, bool aoffi, Blod blod, bool lc, const IR::Value sample{[&]() -> IR::Value { if (tex.dc == 0) { if (HasExplicitLod(blod)) { - return v.ir.ImageSampleExplicitLod(handle, coords, lod, offset, lod_clamp, info); + return v.ir.ImageSampleExplicitLod(handle, coords, lod, offset, info); } else { return v.ir.ImageSampleImplicitLod(handle, coords, lod, offset, lod_clamp, info); } } if (HasExplicitLod(blod)) { - return v.ir.ImageSampleDrefExplicitLod(handle, coords, dref, lod, offset, lod_clamp, - info); + return v.ir.ImageSampleDrefExplicitLod(handle, coords, dref, lod, offset, info); } else { return v.ir.ImageSampleDrefImplicitLod(handle, coords, dref, lod, offset, lod_clamp, info); diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp index 3500a4559..154e7f1a1 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp @@ -81,18 +81,18 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { switch (texs.encoding) { case 0: // 1D.LZ info.type.Assign(TextureType::Color1D); - return v.ir.ImageSampleExplicitLod(handle, v.F(reg_a), zero, {}, {}, info); + return v.ir.ImageSampleExplicitLod(handle, v.F(reg_a), zero, {}, info); case 1: // 2D info.type.Assign(TextureType::Color2D); return v.ir.ImageSampleImplicitLod(handle, Composite(v, reg_a, reg_b), {}, {}, {}, info); case 2: // 2D.LZ info.type.Assign(TextureType::Color2D); - return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_b), zero, {}, {}, info); + return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_b), zero, {}, info); case 3: // 2D.LL CheckAlignment(reg_a, 2); info.type.Assign(TextureType::Color2D); return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), {}, - {}, info); + info); case 4: // 2D.DC CheckAlignment(reg_a, 2); info.type.Assign(TextureType::Color2D); @@ -105,13 +105,13 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { info.type.Assign(TextureType::Color2D); info.is_depth.Assign(1); return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), - v.F(reg_b + 1), v.F(reg_b), {}, {}, info); + v.F(reg_b + 1), v.F(reg_b), {}, info); case 6: // 2D.LZ.DC CheckAlignment(reg_a, 2); info.type.Assign(TextureType::Color2D); info.is_depth.Assign(1); return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), - zero, {}, {}, info); + zero, {}, info); case 7: // ARRAY_2D CheckAlignment(reg_a, 2); info.type.Assign(TextureType::ColorArray2D); @@ -123,7 +123,7 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { info.type.Assign(TextureType::ColorArray2D); return v.ir.ImageSampleExplicitLod( handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))), - zero, {}, {}, info); + zero, {}, info); case 9: // ARRAY_2D.LZ.DC CheckAlignment(reg_a, 2); CheckAlignment(reg_b, 2); @@ -131,7 +131,7 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { info.is_depth.Assign(1); return v.ir.ImageSampleDrefExplicitLod( handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))), - v.F(reg_b + 1), zero, {}, {}, info); + v.F(reg_b + 1), zero, {}, info); case 10: // 3D CheckAlignment(reg_a, 2); info.type.Assign(TextureType::Color3D); @@ -141,7 +141,7 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { CheckAlignment(reg_a, 2); info.type.Assign(TextureType::Color3D); return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b), zero, {}, - {}, info); + info); case 12: // CUBE CheckAlignment(reg_a, 2); info.type.Assign(TextureType::ColorCube); @@ -152,7 +152,7 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { CheckAlignment(reg_b, 2); info.type.Assign(TextureType::ColorCube); return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b), - v.F(reg_b + 1), {}, {}, info); + v.F(reg_b + 1), {}, info); default: throw NotImplementedException("Illegal encoding {}", texs.encoding.Value()); } -- 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 +- .../backend/glasm/emit_glasm_bitwise_conversion.cpp | 4 ++++ src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 3 ++- .../backend/glasm/emit_glasm_not_implemented.cpp | 2 +- src/shader_recompiler/backend/glasm/reg_alloc.cpp | 1 + src/shader_recompiler/backend/spirv/emit_spirv.cpp | 10 +++++++++- src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | 3 ++- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 8 ++++++-- src/shader_recompiler/frontend/ir/ir_emitter.h | 4 +++- src/shader_recompiler/frontend/ir/microinstruction.cpp | 3 ++- src/shader_recompiler/frontend/ir/opcodes.inc | 3 ++- .../frontend/maxwell/structured_control_flow.cpp | 9 +++------ 12 files changed, 36 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 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: diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 9ed2af991..3e20ac3b9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -469,7 +469,15 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { return id; } -void EmitDummyReference(EmitContext&) {} +Id EmitConditionRef(EmitContext& ctx, const IR::Value& value) { + const Id id{ctx.Def(value)}; + if (!Sirit::ValidId(id)) { + throw NotImplementedException("Forward identity declaration"); + } + return id; +} + +void EmitReference(EmitContext&) {} void EmitPhiMove(EmitContext&) { throw LogicError("Unreachable instruction"); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 22260d2a9..1181e7b4f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -23,7 +23,8 @@ class EmitContext; Id EmitPhi(EmitContext& ctx, IR::Inst* inst); void EmitVoid(EmitContext& ctx); Id EmitIdentity(EmitContext& ctx, const IR::Value& value); -void EmitDummyReference(EmitContext&); +Id EmitConditionRef(EmitContext& ctx, const IR::Value& value); +void EmitReference(EmitContext&); void EmitPhiMove(EmitContext&); void EmitJoin(EmitContext& ctx); void EmitDemoteToHelperInvocation(EmitContext& ctx); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 94bdbe39c..e9fd41237 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -61,8 +61,12 @@ F64 IREmitter::Imm64(f64 value) const { return F64{Value{value}}; } -void IREmitter::DummyReference(const Value& value) { - Inst(Opcode::DummyReference, value); +U1 IREmitter::ConditionRef(const U1& value) { + return Inst(Opcode::ConditionRef, value); +} + +void IREmitter::Reference(const Value& value) { + Inst(Opcode::Reference, value); } void IREmitter::PhiMove(IR::Inst& phi, const Value& value) { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 4ae69b788..bb3500c54 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -32,7 +32,9 @@ public: [[nodiscard]] U64 Imm64(s64 value) const; [[nodiscard]] F64 Imm64(f64 value) const; - void DummyReference(const Value& value); + U1 ConditionRef(const U1& value); + void Reference(const Value& value); + void PhiMove(IR::Inst& phi, const Value& value); void Prologue(); diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 267aebc61..3dfa5a880 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -56,7 +56,8 @@ Inst::~Inst() { bool Inst::MayHaveSideEffects() const noexcept { switch (op) { - case Opcode::DummyReference: + case Opcode::ConditionRef: + case Opcode::Reference: case Opcode::PhiMove: case Opcode::Prologue: case Opcode::Epilogue: diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 6196b867d..8a8d0d759 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -6,7 +6,8 @@ OPCODE(Phi, Opaque, ) OPCODE(Identity, Opaque, Opaque, ) OPCODE(Void, Void, ) -OPCODE(DummyReference, Void, Opaque, ) +OPCODE(ConditionRef, U1, U1, ) +OPCODE(Reference, Void, Opaque, ) OPCODE(PhiMove, Void, Opaque, Opaque, ) // Special operations diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 83554a953..ebe5c2654 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -703,8 +703,7 @@ private: // Implement if header block IR::IREmitter ir{*current_block}; - const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.DummyReference(cond); + const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; const size_t if_node_index{syntax_list.size()}; syntax_list.emplace_back(); @@ -754,8 +753,7 @@ private: // The continue block is located at the end of the loop IR::IREmitter ir{*continue_block}; - const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.DummyReference(cond); + const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; loop_header_block->AddBranch(body_block); @@ -791,8 +789,7 @@ private: IR::Block* const skip_block{MergeBlock(parent, stmt)}; IR::IREmitter ir{*current_block}; - const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - ir.DummyReference(cond); + const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; current_block->AddBranch(break_block); current_block->AddBranch(skip_block); current_block = skip_block; -- 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 ++-- src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 +- 4 files changed, 25 insertions(+), 5 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)}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index c10ea2f60..b84b36b9d 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -302,7 +302,7 @@ std::unique_ptr ShaderCache::CreateGraphicsProgram( const size_t stage_index{index - 1}; infos[stage_index] = &program.info; if (device.UseAssemblyShaders()) { - const std::string code{EmitGLASM(profile, program)}; + const std::string code{EmitGLASM(profile, program, binding)}; assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index)); } else { const std::vector code{EmitSPIRV(profile, program, binding)}; -- 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 +- .../backend/spirv/emit_context.cpp | 26 +- src/shader_recompiler/backend/spirv/emit_context.h | 4 +- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 20 +- src/shader_recompiler/backend/spirv/emit_spirv.h | 6 +- .../backend/spirv/emit_spirv_context_get_set.cpp | 4 +- .../backend/spirv/emit_spirv_special.cpp | 15 +- src/shader_recompiler/profile.h | 13 +- src/video_core/renderer_opengl/gl_shader_cache.cpp | 26 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 418 ++++++++++----------- src/video_core/renderer_vulkan/vk_pipeline_cache.h | 5 +- 14 files changed, 300 insertions(+), 308 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 diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index a98e08392..3e8899f53 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -136,7 +136,7 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, break; case Stage::Geometry: if (per_invocation) { - const u32 num_vertices{NumVertices(ctx.profile.input_topology)}; + const u32 num_vertices{NumVertices(ctx.runtime_info.input_topology)}; type = ctx.TypeArray(type, ctx.Const(num_vertices)); } break; @@ -161,8 +161,8 @@ void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional invo while (element < 4) { const u32 remainder{4 - element}; const TransformFeedbackVarying* xfb_varying{}; - if (!ctx.profile.xfb_varyings.empty()) { - xfb_varying = &ctx.profile.xfb_varyings[base_attr_index + element]; + if (!ctx.runtime_info.xfb_varyings.empty()) { + xfb_varying = &ctx.runtime_info.xfb_varyings[base_attr_index + element]; xfb_varying = xfb_varying && xfb_varying->components > 0 ? xfb_varying : nullptr; } const u32 num_components{xfb_varying ? xfb_varying->components : remainder}; @@ -208,7 +208,7 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { } std::optional AttrTypes(EmitContext& ctx, u32 index) { - const AttributeType type{ctx.profile.generic_input_types.at(index)}; + const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; switch (type) { case AttributeType::Float: return AttrInfo{ctx.input_f32, ctx.F32[1], false}; @@ -441,13 +441,15 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie } } -EmitContext::EmitContext(const Profile& profile_, IR::Program& program, Bindings& binding) - : Sirit::Module(profile_.supported_spirv), profile{profile_}, stage{program.stage} { +EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_info_, + IR::Program& program, Bindings& bindings) + : Sirit::Module(profile_.supported_spirv), profile{profile_}, + runtime_info{runtime_info_}, stage{program.stage} { const bool is_unified{profile.unified_descriptor_binding}; - u32& uniform_binding{is_unified ? binding.unified : binding.uniform_buffer}; - u32& storage_binding{is_unified ? binding.unified : binding.storage_buffer}; - u32& texture_binding{is_unified ? binding.unified : binding.texture}; - u32& image_binding{is_unified ? binding.unified : binding.image}; + u32& uniform_binding{is_unified ? bindings.unified : bindings.uniform_buffer}; + u32& storage_binding{is_unified ? bindings.unified : bindings.storage_buffer}; + u32& texture_binding{is_unified ? bindings.unified : bindings.texture}; + u32& image_binding{is_unified ? bindings.unified : bindings.image}; AddCapability(spv::Capability::Shader); DefineCommonTypes(program.info); DefineCommonConstants(); @@ -1211,7 +1213,7 @@ void EmitContext::DefineInputs(const Info& info) { if (!generic.used) { continue; } - const AttributeType input_type{profile.generic_input_types[index]}; + const AttributeType input_type{runtime_info.generic_input_types[index]}; if (input_type == AttributeType::Disabled) { continue; } @@ -1256,7 +1258,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (info.stores_position || stage == Stage::VertexB) { output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); } - if (info.stores_point_size || profile.fixed_state_point_size) { + if (info.stores_point_size || runtime_info.fixed_state_point_size) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing PointSize in fragment stage"); } diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index d2b79f6c1..961c9180c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -103,7 +103,8 @@ struct GenericElementInfo { class EmitContext final : public Sirit::Module { public: - explicit EmitContext(const Profile& profile, IR::Program& program, Bindings& binding); + explicit EmitContext(const Profile& profile, const RuntimeInfo& runtime_info, + IR::Program& program, Bindings& binding); ~EmitContext(); [[nodiscard]] Id Def(const IR::Value& value); @@ -150,6 +151,7 @@ public: } const Profile& profile; + const RuntimeInfo& runtime_info; Stage stage{}; Id void_id{}; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 3e20ac3b9..cba420cda 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -226,16 +226,17 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { case Stage::TessellationEval: execution_model = spv::ExecutionModel::TessellationEvaluation; ctx.AddCapability(spv::Capability::Tessellation); - ctx.AddExecutionMode(main, ExecutionMode(ctx.profile.tess_primitive)); - ctx.AddExecutionMode(main, ExecutionMode(ctx.profile.tess_spacing)); - ctx.AddExecutionMode(main, ctx.profile.tess_clockwise ? spv::ExecutionMode::VertexOrderCw - : spv::ExecutionMode::VertexOrderCcw); + ctx.AddExecutionMode(main, ExecutionMode(ctx.runtime_info.tess_primitive)); + ctx.AddExecutionMode(main, ExecutionMode(ctx.runtime_info.tess_spacing)); + ctx.AddExecutionMode(main, ctx.runtime_info.tess_clockwise + ? spv::ExecutionMode::VertexOrderCw + : spv::ExecutionMode::VertexOrderCcw); break; case Stage::Geometry: execution_model = spv::ExecutionModel::Geometry; ctx.AddCapability(spv::Capability::Geometry); ctx.AddCapability(spv::Capability::GeometryStreams); - switch (ctx.profile.input_topology) { + switch (ctx.runtime_info.input_topology) { case InputTopology::Points: ctx.AddExecutionMode(main, spv::ExecutionMode::InputPoints); break; @@ -279,7 +280,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { if (program.info.stores_frag_depth) { ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); } - if (ctx.profile.force_early_z) { + if (ctx.runtime_info.force_early_z) { ctx.AddExecutionMode(main, spv::ExecutionMode::EarlyFragmentTests); } break; @@ -402,7 +403,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct if (info.uses_sample_id) { ctx.AddCapability(spv::Capability::SampleRateShading); } - if (!ctx.profile.xfb_varyings.empty()) { + if (!ctx.runtime_info.xfb_varyings.empty()) { ctx.AddCapability(spv::Capability::TransformFeedback); } if (info.uses_derivatives) { @@ -433,8 +434,9 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { } } // Anonymous namespace -std::vector EmitSPIRV(const Profile& profile, IR::Program& program, Bindings& binding) { - EmitContext ctx{profile, program, binding}; +std::vector EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, + IR::Program& program, Bindings& bindings) { + EmitContext ctx{profile, runtime_info, program, bindings}; const Id main{DefineMain(ctx, program)}; DefineEntryPoint(program, ctx, main); if (profile.support_float_controls) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index d8ab2d8ed..db0c935fe 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h @@ -16,12 +16,12 @@ namespace Shader::Backend::SPIRV { -[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, IR::Program& program, - Bindings& binding); +[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, + IR::Program& program, Bindings& bindings); [[nodiscard]] inline std::vector EmitSPIRV(const Profile& profile, IR::Program& program) { Bindings binding; - return EmitSPIRV(profile, program, binding); + return EmitSPIRV(profile, {}, program, binding); } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 8e57ff070..c1b69c234 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -17,7 +17,7 @@ struct AttrInfo { }; std::optional AttrTypes(EmitContext& ctx, u32 index) { - const AttributeType type{ctx.profile.generic_input_types.at(index)}; + const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; switch (type) { case AttributeType::Float: return AttrInfo{ctx.input_f32, ctx.F32[1], false}; @@ -468,7 +468,7 @@ Id EmitIsHelperInvocation(EmitContext& ctx) { } Id EmitYDirection(EmitContext& ctx) { - return ctx.Const(ctx.profile.y_negate ? -1.0f : 1.0f); + return ctx.Const(ctx.runtime_info.y_negate ? -1.0f : 1.0f); } Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index ba948f3c9..072a3b1bd 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -18,8 +18,8 @@ void ConvertDepthMode(EmitContext& ctx) { } void SetFixedPipelinePointSize(EmitContext& ctx) { - if (ctx.profile.fixed_state_point_size) { - const float point_size{*ctx.profile.fixed_state_point_size}; + if (ctx.runtime_info.fixed_state_point_size) { + const float point_size{*ctx.runtime_info.fixed_state_point_size}; ctx.OpStore(ctx.output_point_size, ctx.Const(point_size)); } } @@ -62,7 +62,10 @@ Id ComparisonFunction(EmitContext& ctx, CompareFunction comparison, Id operand_1 } void AlphaTest(EmitContext& ctx) { - const auto comparison{*ctx.profile.alpha_test_func}; + if (!ctx.runtime_info.alpha_test_func) { + return; + } + const auto comparison{*ctx.runtime_info.alpha_test_func}; if (comparison == CompareFunction::Always) { return; } @@ -76,7 +79,7 @@ void AlphaTest(EmitContext& ctx) { const Id true_label{ctx.OpLabel()}; const Id discard_label{ctx.OpLabel()}; - const Id alpha_reference{ctx.Const(ctx.profile.alpha_test_reference)}; + const Id alpha_reference{ctx.Const(ctx.runtime_info.alpha_test_reference)}; const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; ctx.OpSelectionMerge(true_label, spv::SelectionControlMask::MaskNone); @@ -113,7 +116,7 @@ void EmitPrologue(EmitContext& ctx) { } void EmitEpilogue(EmitContext& ctx) { - if (ctx.stage == Stage::VertexB && ctx.profile.convert_depth_mode) { + if (ctx.stage == Stage::VertexB && ctx.runtime_info.convert_depth_mode) { ConvertDepthMode(ctx); } if (ctx.stage == Stage::Fragment) { @@ -122,7 +125,7 @@ void EmitEpilogue(EmitContext& ctx) { } void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { - if (ctx.profile.convert_depth_mode) { + if (ctx.runtime_info.convert_depth_mode) { ConvertDepthMode(ctx); } if (stream.IsImmediate()) { diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 12699511a..c46452c3d 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -81,19 +81,22 @@ struct Profile { bool support_viewport_mask{}; bool support_typeless_image_loads{}; bool support_demote_to_helper_invocation{}; - bool warp_size_potentially_larger_than_guest{}; bool support_int64_atomics{}; + + bool warp_size_potentially_larger_than_guest{}; bool lower_left_origin_mode{}; - // FClamp is broken and OpFMax + OpFMin should be used instead + /// OpFClamp is broken and OpFMax + OpFMin should be used instead bool has_broken_spirv_clamp{}; - // Offset image operands with an unsigned type do not work + /// Offset image operands with an unsigned type do not work bool has_broken_unsigned_image_offsets{}; - // Signed instructions with unsigned data types are misinterpreted + /// Signed instructions with unsigned data types are misinterpreted bool has_broken_signed_operations{}; - // Ignores SPIR-V ordered vs unordered using GLSL semantics + /// Ignores SPIR-V ordered vs unordered using GLSL semantics bool ignore_nan_fp_comparisons{}; +}; +struct RuntimeInfo { std::array generic_input_types{}; bool convert_depth_mode{}; bool force_early_z{}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index b84b36b9d..d7efbdd01 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -61,33 +61,15 @@ const Shader::Profile profile{ .support_viewport_mask = true, .support_typeless_image_loads = true, .support_demote_to_helper_invocation = false, - .warp_size_potentially_larger_than_guest = true, .support_int64_atomics = false, + + .warp_size_potentially_larger_than_guest = true, .lower_left_origin_mode = true, .has_broken_spirv_clamp = true, .has_broken_unsigned_image_offsets = true, .has_broken_signed_operations = true, .ignore_nan_fp_comparisons = true, - - .generic_input_types = {}, - .convert_depth_mode = false, - .force_early_z = false, - - .tess_primitive = {}, - .tess_spacing = {}, - .tess_clockwise = false, - - .input_topology = Shader::InputTopology::Triangles, - - .fixed_state_point_size = std::nullopt, - - .alpha_test_func = Shader::CompareFunction::Always, - .alpha_test_reference = 0.0f, - - .y_negate = false, - - .xfb_varyings = {}, }; using Shader::Backend::GLASM::EmitGLASM; @@ -302,10 +284,10 @@ std::unique_ptr ShaderCache::CreateGraphicsProgram( const size_t stage_index{index - 1}; infos[stage_index] = &program.info; if (device.UseAssemblyShaders()) { - const std::string code{EmitGLASM(profile, program, binding)}; + const std::string code{EmitGLASM(profile, {}, program, binding)}; assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index)); } else { - const std::vector code{EmitSPIRV(profile, program, binding)}; + const std::vector code{EmitSPIRV(profile, {}, program, binding)}; AddShader(Stage(stage_index), source_program.handle, code); } } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 7830c0194..88db10b75 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -89,6 +89,208 @@ Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp compariso UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison); return {}; } + +static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) { + if (attr.enabled == 0) { + return Shader::AttributeType::Disabled; + } + switch (attr.Type()) { + case Maxwell::VertexAttribute::Type::SignedNorm: + case Maxwell::VertexAttribute::Type::UnsignedNorm: + case Maxwell::VertexAttribute::Type::UnsignedScaled: + case Maxwell::VertexAttribute::Type::SignedScaled: + case Maxwell::VertexAttribute::Type::Float: + return Shader::AttributeType::Float; + case Maxwell::VertexAttribute::Type::SignedInt: + return Shader::AttributeType::SignedInt; + case Maxwell::VertexAttribute::Type::UnsignedInt: + return Shader::AttributeType::UnsignedInt; + } + return Shader::AttributeType::Float; +} + +std::vector MakeTransformFeedbackVaryings( + const GraphicsPipelineCacheKey& key) { + static constexpr std::array VECTORS{ + 28, // gl_Position + 32, // Generic 0 + 36, // Generic 1 + 40, // Generic 2 + 44, // Generic 3 + 48, // Generic 4 + 52, // Generic 5 + 56, // Generic 6 + 60, // Generic 7 + 64, // Generic 8 + 68, // Generic 9 + 72, // Generic 10 + 76, // Generic 11 + 80, // Generic 12 + 84, // Generic 13 + 88, // Generic 14 + 92, // Generic 15 + 96, // Generic 16 + 100, // Generic 17 + 104, // Generic 18 + 108, // Generic 19 + 112, // Generic 20 + 116, // Generic 21 + 120, // Generic 22 + 124, // Generic 23 + 128, // Generic 24 + 132, // Generic 25 + 136, // Generic 26 + 140, // Generic 27 + 144, // Generic 28 + 148, // Generic 29 + 152, // Generic 30 + 156, // Generic 31 + 160, // gl_FrontColor + 164, // gl_FrontSecondaryColor + 160, // gl_BackColor + 164, // gl_BackSecondaryColor + 192, // gl_TexCoord[0] + 196, // gl_TexCoord[1] + 200, // gl_TexCoord[2] + 204, // gl_TexCoord[3] + 208, // gl_TexCoord[4] + 212, // gl_TexCoord[5] + 216, // gl_TexCoord[6] + 220, // gl_TexCoord[7] + }; + std::vector xfb(256); + for (size_t buffer = 0; buffer < Maxwell::NumTransformFeedbackBuffers; ++buffer) { + const auto& locations = key.state.xfb_state.varyings[buffer]; + const auto& layout = key.state.xfb_state.layouts[buffer]; + const u32 varying_count = layout.varying_count; + u32 highest = 0; + for (u32 offset = 0; offset < varying_count; ++offset) { + const u32 base_offset = offset; + const u8 location = locations[offset]; + + Shader::TransformFeedbackVarying varying; + varying.buffer = layout.stream; + varying.stride = layout.stride; + varying.offset = offset * 4; + varying.components = 1; + + if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) { + UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB"); + + const u8 base_index = location / 4; + while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) { + ++offset; + ++varying.components; + } + } + xfb[location] = varying; + highest = std::max(highest, (base_offset + varying.components) * 4); + } + UNIMPLEMENTED_IF(highest != layout.stride); + } + return xfb; +} + +Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key, + const Shader::IR::Program& program) { + Shader::RuntimeInfo info; + + const Shader::Stage stage{program.stage}; + const bool has_geometry{key.unique_hashes[4] != 0}; + const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; + const float point_size{Common::BitCast(key.state.point_size)}; + switch (stage) { + case Shader::Stage::VertexB: + if (!has_geometry) { + if (key.state.topology == Maxwell::PrimitiveTopology::Points) { + info.fixed_state_point_size = point_size; + } + if (key.state.xfb_enabled != 0) { + info.xfb_varyings = MakeTransformFeedbackVaryings(key); + } + info.convert_depth_mode = gl_ndc; + } + std::ranges::transform(key.state.attributes, info.generic_input_types.begin(), + &CastAttributeType); + break; + case Shader::Stage::TessellationEval: + // We have to flip tessellation clockwise for some reason... + info.tess_clockwise = key.state.tessellation_clockwise == 0; + info.tess_primitive = [&key] { + const u32 raw{key.state.tessellation_primitive.Value()}; + switch (static_cast(raw)) { + case Maxwell::TessellationPrimitive::Isolines: + return Shader::TessPrimitive::Isolines; + case Maxwell::TessellationPrimitive::Triangles: + return Shader::TessPrimitive::Triangles; + case Maxwell::TessellationPrimitive::Quads: + return Shader::TessPrimitive::Quads; + } + UNREACHABLE(); + return Shader::TessPrimitive::Triangles; + }(); + info.tess_spacing = [&] { + const u32 raw{key.state.tessellation_spacing}; + switch (static_cast(raw)) { + case Maxwell::TessellationSpacing::Equal: + return Shader::TessSpacing::Equal; + case Maxwell::TessellationSpacing::FractionalOdd: + return Shader::TessSpacing::FractionalOdd; + case Maxwell::TessellationSpacing::FractionalEven: + return Shader::TessSpacing::FractionalEven; + } + UNREACHABLE(); + return Shader::TessSpacing::Equal; + }(); + break; + case Shader::Stage::Geometry: + if (program.output_topology == Shader::OutputTopology::PointList) { + info.fixed_state_point_size = point_size; + } + if (key.state.xfb_enabled != 0) { + info.xfb_varyings = MakeTransformFeedbackVaryings(key); + } + info.convert_depth_mode = gl_ndc; + break; + case Shader::Stage::Fragment: + info.alpha_test_func = MaxwellToCompareFunction( + key.state.UnpackComparisonOp(key.state.alpha_test_func.Value())); + info.alpha_test_reference = Common::BitCast(key.state.alpha_test_ref); + break; + default: + break; + } + switch (key.state.topology) { + case Maxwell::PrimitiveTopology::Points: + info.input_topology = Shader::InputTopology::Points; + break; + case Maxwell::PrimitiveTopology::Lines: + case Maxwell::PrimitiveTopology::LineLoop: + case Maxwell::PrimitiveTopology::LineStrip: + info.input_topology = Shader::InputTopology::Lines; + break; + case Maxwell::PrimitiveTopology::Triangles: + case Maxwell::PrimitiveTopology::TriangleStrip: + case Maxwell::PrimitiveTopology::TriangleFan: + case Maxwell::PrimitiveTopology::Quads: + case Maxwell::PrimitiveTopology::QuadStrip: + case Maxwell::PrimitiveTopology::Polygon: + case Maxwell::PrimitiveTopology::Patches: + info.input_topology = Shader::InputTopology::Triangles; + break; + case Maxwell::PrimitiveTopology::LinesAdjacency: + case Maxwell::PrimitiveTopology::LineStripAdjacency: + info.input_topology = Shader::InputTopology::LinesAdjacency; + break; + case Maxwell::PrimitiveTopology::TrianglesAdjacency: + case Maxwell::PrimitiveTopology::TriangleStripAdjacency: + info.input_topology = Shader::InputTopology::TrianglesAdjacency; + break; + } + info.force_early_z = key.state.early_z != 0; + info.y_negate = key.state.y_negate != 0; + return info; +} } // Anonymous namespace size_t ComputePipelineCacheKey::Hash() const noexcept { @@ -124,7 +326,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw serialization_thread(1, "yuzu:PipelineSerialization") { const auto& float_control{device.FloatControlProperties()}; const VkDriverIdKHR driver_id{device.GetDriverID()}; - base_profile = Shader::Profile{ + profile = Shader::Profile{ .supported_spirv = device.IsKhrSpirv1_4Supported() ? 0x00010400U : 0x00010000U, .unified_descriptor_binding = true, .support_descriptor_aliasing = true, @@ -153,14 +355,10 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw .support_viewport_mask = device.IsNvViewportArray2Supported(), .support_typeless_image_loads = device.IsFormatlessImageLoadSupported(), .support_demote_to_helper_invocation = true, - .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), + .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, .has_broken_unsigned_image_offsets = false, - .generic_input_types{}, - .fixed_state_point_size{}, - .alpha_test_func{}, - .xfb_varyings{}, }; } @@ -329,8 +527,8 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( const size_t stage_index{index - 1}; infos[stage_index] = &program.info; - const Shader::Profile profile{MakeProfile(key, program)}; - const std::vector code{EmitSPIRV(profile, program, binding)}; + const Shader::RuntimeInfo runtime_info{MakeRuntimeInfo(key, program)}; + const std::vector code{EmitSPIRV(profile, runtime_info, program, binding)}; device.SaveShader(code); modules[stage_index] = BuildShader(device, code); if (device.HasDebuggingToolAttached()) { @@ -391,7 +589,7 @@ std::unique_ptr PipelineCache::CreateComputePipeline( Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; Shader::IR::Program program{TranslateProgram(pools.inst, pools.block, env, cfg)}; - const std::vector code{EmitSPIRV(base_profile, program)}; + const std::vector code{EmitSPIRV(profile, program)}; device.SaveShader(code); vk::ShaderModule spv_module{BuildShader(device, code)}; if (device.HasDebuggingToolAttached()) { @@ -403,206 +601,4 @@ std::unique_ptr PipelineCache::CreateComputePipeline( thread_worker, program.info, std::move(spv_module)); } -static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) { - if (attr.enabled == 0) { - return Shader::AttributeType::Disabled; - } - switch (attr.Type()) { - case Maxwell::VertexAttribute::Type::SignedNorm: - case Maxwell::VertexAttribute::Type::UnsignedNorm: - case Maxwell::VertexAttribute::Type::UnsignedScaled: - case Maxwell::VertexAttribute::Type::SignedScaled: - case Maxwell::VertexAttribute::Type::Float: - return Shader::AttributeType::Float; - case Maxwell::VertexAttribute::Type::SignedInt: - return Shader::AttributeType::SignedInt; - case Maxwell::VertexAttribute::Type::UnsignedInt: - return Shader::AttributeType::UnsignedInt; - } - return Shader::AttributeType::Float; -} - -static std::vector MakeTransformFeedbackVaryings( - const GraphicsPipelineCacheKey& key) { - static constexpr std::array VECTORS{ - 28, // gl_Position - 32, // Generic 0 - 36, // Generic 1 - 40, // Generic 2 - 44, // Generic 3 - 48, // Generic 4 - 52, // Generic 5 - 56, // Generic 6 - 60, // Generic 7 - 64, // Generic 8 - 68, // Generic 9 - 72, // Generic 10 - 76, // Generic 11 - 80, // Generic 12 - 84, // Generic 13 - 88, // Generic 14 - 92, // Generic 15 - 96, // Generic 16 - 100, // Generic 17 - 104, // Generic 18 - 108, // Generic 19 - 112, // Generic 20 - 116, // Generic 21 - 120, // Generic 22 - 124, // Generic 23 - 128, // Generic 24 - 132, // Generic 25 - 136, // Generic 26 - 140, // Generic 27 - 144, // Generic 28 - 148, // Generic 29 - 152, // Generic 30 - 156, // Generic 31 - 160, // gl_FrontColor - 164, // gl_FrontSecondaryColor - 160, // gl_BackColor - 164, // gl_BackSecondaryColor - 192, // gl_TexCoord[0] - 196, // gl_TexCoord[1] - 200, // gl_TexCoord[2] - 204, // gl_TexCoord[3] - 208, // gl_TexCoord[4] - 212, // gl_TexCoord[5] - 216, // gl_TexCoord[6] - 220, // gl_TexCoord[7] - }; - std::vector xfb(256); - for (size_t buffer = 0; buffer < Maxwell::NumTransformFeedbackBuffers; ++buffer) { - const auto& locations = key.state.xfb_state.varyings[buffer]; - const auto& layout = key.state.xfb_state.layouts[buffer]; - const u32 varying_count = layout.varying_count; - u32 highest = 0; - for (u32 offset = 0; offset < varying_count; ++offset) { - const u32 base_offset = offset; - const u8 location = locations[offset]; - - Shader::TransformFeedbackVarying varying; - varying.buffer = layout.stream; - varying.stride = layout.stride; - varying.offset = offset * 4; - varying.components = 1; - - if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) { - UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB"); - - const u8 base_index = location / 4; - while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) { - ++offset; - ++varying.components; - } - } - xfb[location] = varying; - highest = std::max(highest, (base_offset + varying.components) * 4); - } - UNIMPLEMENTED_IF(highest != layout.stride); - } - return xfb; -} - -Shader::Profile PipelineCache::MakeProfile(const GraphicsPipelineCacheKey& key, - const Shader::IR::Program& program) { - Shader::Profile profile{base_profile}; - - const Shader::Stage stage{program.stage}; - const bool has_geometry{key.unique_hashes[4] != 0}; - const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; - const float point_size{Common::BitCast(key.state.point_size)}; - switch (stage) { - case Shader::Stage::VertexB: - if (!has_geometry) { - if (key.state.topology == Maxwell::PrimitiveTopology::Points) { - profile.fixed_state_point_size = point_size; - } - if (key.state.xfb_enabled != 0) { - profile.xfb_varyings = MakeTransformFeedbackVaryings(key); - } - profile.convert_depth_mode = gl_ndc; - } - std::ranges::transform(key.state.attributes, profile.generic_input_types.begin(), - &CastAttributeType); - break; - case Shader::Stage::TessellationEval: - // We have to flip tessellation clockwise for some reason... - profile.tess_clockwise = key.state.tessellation_clockwise == 0; - profile.tess_primitive = [&key] { - const u32 raw{key.state.tessellation_primitive.Value()}; - switch (static_cast(raw)) { - case Maxwell::TessellationPrimitive::Isolines: - return Shader::TessPrimitive::Isolines; - case Maxwell::TessellationPrimitive::Triangles: - return Shader::TessPrimitive::Triangles; - case Maxwell::TessellationPrimitive::Quads: - return Shader::TessPrimitive::Quads; - } - UNREACHABLE(); - return Shader::TessPrimitive::Triangles; - }(); - profile.tess_spacing = [&] { - const u32 raw{key.state.tessellation_spacing}; - switch (static_cast(raw)) { - case Maxwell::TessellationSpacing::Equal: - return Shader::TessSpacing::Equal; - case Maxwell::TessellationSpacing::FractionalOdd: - return Shader::TessSpacing::FractionalOdd; - case Maxwell::TessellationSpacing::FractionalEven: - return Shader::TessSpacing::FractionalEven; - } - UNREACHABLE(); - return Shader::TessSpacing::Equal; - }(); - break; - case Shader::Stage::Geometry: - if (program.output_topology == Shader::OutputTopology::PointList) { - profile.fixed_state_point_size = point_size; - } - if (key.state.xfb_enabled != 0) { - profile.xfb_varyings = MakeTransformFeedbackVaryings(key); - } - profile.convert_depth_mode = gl_ndc; - break; - case Shader::Stage::Fragment: - profile.alpha_test_func = MaxwellToCompareFunction( - key.state.UnpackComparisonOp(key.state.alpha_test_func.Value())); - profile.alpha_test_reference = Common::BitCast(key.state.alpha_test_ref); - break; - default: - break; - } - switch (key.state.topology) { - case Maxwell::PrimitiveTopology::Points: - profile.input_topology = Shader::InputTopology::Points; - break; - case Maxwell::PrimitiveTopology::Lines: - case Maxwell::PrimitiveTopology::LineLoop: - case Maxwell::PrimitiveTopology::LineStrip: - profile.input_topology = Shader::InputTopology::Lines; - break; - case Maxwell::PrimitiveTopology::Triangles: - case Maxwell::PrimitiveTopology::TriangleStrip: - case Maxwell::PrimitiveTopology::TriangleFan: - case Maxwell::PrimitiveTopology::Quads: - case Maxwell::PrimitiveTopology::QuadStrip: - case Maxwell::PrimitiveTopology::Polygon: - case Maxwell::PrimitiveTopology::Patches: - profile.input_topology = Shader::InputTopology::Triangles; - break; - case Maxwell::PrimitiveTopology::LinesAdjacency: - case Maxwell::PrimitiveTopology::LineStripAdjacency: - profile.input_topology = Shader::InputTopology::LinesAdjacency; - break; - case Maxwell::PrimitiveTopology::TrianglesAdjacency: - case Maxwell::PrimitiveTopology::TriangleStripAdjacency: - profile.input_topology = Shader::InputTopology::TrianglesAdjacency; - break; - } - profile.force_early_z = key.state.early_z != 0; - profile.y_negate = key.state.y_negate != 0; - return profile; -} - } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 4e48b4956..4116cc73f 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -129,9 +129,6 @@ private: Shader::Environment& env, bool build_in_parallel); - Shader::Profile MakeProfile(const GraphicsPipelineCacheKey& key, - const Shader::IR::Program& program); - const Device& device; VKScheduler& scheduler; DescriptorPool& descriptor_pool; @@ -148,7 +145,7 @@ private: ShaderPools main_pools; - Shader::Profile base_profile; + Shader::Profile profile; std::filesystem::path pipeline_cache_filename; Common::ThreadWorker workers; -- 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 ++++++-- src/video_core/renderer_opengl/gl_shader_cache.cpp | 4 ++-- 2 files changed, 8 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 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); diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 0a0f1324f..e678b4bb2 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -219,8 +219,8 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsProgramKey& key, return Shader::TessSpacing::Equal; }(); break; - case Shader::Stage::Geometry: - + case Shader::Stage::Fragment: + info.force_early_z = key.early_z != 0; break; default: break; -- 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 +- src/video_core/renderer_opengl/gl_shader_cache.cpp | 74 +++++++++++----------- src/video_core/renderer_opengl/gl_shader_cache.h | 2 + 3 files changed, 43 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 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;"; } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 747a133fb..2c0510f11 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -36,42 +36,6 @@ namespace OpenGL { namespace { -// FIXME: Move this somewhere else -const Shader::Profile profile{ - .supported_spirv = 0x00010000, - - .unified_descriptor_binding = false, - .support_descriptor_aliasing = false, - .support_int8 = false, - .support_int16 = false, - .support_vertex_instance_id = true, - .support_float_controls = false, - .support_separate_denorm_behavior = false, - .support_separate_rounding_mode = false, - .support_fp16_denorm_preserve = false, - .support_fp32_denorm_preserve = false, - .support_fp16_denorm_flush = false, - .support_fp32_denorm_flush = false, - .support_fp16_signed_zero_nan_preserve = false, - .support_fp32_signed_zero_nan_preserve = false, - .support_fp64_signed_zero_nan_preserve = false, - .support_explicit_workgroup_layout = false, - .support_vote = true, - .support_viewport_index_layer_non_geometry = true, - .support_viewport_mask = true, - .support_typeless_image_loads = true, - .support_demote_to_helper_invocation = false, - .support_int64_atomics = false, - - .warp_size_potentially_larger_than_guest = true, - .lower_left_origin_mode = true, - - .has_broken_spirv_clamp = true, - .has_broken_unsigned_image_offsets = true, - .has_broken_signed_operations = true, - .ignore_nan_fp_comparisons = true, -}; - using Shader::Backend::GLASM::EmitGLASM; using Shader::Backend::SPIRV::EmitSPIRV; using Shader::Maxwell::TranslateProgram; @@ -279,7 +243,43 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{ - state_tracker_} {} + state_tracker_} { + profile = Shader::Profile{ + .supported_spirv = 0x00010000, + + .unified_descriptor_binding = false, + .support_descriptor_aliasing = false, + .support_int8 = false, + .support_int16 = false, + .support_vertex_instance_id = true, + .support_float_controls = false, + .support_separate_denorm_behavior = false, + .support_separate_rounding_mode = false, + .support_fp16_denorm_preserve = false, + .support_fp32_denorm_preserve = false, + .support_fp16_denorm_flush = false, + .support_fp32_denorm_flush = false, + .support_fp16_signed_zero_nan_preserve = false, + .support_fp32_signed_zero_nan_preserve = false, + .support_fp64_signed_zero_nan_preserve = false, + .support_explicit_workgroup_layout = false, + .support_vote = true, + .support_viewport_index_layer_non_geometry = + device.HasNvViewportArray2() || device.HasVertexViewportLayer(), + .support_viewport_mask = true, + .support_typeless_image_loads = device.HasImageLoadFormatted(), + .support_demote_to_helper_invocation = false, + .support_int64_atomics = false, + + .warp_size_potentially_larger_than_guest = true, + .lower_left_origin_mode = true, + + .has_broken_spirv_clamp = true, + .has_broken_unsigned_image_offsets = true, + .has_broken_signed_operations = true, + .ignore_nan_fp_comparisons = true, + }; +} ShaderCache::~ShaderCache() = default; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index b479d073a..b49cd0ac7 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -86,6 +86,8 @@ private: ShaderPools main_pools; std::unordered_map> graphics_cache; std::unordered_map> compute_cache; + + Shader::Profile profile; }; } // namespace OpenGL -- 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 --- src/shader_recompiler/CMakeLists.txt | 1 - .../backend/glasm/emit_glasm_image.cpp | 153 +++++++++++++++++++ .../backend/glasm/emit_glasm_image_atomic.cpp | 165 --------------------- 3 files changed, 153 insertions(+), 166 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/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 0d55924a7..becdb7d54 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -13,7 +13,6 @@ add_library(shader_recompiler STATIC backend/glasm/emit_glasm_convert.cpp backend/glasm/emit_glasm_floating_point.cpp backend/glasm/emit_glasm_image.cpp - backend/glasm/emit_glasm_image_atomic.cpp backend/glasm/emit_glasm_instructions.h backend/glasm/emit_glasm_integer.cpp backend/glasm/emit_glasm_logical.cpp 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 --- .../backend/glasm/emit_glasm_not_implemented.cpp | 4 +++- src/shader_recompiler/frontend/ir/value.h | 13 +++++++++++++ 2 files changed, 16 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; } diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 0c6bf684d..090cc1739 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -395,4 +395,17 @@ inline f64 Value::F64() const { return inst.GetOpcode() == Opcode::Phi; } +[[nodiscard]] inline bool IsUndef(const Inst& inst) { + switch (inst.GetOpcode()) { + case Opcode::UndefU1: + case Opcode::UndefU8: + case Opcode::UndefU16: + case Opcode::UndefU32: + case Opcode::UndefU64: + return true; + default: + return false; + } +} + } // namespace Shader::IR -- 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 --- src/shader_recompiler/CMakeLists.txt | 1 - .../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 ++++++++++++++++++++- src/shader_recompiler/profile.h | 3 + src/video_core/renderer_opengl/gl_buffer_cache.cpp | 26 +- src/video_core/renderer_opengl/gl_buffer_cache.h | 6 + .../renderer_opengl/gl_compute_pipeline.cpp | 42 ++- .../renderer_opengl/gl_compute_pipeline.h | 12 +- src/video_core/renderer_opengl/gl_device.cpp | 18 +- src/video_core/renderer_opengl/gl_device.h | 6 +- .../renderer_opengl/gl_graphics_pipeline.cpp | 19 +- .../renderer_opengl/gl_graphics_pipeline.h | 12 +- src/video_core/renderer_opengl/gl_rasterizer.cpp | 13 +- src/video_core/renderer_opengl/gl_rasterizer.h | 3 +- src/video_core/renderer_opengl/gl_shader_cache.cpp | 30 +- 17 files changed, 503 insertions(+), 437 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/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index becdb7d54..d6d8e5f59 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -4,7 +4,6 @@ add_library(shader_recompiler STATIC backend/glasm/emit_context.h backend/glasm/emit_glasm.cpp backend/glasm/emit_glasm.h - backend/glasm/emit_glasm_atomic.cpp backend/glasm/emit_glasm_barriers.cpp backend/glasm/emit_glasm_bitwise_conversion.cpp backend/glasm/emit_glasm_composite.cpp 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 diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index c46452c3d..f8913bf14 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -111,7 +111,10 @@ struct RuntimeInfo { std::optional alpha_test_func; float alpha_test_reference{}; + // Static y negate value bool y_negate{}; + // Use storage buffers instead of global pointers on GLASM + bool glasm_use_storage_buffers{}; std::vector xfb_varyings; }; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 2d0ef1307..334ed470f 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp @@ -195,7 +195,12 @@ void BufferCacheRuntime::BindComputeUniformBuffer(u32 binding_index, Buffer& buf void BufferCacheRuntime::BindStorageBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size, bool is_written) { - if (use_assembly_shaders) { + if (use_storage_buffers) { + const GLuint base_binding = graphics_base_storage_bindings[stage]; + const GLuint binding = base_binding + binding_index; + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, buffer.Handle(), + static_cast(offset), static_cast(size)); + } else { const BindlessSSBO ssbo{ .address = buffer.HostGpuAddr() + offset, .length = static_cast(size), @@ -204,17 +209,19 @@ void BufferCacheRuntime::BindStorageBuffer(size_t stage, u32 binding_index, Buff buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); glProgramLocalParametersI4uivNV(PROGRAM_LUT[stage], binding_index, 1, reinterpret_cast(&ssbo)); - } else { - const GLuint base_binding = graphics_base_storage_bindings[stage]; - const GLuint binding = base_binding + binding_index; - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, buffer.Handle(), - static_cast(offset), static_cast(size)); } } void BufferCacheRuntime::BindComputeStorageBuffer(u32 binding_index, Buffer& buffer, u32 offset, u32 size, bool is_written) { - if (use_assembly_shaders) { + if (use_storage_buffers) { + if (size != 0) { + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, buffer.Handle(), + static_cast(offset), static_cast(size)); + } else { + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, 0, 0, 0); + } + } else { const BindlessSSBO ssbo{ .address = buffer.HostGpuAddr() + offset, .length = static_cast(size), @@ -223,11 +230,6 @@ void BufferCacheRuntime::BindComputeStorageBuffer(u32 binding_index, Buffer& buf buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); glProgramLocalParametersI4uivNV(GL_COMPUTE_PROGRAM_NV, binding_index, 1, reinterpret_cast(&ssbo)); - } else if (size == 0) { - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, 0, 0, 0); - } else { - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, buffer.Handle(), - static_cast(offset), static_cast(size)); } } diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 4986c65fd..bc16abafb 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -147,6 +147,10 @@ public: image_handles = image_handles_; } + void SetEnableStorageBuffers(bool use_storage_buffers_) { + use_storage_buffers = use_storage_buffers_; + } + private: static constexpr std::array PABO_LUT{ GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV, @@ -160,6 +164,8 @@ private: bool use_assembly_shaders = false; bool has_unified_vertex_buffers = false; + bool use_storage_buffers = false; + u32 max_attributes = 0; std::array graphics_base_uniform_bindings{}; diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 700ebd8b8..5cf5f97a9 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp @@ -17,6 +17,15 @@ using VideoCommon::ImageId; constexpr u32 MAX_TEXTURES = 64; constexpr u32 MAX_IMAGES = 16; +template +u32 AccumulateCount(const Range& range) { + u32 num{}; + for (const auto& desc : range) { + num += desc.count; + } + return num; +} + size_t ComputePipelineKey::Hash() const noexcept { return static_cast( Common::CityHash64(reinterpret_cast(this), sizeof *this)); @@ -26,31 +35,31 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep return std::memcmp(this, &rhs, sizeof *this) == 0; } -ComputePipeline::ComputePipeline(TextureCache& texture_cache_, BufferCache& buffer_cache_, - Tegra::MemoryManager& gpu_memory_, +ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_, + BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::KeplerCompute& kepler_compute_, ProgramManager& program_manager_, const Shader::Info& info_, OGLProgram source_program_, OGLAssemblyProgram assembly_program_) : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, kepler_compute{kepler_compute_}, program_manager{program_manager_}, info{info_}, source_program{std::move(source_program_)}, assembly_program{std::move(assembly_program_)} { - for (const auto& desc : info.texture_buffer_descriptors) { - num_texture_buffers += desc.count; - } - for (const auto& desc : info.image_buffer_descriptors) { - num_image_buffers += desc.count; - } - u32 num_textures = num_texture_buffers; - for (const auto& desc : info.texture_descriptors) { - num_textures += desc.count; - } + + num_texture_buffers = AccumulateCount(info.texture_buffer_descriptors); + num_image_buffers = AccumulateCount(info.image_buffer_descriptors); + + const u32 num_textures{num_texture_buffers + AccumulateCount(info.texture_descriptors)}; ASSERT(num_textures <= MAX_TEXTURES); - u32 num_images = num_image_buffers; - for (const auto& desc : info.image_descriptors) { - num_images += desc.count; - } + const u32 num_images{num_image_buffers + AccumulateCount(info.image_descriptors)}; ASSERT(num_images <= MAX_IMAGES); + + const bool is_glasm{assembly_program.handle != 0}; + const u32 num_storage_buffers{AccumulateCount(info.storage_buffers_descriptors)}; + use_storage_buffers = + !is_glasm || num_storage_buffers < device.GetMaxGLASMStorageBufferBlocks(); + writes_global_memory = !use_storage_buffers && + std::ranges::any_of(info.storage_buffers_descriptors, + [](const auto& desc) { return desc.is_written; }); } void ComputePipeline::Configure() { @@ -150,6 +159,7 @@ void ComputePipeline::Configure() { buffer_cache.UpdateComputeBuffers(); + buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers); buffer_cache.runtime.SetImagePointers(textures.data(), images.data()); buffer_cache.BindHostComputeBuffers(); diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h index e3b94e2f3..dd6b62ef2 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.h +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h @@ -28,6 +28,7 @@ struct Info; namespace OpenGL { +class Device; class ProgramManager; struct ComputePipelineKey { @@ -49,14 +50,18 @@ static_assert(std::is_trivially_constructible_v); class ComputePipeline { public: - explicit ComputePipeline(TextureCache& texture_cache_, BufferCache& buffer_cache_, - Tegra::MemoryManager& gpu_memory_, + explicit ComputePipeline(const Device& device, TextureCache& texture_cache_, + BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::KeplerCompute& kepler_compute_, ProgramManager& program_manager_, const Shader::Info& info_, OGLProgram source_program_, OGLAssemblyProgram assembly_program_); void Configure(); + [[nodiscard]] bool WritesGlobalMemory() const noexcept { + return writes_global_memory; + } + private: TextureCache& texture_cache; BufferCache& buffer_cache; @@ -70,6 +75,9 @@ private: u32 num_texture_buffers{}; u32 num_image_buffers{}; + + bool use_storage_buffers{}; + bool writes_global_memory{}; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 18bbc4c1f..01da2bb57 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -135,13 +135,13 @@ Device::Device() { "Beta driver 443.24 is known to have issues. There might be performance issues."); disable_fast_buffer_sub_data = true; } - max_uniform_buffers = BuildMaxUniformBuffers(); uniform_buffer_alignment = GetInteger(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); shader_storage_alignment = GetInteger(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); max_vertex_attributes = GetInteger(GL_MAX_VERTEX_ATTRIBS); max_varyings = GetInteger(GL_MAX_VARYING_VECTORS); max_compute_shared_memory_size = GetInteger(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE); + max_glasm_storage_buffer_blocks = GetInteger(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS); has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group && GLAD_GL_NV_shader_thread_shuffle; has_shader_ballot = GLAD_GL_ARB_shader_ballot; @@ -236,22 +236,6 @@ std::string Device::GetVendorName() const { return vendor_name; } -Device::Device(std::nullptr_t) { - max_uniform_buffers.fill(std::numeric_limits::max()); - uniform_buffer_alignment = 4; - shader_storage_alignment = 4; - max_vertex_attributes = 16; - max_varyings = 15; - max_compute_shared_memory_size = 0x10000; - has_warp_intrinsics = true; - has_shader_ballot = true; - has_vertex_viewport_layer = true; - has_image_load_formatted = true; - has_texture_shadow_lod = true; - has_variable_aoffi = true; - has_depth_buffer_float = true; -} - bool Device::TestVariableAoffi() { return TestProgram(R"(#version 430 core // This is a unit test, please ignore me on apitrace bug reports. diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 152a3acd3..d67f5693c 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -13,7 +13,6 @@ namespace OpenGL { class Device { public: explicit Device(); - explicit Device(std::nullptr_t); [[nodiscard]] std::string GetVendorName() const; @@ -41,6 +40,10 @@ public: return max_compute_shared_memory_size; } + u32 GetMaxGLASMStorageBufferBlocks() const { + return max_glasm_storage_buffer_blocks; + } + bool HasWarpIntrinsics() const { return has_warp_intrinsics; } @@ -124,6 +127,7 @@ private: u32 max_vertex_attributes{}; u32 max_varyings{}; u32 max_compute_shared_memory_size{}; + u32 max_glasm_storage_buffer_blocks{}; bool has_warp_intrinsics{}; bool has_shader_ballot{}; bool has_vertex_viewport_layer{}; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 32df35202..19d85c482 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -25,7 +25,7 @@ constexpr u32 MAX_TEXTURES = 64; constexpr u32 MAX_IMAGES = 8; template -u32 AccumulateCount(Range&& range) { +u32 AccumulateCount(const Range& range) { u32 num{}; for (const auto& desc : range) { num += desc.count; @@ -70,8 +70,8 @@ bool GraphicsPipelineKey::operator==(const GraphicsPipelineKey& rhs) const noexc return std::memcmp(this, &rhs, Size()) == 0; } -GraphicsPipeline::GraphicsPipeline(TextureCache& texture_cache_, BufferCache& buffer_cache_, - Tegra::MemoryManager& gpu_memory_, +GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_cache_, + BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, ProgramManager& program_manager_, StateTracker& state_tracker_, OGLProgram program_, @@ -90,6 +90,7 @@ GraphicsPipeline::GraphicsPipeline(TextureCache& texture_cache_, BufferCache& bu } u32 num_textures{}; u32 num_images{}; + u32 num_storage_buffers{}; for (size_t stage = 0; stage < base_uniform_bindings.size(); ++stage) { const auto& info{stage_infos[stage]}; if (stage < 4) { @@ -109,11 +110,20 @@ GraphicsPipeline::GraphicsPipeline(TextureCache& texture_cache_, BufferCache& bu num_textures += AccumulateCount(info.texture_descriptors); num_images += AccumulateCount(info.image_descriptors); + num_storage_buffers += AccumulateCount(info.storage_buffers_descriptors); + + writes_global_memory |= std::ranges::any_of( + info.storage_buffers_descriptors, [](const auto& desc) { return desc.is_written; }); } ASSERT(num_textures <= MAX_TEXTURES); ASSERT(num_images <= MAX_IMAGES); - if (assembly_programs[0].handle != 0 && xfb_state) { + const bool assembly_shaders{assembly_programs[0].handle != 0}; + use_storage_buffers = + !assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); + writes_global_memory &= !use_storage_buffers; + + if (assembly_shaders && xfb_state) { GenerateTransformFeedbackState(*xfb_state); } } @@ -137,6 +147,7 @@ void GraphicsPipeline::Configure(bool is_indexed) { buffer_cache.runtime.SetBaseUniformBindings(base_uniform_bindings); buffer_cache.runtime.SetBaseStorageBindings(base_storage_bindings); + buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers); const auto& regs{maxwell3d.regs}; const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 62f700cf5..c1113e180 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h @@ -20,6 +20,7 @@ namespace OpenGL { +class Device; class ProgramManager; using Maxwell = Tegra::Engines::Maxwell3D::Regs; @@ -60,8 +61,8 @@ static_assert(std::is_trivially_constructible_v); class GraphicsPipeline { public: - explicit GraphicsPipeline(TextureCache& texture_cache_, BufferCache& buffer_cache_, - Tegra::MemoryManager& gpu_memory_, + explicit GraphicsPipeline(const Device& device, TextureCache& texture_cache_, + BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, ProgramManager& program_manager_, StateTracker& state_tracker_, OGLProgram program_, @@ -77,6 +78,10 @@ public: } } + [[nodiscard]] bool WritesGlobalMemory() const noexcept { + return writes_global_memory; + } + private: void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state); @@ -99,6 +104,9 @@ private: std::array num_texture_buffers{}; std::array num_image_buffers{}; + bool use_storage_buffers{}; + bool writes_global_memory{}; + static constexpr std::size_t XFB_ENTRY_STRIDE = 3; GLsizei num_xfb_attribs{}; GLsizei num_xfb_strides{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index eec01e8c2..5d4e80364 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -268,19 +268,21 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { EndTransformFeedback(); ++num_queued_commands; + has_written_global_memory |= pipeline->WritesGlobalMemory(); gpu.TickWork(); } void RasterizerOpenGL::DispatchCompute() { - ComputePipeline* const program{shader_cache.CurrentComputePipeline()}; - if (!program) { + ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; + if (!pipeline) { return; } - program->Configure(); + pipeline->Configure(); const auto& qmd{kepler_compute.launch_description}; glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z); ++num_queued_commands; + has_written_global_memory |= pipeline->WritesGlobalMemory(); } void RasterizerOpenGL::ResetCounter(VideoCore::QueryType type) { @@ -449,9 +451,8 @@ void RasterizerOpenGL::FlushCommands() { // Make sure memory stored from the previous GL command stream is visible // This is only needed on assembly shaders where we write to GPU memory with raw pointers - // TODO: Call this only when NV_shader_buffer_load or NV_shader_buffer_store have been used - // and prefer using NV_shader_storage_buffer_object when possible - if (Settings::values.use_assembly_shaders.GetValue()) { + if (has_written_global_memory) { + has_written_global_memory = false; glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); } glFlush(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index afd43b2ee..d0397b745 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -225,7 +225,8 @@ private: std::array image_handles{}; /// Number of commands queued to the OpenGL driver. Resetted on flush. - std::size_t num_queued_commands = 0; + size_t num_queued_commands = 0; + bool has_written_global_memory = false; u32 last_clip_distance_mask = 0; }; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 3aa5ac31d..287f497b5 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -157,7 +157,8 @@ GLenum AssemblyStage(size_t stage_index) { } Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, - const Shader::IR::Program& program) { + const Shader::IR::Program& program, + bool glasm_use_storage_buffers) { Shader::RuntimeInfo info; switch (program.stage) { case Shader::Stage::TessellationEval: @@ -220,6 +221,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, info.input_topology = Shader::InputTopology::TrianglesAdjacency; break; } + info.glasm_use_storage_buffers = glasm_use_storage_buffers; return info; } @@ -435,7 +437,8 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( ShaderPools& pools, const GraphicsPipelineKey& key, std::span envs, bool build_in_parallel) { LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); - size_t env_index{0}; + size_t env_index{}; + u32 total_storage_buffers{}; std::array programs; for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { if (key.unique_hashes[index] == 0) { @@ -447,7 +450,14 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( const u32 cfg_offset{static_cast(env.StartAddress() + sizeof(Shader::ProgramHeader))}; Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset); programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg); + + for (const auto& desc : programs[index].info.storage_buffers_descriptors) { + total_storage_buffers += desc.count; + } } + const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; + const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit}; + std::array infos{}; OGLProgram source_program; @@ -466,7 +476,7 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( const size_t stage_index{index - 1}; infos[stage_index] = &program.info; - const Shader::RuntimeInfo runtime_info{MakeRuntimeInfo(key, program)}; + const auto runtime_info{MakeRuntimeInfo(key, program, glasm_use_storage_buffers)}; if (device.UseAssemblyShaders()) { const std::string code{EmitGLASM(profile, runtime_info, program, binding)}; assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index)); @@ -479,7 +489,7 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( LinkProgram(source_program.handle); } return std::make_unique( - texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, + device, texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, std::move(source_program), std::move(assembly_programs), infos, key.xfb_enabled != 0 ? &key.xfb_state : nullptr); } @@ -508,10 +518,18 @@ std::unique_ptr ShaderCache::CreateComputePipeline(ShaderPools& Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; Shader::IR::Program program{TranslateProgram(pools.inst, pools.block, env, cfg)}; + + u32 num_storage_buffers{}; + for (const auto& desc : program.info.storage_buffers_descriptors) { + num_storage_buffers += desc.count; + } + Shader::RuntimeInfo info; + info.glasm_use_storage_buffers = num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); + OGLAssemblyProgram asm_program; OGLProgram source_program; if (device.UseAssemblyShaders()) { - const std::string code{EmitGLASM(profile, program)}; + const std::string code{EmitGLASM(profile, info, program)}; asm_program = CompileProgram(code, GL_COMPUTE_PROGRAM_NV); } else { const std::vector code{EmitSPIRV(profile, program)}; @@ -519,7 +537,7 @@ std::unique_ptr ShaderCache::CreateComputePipeline(ShaderPools& AddShader(GL_COMPUTE_SHADER, source_program.handle, code); LinkProgram(source_program.handle); } - return std::make_unique(texture_cache, buffer_cache, gpu_memory, + return std::make_unique(device, texture_cache, buffer_cache, gpu_memory, kepler_compute, program_manager, program.info, std::move(source_program), std::move(asm_program)); } -- 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. --- .../backend/glasm/emit_glasm_not_implemented.cpp | 4 +--- src/shader_recompiler/frontend/ir/value.h | 13 ------------- 2 files changed, 1 insertion(+), 16 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; } diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 090cc1739..0c6bf684d 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -395,17 +395,4 @@ inline f64 Value::F64() const { return inst.GetOpcode() == Opcode::Phi; } -[[nodiscard]] inline bool IsUndef(const Inst& inst) { - switch (inst.GetOpcode()) { - case Opcode::UndefU1: - case Opcode::UndefU8: - case Opcode::UndefU16: - case Opcode::UndefU32: - case Opcode::UndefU64: - return true; - default: - return false; - } -} - } // namespace Shader::IR -- 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 +-- src/shader_recompiler/backend/spirv/emit_context.cpp | 2 +- src/shader_recompiler/profile.h | 4 ++++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 ++ src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 7 +++++++ 6 files changed, 18 insertions(+), 10 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;"; } } diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 3e8899f53..7c618125e 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1320,7 +1320,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { break; case Stage::Fragment: for (u32 index = 0; index < 8; ++index) { - if (!info.stores_frag_color[index]) { + if (!info.stores_frag_color[index] && !profile.need_declared_frag_colors) { continue; } frag_color[index] = DefineOutput(*this, F32[4], std::nullopt); diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index f8913bf14..f059e3b26 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -84,7 +84,11 @@ struct Profile { bool support_int64_atomics{}; bool warp_size_potentially_larger_than_guest{}; + bool lower_left_origin_mode{}; + /// Fragment outputs have to be declared even if they are not written to avoid undefined values. + /// See Ori and the Blind Forest's main menu for reference. + bool need_declared_frag_colors{}; /// OpFClamp is broken and OpFMax + OpFMin should be used instead bool has_broken_spirv_clamp{}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7d2ec4efa..6ea7c0ee8 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -276,7 +276,9 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .support_int64_atomics = false, .warp_size_potentially_larger_than_guest = true, + .lower_left_origin_mode = true, + .need_declared_frag_colors = true, .has_broken_spirv_clamp = true, .has_broken_unsigned_image_offsets = true, diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index b6998e37c..cec51cc77 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -274,9 +274,16 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw .support_typeless_image_loads = device.IsFormatlessImageLoadSupported(), .support_demote_to_helper_invocation = true, .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), + .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), + + .lower_left_origin_mode = false, + .need_declared_frag_colors = false, + .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, .has_broken_unsigned_image_offsets = false, + .has_broken_signed_operations = false, + .ignore_nan_fp_comparisons = false, }; } -- 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 ++++++++ .../backend/spirv/emit_spirv_context_get_set.cpp | 9 +++------ src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | 4 ++-- 3 files changed, 13 insertions(+), 8 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 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); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index c1b69c234..442a958a5 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -122,7 +122,7 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { } Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, - const IR::Value& binding, const IR::Value& offset, bool check_alignment = true) { + const IR::Value& binding, const IR::Value& offset) { if (!binding.IsImmediate()) { throw NotImplementedException("Constant buffer indexing"); } @@ -138,17 +138,14 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, index)}; return ctx.OpLoad(result_type, access_chain); } - if (check_alignment && offset.U32() % element_size != 0) { - throw NotImplementedException("Unaligned immediate constant buffer load"); - } + // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4) const Id imm_offset{ctx.Const(offset.U32() / element_size)}; const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, imm_offset)}; return ctx.OpLoad(result_type, access_chain); } Id GetCbufU32x4(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset, - false); + return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset); } Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 index_offset) { diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index 88bbac0a5..b446aae0e 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp @@ -122,14 +122,14 @@ IR::F64 TranslatorVisitor::GetDoubleReg39(u64 insn) { static std::pair CbufAddr(u64 insn) { union { u64 raw; - BitField<20, 14, s64> offset; + BitField<20, 14, u64> offset; BitField<34, 5, u64> binding; } const cbuf{insn}; if (cbuf.binding >= 18) { throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); } - if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { + if (cbuf.offset >= 0x10'000) { throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); } const IR::Value binding{static_cast(cbuf.binding)}; -- 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 +++- .../ir_opt/collect_shader_info_pass.cpp | 70 ++++++---------------- src/shader_recompiler/shader_info.h | 1 + 3 files changed, 29 insertions(+), 54 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; } diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index b343f0429..6a5243c9f 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -28,12 +28,16 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { }); } -void GetAttribute(Info& info, IR::Attribute attribute) { - if (IR::IsGeneric(attribute)) { - info.input_generics.at(IR::GenericAttributeIndex(attribute)).used = true; +void GetAttribute(Info& info, IR::Attribute attr) { + if (IR::IsGeneric(attr)) { + info.input_generics.at(IR::GenericAttributeIndex(attr)).used = true; return; } - switch (attribute) { + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + info.loads_fixed_fnc_textures = true; + return; + } + switch (attr) { case IR::Attribute::PrimitiveId: info.loads_primitive_id = true; break; @@ -67,16 +71,20 @@ void GetAttribute(Info& info, IR::Attribute attribute) { info.loads_front_face = true; break; default: - throw NotImplementedException("Get attribute {}", attribute); + throw NotImplementedException("Get attribute {}", attr); } } -void SetAttribute(Info& info, IR::Attribute attribute) { - if (IR::IsGeneric(attribute)) { - info.stores_generics.at(IR::GenericAttributeIndex(attribute)) = true; +void SetAttribute(Info& info, IR::Attribute attr) { + if (IR::IsGeneric(attr)) { + info.stores_generics.at(IR::GenericAttributeIndex(attr)) = true; return; } - switch (attribute) { + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + info.stores_fixed_fnc_textures = true; + return; + } + switch (attr) { case IR::Attribute::Layer: info.stores_layer = true; break; @@ -116,48 +124,6 @@ void SetAttribute(Info& info, IR::Attribute attribute) { case IR::Attribute::ColorBackSpecularA: info.stores_color_front_specular = true; break; - case IR::Attribute::FixedFncTexture0S: - case IR::Attribute::FixedFncTexture0T: - case IR::Attribute::FixedFncTexture0R: - case IR::Attribute::FixedFncTexture0Q: - case IR::Attribute::FixedFncTexture1S: - case IR::Attribute::FixedFncTexture1T: - case IR::Attribute::FixedFncTexture1R: - case IR::Attribute::FixedFncTexture1Q: - case IR::Attribute::FixedFncTexture2S: - case IR::Attribute::FixedFncTexture2T: - case IR::Attribute::FixedFncTexture2R: - case IR::Attribute::FixedFncTexture2Q: - case IR::Attribute::FixedFncTexture3S: - case IR::Attribute::FixedFncTexture3T: - case IR::Attribute::FixedFncTexture3R: - case IR::Attribute::FixedFncTexture3Q: - case IR::Attribute::FixedFncTexture4S: - case IR::Attribute::FixedFncTexture4T: - case IR::Attribute::FixedFncTexture4R: - case IR::Attribute::FixedFncTexture4Q: - case IR::Attribute::FixedFncTexture5S: - case IR::Attribute::FixedFncTexture5T: - case IR::Attribute::FixedFncTexture5R: - case IR::Attribute::FixedFncTexture5Q: - case IR::Attribute::FixedFncTexture6S: - case IR::Attribute::FixedFncTexture6T: - case IR::Attribute::FixedFncTexture6R: - case IR::Attribute::FixedFncTexture6Q: - case IR::Attribute::FixedFncTexture7S: - case IR::Attribute::FixedFncTexture7T: - case IR::Attribute::FixedFncTexture7R: - case IR::Attribute::FixedFncTexture7Q: - case IR::Attribute::FixedFncTexture8S: - case IR::Attribute::FixedFncTexture8T: - case IR::Attribute::FixedFncTexture8R: - case IR::Attribute::FixedFncTexture8Q: - case IR::Attribute::FixedFncTexture9S: - case IR::Attribute::FixedFncTexture9T: - case IR::Attribute::FixedFncTexture9R: - case IR::Attribute::FixedFncTexture9Q: - info.stores_fixed_fnc_textures = true; - break; case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance1: case IR::Attribute::ClipDistance2: @@ -175,7 +141,7 @@ void SetAttribute(Info& info, IR::Attribute attribute) { info.stores_viewport_mask = true; break; default: - throw NotImplementedException("Set attribute {}", attribute); + throw NotImplementedException("Set attribute {}", attr); } } diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index b60ba0457..d5b2ca7bc 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -123,6 +123,7 @@ struct Info { bool loads_primitive_id{}; bool loads_position{}; bool loads_color_front_diffuse{}; + bool loads_fixed_fnc_textures{}; bool loads_point_coord{}; bool loads_instance_id{}; bool loads_vertex_id{}; -- 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 +++++++++++++++++++--- src/shader_recompiler/profile.h | 1 + src/video_core/renderer_opengl/gl_device.cpp | 1 + src/video_core/renderer_opengl/gl_device.h | 5 ++++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 1 + 6 files changed, 37 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 diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index f059e3b26..3109fb69c 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -82,6 +82,7 @@ struct Profile { bool support_typeless_image_loads{}; bool support_demote_to_helper_invocation{}; bool support_int64_atomics{}; + bool support_derivative_control{}; bool warp_size_potentially_larger_than_guest{}; diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 01da2bb57..3f7929f9e 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -154,6 +154,7 @@ Device::Device() { has_precise_bug = TestPreciseBug(); has_broken_texture_view_formats = is_amd || (!is_linux && is_intel); has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; + has_derivative_control = GLAD_GL_ARB_derivative_control; has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; has_debugging_tool_attached = IsDebugToolAttached(extensions); has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float"); diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index d67f5693c..1ffd24883 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -96,6 +96,10 @@ public: return has_nv_viewport_array2; } + bool HasDerivativeControl() const { + return has_derivative_control; + } + bool HasDebuggingToolAttached() const { return has_debugging_tool_attached; } @@ -141,6 +145,7 @@ private: bool has_broken_texture_view_formats{}; bool has_fast_buffer_sub_data{}; bool has_nv_viewport_array2{}; + bool has_derivative_control{}; bool has_debugging_tool_attached{}; bool use_assembly_shaders{}; bool use_asynchronous_shaders{}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 6ea7c0ee8..bdffac4b2 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -274,6 +274,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .support_typeless_image_loads = device.HasImageLoadFormatted(), .support_demote_to_helper_invocation = false, .support_int64_atomics = false, + .support_derivative_control = device.HasDerivativeControl(), .warp_size_potentially_larger_than_guest = true, -- 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/common/settings.h | 3 + .../backend/glasm/emit_glasm_instructions.h | 2 + .../backend/glasm/emit_glasm_not_implemented.cpp | 8 +++ .../backend/spirv/emit_spirv_context_get_set.cpp | 24 +++++--- .../backend/spirv/emit_spirv_instructions.h | 2 + src/shader_recompiler/frontend/ir/ir_emitter.cpp | 14 ++++- src/shader_recompiler/frontend/ir/ir_emitter.h | 3 + src/shader_recompiler/frontend/ir/opcodes.inc | 2 + .../frontend/maxwell/structured_control_flow.cpp | 42 ++++++++++++-- src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 66 +++++++++++++++------- src/video_core/vulkan_common/vulkan_device.cpp | 4 +- src/yuzu/configuration/config.cpp | 4 ++ src/yuzu/configuration/configure_debug.cpp | 8 +++ src/yuzu/configuration/configure_debug.ui | 26 +++++++++ src/yuzu_cmd/config.cpp | 2 + src/yuzu_cmd/default_ini.h | 8 +++ 16 files changed, 183 insertions(+), 35 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/common/settings.h b/src/common/settings.h index ce1bc647d..ac0590690 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -308,6 +308,9 @@ struct Values { // Renderer Setting renderer_backend{RendererBackend::OpenGL, "backend"}; BasicSetting renderer_debug{false, "debug"}; + BasicSetting enable_nsight_aftermath{false, "nsight_aftermath"}; + BasicSetting disable_shader_loop_safety_checks{false, + "disable_shader_loop_safety_checks"}; Setting vulkan_device{0, "vulkan_device"}; Setting resolution_factor{1, "resolution_factor"}; 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(); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 442a958a5..42fff74e3 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -163,35 +163,43 @@ Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 inde } // Anonymous namespace void EmitGetRegister(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitSetRegister(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitGetPred(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitSetPred(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitSetGotoVariable(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitGetGotoVariable(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitSetIndirectBranchVariable(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); } void EmitGetIndirectBranchVariable(EmitContext&) { - throw NotImplementedException("SPIR-V Instruction"); + throw LogicError("Unreachable instruction"); +} + +void EmitSetLoopSafetyVariable(EmitContext&) { + throw LogicError("Unreachable instruction"); +} + +void EmitGetLoopSafetyVariable(EmitContext&) { + throw LogicError("Unreachable instruction"); } Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 1181e7b4f..e3e5b03fe 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -43,6 +43,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); Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index e9fd41237..6c37af5e7 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -125,6 +125,12 @@ U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) { } } +void IREmitter::SetPred(IR::Pred pred, const U1& value) { + if (pred != IR::Pred::PT) { + Inst(Opcode::SetPred, pred, value); + } +} + U1 IREmitter::GetGotoVariable(u32 id) { return Inst(Opcode::GetGotoVariable, id); } @@ -141,8 +147,12 @@ void IREmitter::SetIndirectBranchVariable(const U32& value) { Inst(Opcode::SetIndirectBranchVariable, value); } -void IREmitter::SetPred(IR::Pred pred, const U1& value) { - Inst(Opcode::SetPred, pred, value); +U32 IREmitter::GetLoopSafetyVariable(u32 id) { + return Inst(Opcode::GetLoopSafetyVariable, id); +} + +void IREmitter::SetLoopSafetyVariable(u32 id, const U32& counter) { + Inst(Opcode::SetLoopSafetyVariable, id, counter); } U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index bb3500c54..7caab1f61 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -55,6 +55,9 @@ public: [[nodiscard]] U32 GetIndirectBranchVariable(); void SetIndirectBranchVariable(const U32& value); + [[nodiscard]] U32 GetLoopSafetyVariable(u32 id); + void SetLoopSafetyVariable(u32 id, const U32& counter); + [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, bool is_signed); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 8a8d0d759..e87aeddd5 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -32,6 +32,8 @@ OPCODE(GetGotoVariable, U1, U32, OPCODE(SetGotoVariable, Void, U32, U1, ) OPCODE(GetIndirectBranchVariable, U32, ) OPCODE(SetIndirectBranchVariable, Void, U32, ) +OPCODE(GetLoopSafetyVariable, U32, U32, ) +OPCODE(SetLoopSafetyVariable, Void, U32, U32, ) OPCODE(GetCbufU8, U32, U32, U32, ) OPCODE(GetCbufS8, U32, U32, U32, ) OPCODE(GetCbufU16, U32, U32, U32, ) diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index c1e0646e6..b2b8c492a 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -9,11 +9,13 @@ #include #include #include +#include #include #include +#include "common/settings.h" #include "shader_recompiler/environment.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/ir_emitter.h" @@ -739,8 +741,25 @@ private: } case StatementType::Loop: { IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; - if (current_block) { - current_block->AddBranch(loop_header_block); + const u32 this_loop_id{loop_id++}; + + if (Settings::values.disable_shader_loop_safety_checks) { + if (current_block) { + current_block->AddBranch(loop_header_block); + } + } else { + IR::Block* const init_block{block_pool.Create(inst_pool)}; + IR::IREmitter ir{*init_block}; + ir.SetLoopSafetyVariable(this_loop_id, ir.Imm32(0x2000)); + + if (current_block) { + current_block->AddBranch(init_block); + } + init_block->AddBranch(loop_header_block); + + auto& init_node{syntax_list.emplace_back()}; + init_node.type = IR::AbstractSyntaxNode::Type::Block; + init_node.data.block = init_block; } auto& header_node{syntax_list.emplace_back()}; header_node.type = IR::AbstractSyntaxNode::Type::Block; @@ -758,7 +777,16 @@ private: // The continue block is located at the end of the loop IR::IREmitter ir{*continue_block}; - const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; + IR::U1 cond{VisitExpr(ir, *stmt.cond)}; + if (!Settings::values.disable_shader_loop_safety_checks) { + const IR::U32 old_counter{ir.GetLoopSafetyVariable(this_loop_id)}; + const IR::U32 new_counter{ir.ISub(old_counter, ir.Imm32(1))}; + ir.SetLoopSafetyVariable(this_loop_id, new_counter); + + const IR::U1 safety_cond{ir.INotEqual(new_counter, ir.Imm32(0))}; + cond = ir.LogicalAnd(cond, safety_cond); + } + cond = ir.ConditionRef(cond); IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; loop_header_block->AddBranch(body_block); @@ -863,8 +891,14 @@ private: ObjectPool& block_pool; Environment& env; IR::AbstractSyntaxList& syntax_list; - // TODO: Make this constexpr when std::vector is constexpr + u32 loop_id{}; + +// TODO: C++20 Remove this when all compilers support constexpr std::vector +#if __cpp_lib_constexpr_vector >= 201907 + static constexpr Flow::Block dummy_flow_block; +#else const Flow::Block dummy_flow_block; +#endif }; } // Anonymous namespace diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index e54499ba5..a4ba393ef 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -48,73 +48,91 @@ struct GotoVariable : FlagTag { u32 index; }; +struct LoopSafetyVariable { + LoopSafetyVariable() = default; + explicit LoopSafetyVariable(u32 index_) : index{index_} {} + + auto operator<=>(const LoopSafetyVariable&) const noexcept = default; + + u32 index; +}; + struct IndirectBranchVariable { auto operator<=>(const IndirectBranchVariable&) const noexcept = default; }; -using Variant = std::variant; -using ValueMap = boost::container::flat_map>; +using Variant = + std::variant; +using ValueMap = boost::container::flat_map; struct DefTable { - const IR::Value& Def(IR::Block* block, IR::Reg variable) noexcept { + const IR::Value& Def(IR::Block* block, IR::Reg variable) { return block->SsaRegValue(variable); } - void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) { block->SetSsaRegValue(variable, value); } - const IR::Value& Def(IR::Block* block, IR::Pred variable) noexcept { + const IR::Value& Def(IR::Block* block, IR::Pred variable) { return preds[IR::PredIndex(variable)][block]; } - void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) { preds[IR::PredIndex(variable)].insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, GotoVariable variable) noexcept { + const IR::Value& Def(IR::Block* block, GotoVariable variable) { return goto_vars[variable.index][block]; } - void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) { goto_vars[variable.index].insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, IndirectBranchVariable) noexcept { + const IR::Value& Def(IR::Block* block, LoopSafetyVariable variable) { + return loop_safety_vars[variable.index][block]; + } + void SetDef(IR::Block* block, LoopSafetyVariable variable, const IR::Value& value) { + loop_safety_vars[variable.index].insert_or_assign(block, value); + } + + const IR::Value& Def(IR::Block* block, IndirectBranchVariable) { return indirect_branch_var[block]; } - void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) { indirect_branch_var.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, ZeroFlagTag) noexcept { + const IR::Value& Def(IR::Block* block, ZeroFlagTag) { return zero_flag[block]; } - void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) { zero_flag.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, SignFlagTag) noexcept { + const IR::Value& Def(IR::Block* block, SignFlagTag) { return sign_flag[block]; } - void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) { sign_flag.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, CarryFlagTag) noexcept { + const IR::Value& Def(IR::Block* block, CarryFlagTag) { return carry_flag[block]; } - void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) { carry_flag.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, OverflowFlagTag) noexcept { + const IR::Value& Def(IR::Block* block, OverflowFlagTag) { return overflow_flag[block]; } - void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) noexcept { + void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) { overflow_flag.insert_or_assign(block, value); } std::array preds; boost::container::flat_map goto_vars; + boost::container::flat_map loop_safety_vars; ValueMap indirect_branch_var; ValueMap zero_flag; ValueMap sign_flag; @@ -134,6 +152,10 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept { return IR::Opcode::UndefU1; } +IR::Opcode UndefOpcode(const LoopSafetyVariable&) noexcept { + return IR::Opcode::UndefU32; +} + IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { return IR::Opcode::UndefU32; } @@ -315,6 +337,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::SetGotoVariable: pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); break; + case IR::Opcode::SetLoopSafetyVariable: + pass.WriteVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block, inst.Arg(0)); + break; case IR::Opcode::SetIndirectBranchVariable: pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); break; @@ -343,6 +368,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetGotoVariable: inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); break; + case IR::Opcode::GetLoopSafetyVariable: + inst.ReplaceUsesWith(pass.ReadVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block)); + break; case IR::Opcode::GetIndirectBranchVariable: inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); break; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 8eb37a77a..bf063c047 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -467,7 +467,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv; - if (nv_device_diagnostics_config) { + if (Settings::values.enable_nsight_aftermath && nv_device_diagnostics_config) { nsight_aftermath_tracker = std::make_unique(); diagnostics_nv = { @@ -781,7 +781,7 @@ std::vector Device::LoadExtensions(bool requires_surface) { test(has_ext_shader_atomic_int64, VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME, false); test(has_khr_workgroup_memory_explicit_layout, VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME, false); - if (Settings::values.renderer_debug) { + if (Settings::values.enable_nsight_aftermath) { test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, true); } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index a5e032959..dc69574a9 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -824,6 +824,8 @@ void Config::ReadRendererValues() { if (global) { ReadBasicSetting(Settings::values.renderer_debug); + ReadBasicSetting(Settings::values.enable_nsight_aftermath); + ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); } qt_config->endGroup(); @@ -1353,6 +1355,8 @@ void Config::SaveRendererValues() { if (global) { WriteBasicSetting(Settings::values.renderer_debug); + WriteBasicSetting(Settings::values.enable_nsight_aftermath); + WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); } qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 8fceb3878..f7e29dbd7 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -45,8 +45,13 @@ void ConfigureDebug::SetConfiguration() { ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); ui->enable_cpu_debugging->setEnabled(runtime_lock); ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); + ui->enable_nsight_aftermath->setEnabled(runtime_lock); + ui->enable_nsight_aftermath->setChecked(Settings::values.enable_nsight_aftermath.GetValue()); ui->disable_macro_jit->setEnabled(runtime_lock); ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue()); + ui->disable_loop_safety_checks->setEnabled(runtime_lock); + ui->disable_loop_safety_checks->setChecked( + Settings::values.disable_shader_loop_safety_checks.GetValue()); ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); } @@ -61,6 +66,9 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); + Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); + Settings::values.disable_shader_loop_safety_checks = + ui->disable_loop_safety_checks->isChecked(); Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); Settings::values.extended_logging = ui->extended_logging->isChecked(); Debugger::ToggleConsole(); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 1260ad6f0..c8baf2921 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -125,6 +125,16 @@ + + + + When checked, it enables Nsight Aftermath crash dumps + + + Enable Nsight Aftermath + + + @@ -138,6 +148,16 @@ + + + + When checked, it executes shaders without loop logic changes + + + Disable Loop safety checks + + + @@ -252,11 +272,17 @@ log_filter_edit toggle_console + extended_logging open_log_button homebrew_args_edit enable_graphics_debugging + enable_nsight_aftermath + disable_macro_jit + disable_loop_safety_checks reporting_services quest_flag + use_debug_asserts + use_auto_stub diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 3e22fee37..763df6dd6 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -444,6 +444,8 @@ void Config::ReadValues() { // Renderer ReadSetting("Renderer", Settings::values.renderer_backend); ReadSetting("Renderer", Settings::values.renderer_debug); + ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); + ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); ReadSetting("Renderer", Settings::values.vulkan_device); ReadSetting("Renderer", Settings::values.fullscreen_mode); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 88d33ecab..a6ca7b6cd 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -221,6 +221,14 @@ backend = # 0 (default): Disabled, 1: Enabled debug = +# Enable Nsight Aftermath crash dumps +# 0 (default): Disabled, 1: Enabled +nsight_aftermath = + +# Disable shader loop safety checks, executing the shader without loop logic changes +# 0 (default): Disabled, 1: Enabled +disable_shader_loop_safety_checks = + # Which Vulkan physical device to use (defaults to 0) vulkan_device = -- 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/common/logging/filter.cpp | 4 ++++ src/common/logging/types.h | 4 ++++ 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 ++++---- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 8 ++++---- src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp | 6 +++--- src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 4 ++-- src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | 4 ++-- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 2 +- .../maxwell/translate/impl/internal_stage_buffer_entry_read.cpp | 2 +- .../frontend/maxwell/translate/impl/move_special_register.cpp | 8 ++++---- src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp | 2 +- 15 files changed, 38 insertions(+), 28 deletions(-) (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 4f2cc29e1..f055f0e11 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -144,6 +144,10 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Render, Software) \ SUB(Render, OpenGL) \ SUB(Render, Vulkan) \ + CLS(Shader) \ + SUB(Shader, SPIRV) \ + SUB(Shader, GLASM) \ + SUB(Shader, GLSL) \ CLS(Audio) \ SUB(Audio, DSP) \ SUB(Audio, Sink) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index 88b0e9c01..7ad0334fc 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -114,6 +114,10 @@ enum class Class : u8 { Render_Software, ///< Software renderer backend Render_OpenGL, ///< OpenGL backend Render_Vulkan, ///< Vulkan backend + Shader, ///< Shader recompiler + Shader_SPIRV, ///< Shader SPIR-V code generation + Shader_GLASM, ///< Shader GLASM code generation + Shader_GLSL, ///< Shader GLSL code generation Audio, ///< Audio emulation Audio_DSP, ///< The HLE implementation of the DSP Audio_Sink, ///< Emulator audio output backend 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); } } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index cba420cda..14a99750d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -294,7 +294,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit Id main_func) { const Info& info{program.info}; if (info.uses_fp32_denorms_flush && info.uses_fp32_denorms_preserve) { - // LOG_ERROR(HW_GPU, "Fp32 denorm flush and preserve on the same shader"); + LOG_ERROR(Shader_SPIRV, "Fp32 denorm flush and preserve on the same shader"); } else if (info.uses_fp32_denorms_flush) { if (profile.support_fp32_denorm_flush) { ctx.AddCapability(spv::Capability::DenormFlushToZero); @@ -307,7 +307,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit ctx.AddCapability(spv::Capability::DenormPreserve); ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 32U); } else { - // LOG_WARNING(HW_GPU, "Fp32 denorm preserve used in shader without host support"); + LOG_WARNING(Shader_SPIRV, "Fp32 denorm preserve used in shader without host support"); } } if (!profile.support_separate_denorm_behavior) { @@ -315,7 +315,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit return; } if (info.uses_fp16_denorms_flush && info.uses_fp16_denorms_preserve) { - // LOG_ERROR(HW_GPU, "Fp16 denorm flush and preserve on the same shader"); + LOG_ERROR(Shader_SPIRV, "Fp16 denorm flush and preserve on the same shader"); } else if (info.uses_fp16_denorms_flush) { if (profile.support_fp16_denorm_flush) { ctx.AddCapability(spv::Capability::DenormFlushToZero); @@ -328,7 +328,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit ctx.AddCapability(spv::Capability::DenormPreserve); ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); } else { - // LOG_WARNING(HW_GPU, "Fp16 denorm preserve used in shader without host support"); + LOG_WARNING(Shader_SPIRV, "Fp16 denorm preserve used in shader without host support"); } } } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 053800eb7..9af8bb9e1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -73,7 +73,7 @@ Id StorageAtomicU64(EmitContext& ctx, const IR::Value& binding, const IR::Value& const auto [scope, semantics]{AtomicArgs(ctx)}; return (ctx.*atomic_func)(ctx.U64, pointer, scope, semantics, value); } - // LOG_WARNING(..., "Int64 Atomics not supported, fallback to non-atomic"); + LOG_ERROR(Shader_SPIRV, "Int64 atomics not supported, fallback to non-atomic"); const Id pointer{StoragePointer(ctx, ctx.storage_types.U32x2, &StorageDefinitions::U32x2, binding, offset, sizeof(u32[2]))}; const Id original_value{ctx.OpBitcast(ctx.U64, ctx.OpLoad(ctx.U32[2], pointer))}; @@ -140,7 +140,7 @@ Id EmitSharedAtomicExchange64(EmitContext& ctx, Id offset, Id value) { const auto [scope, semantics]{AtomicArgs(ctx)}; return ctx.OpAtomicExchange(ctx.U64, pointer, scope, semantics, value); } - // LOG_WARNING("Int64 Atomics not supported, fallback to non-atomic"); + LOG_ERROR(Shader_SPIRV, "Int64 atomics not supported, fallback to non-atomic"); const Id pointer_1{SharedPointer(ctx, offset, 0)}; const Id pointer_2{SharedPointer(ctx, offset, 1)}; const Id value_1{ctx.OpLoad(ctx.U32[1], pointer_1)}; @@ -266,7 +266,7 @@ Id EmitStorageAtomicExchange64(EmitContext& ctx, const IR::Value& binding, const const auto [scope, semantics]{AtomicArgs(ctx)}; return ctx.OpAtomicExchange(ctx.U64, pointer, scope, semantics, value); } - // LOG_WARNING(..., "Int64 Atomics not supported, fallback to non-atomic"); + LOG_ERROR(Shader_SPIRV, "Int64 atomics not supported, fallback to non-atomic"); const Id pointer{StoragePointer(ctx, ctx.storage_types.U32x2, &StorageDefinitions::U32x2, binding, offset, sizeof(u32[2]))}; const Id original{ctx.OpBitcast(ctx.U64, ctx.OpLoad(ctx.U32[2], pointer))}; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index cf842e1e0..647804814 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -39,7 +39,7 @@ public: } const std::array values{offset.InstRecursive(), offset2.InstRecursive()}; if (!values[0]->AreAllArgsImmediates() || !values[1]->AreAllArgsImmediates()) { - // LOG_WARNING("Not all arguments in PTP are immediate, STUBBING"); + LOG_WARNING(Shader_SPIRV, "Not all arguments in PTP are immediate, ignoring"); return; } const IR::Opcode opcode{values[0]->GetOpcode()}; @@ -442,7 +442,7 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { const auto info{inst->Flags()}; if (info.image_format == ImageFormat::Typeless && !ctx.profile.support_typeless_image_loads) { - // LOG_WARNING(..., "Typeless image read not supported by host"); + LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host"); return ctx.ConstantNull(ctx.U32[4]); } return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 072a3b1bd..9e7eb3cb1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -131,7 +131,7 @@ void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { if (stream.IsImmediate()) { ctx.OpEmitStreamVertex(ctx.Def(stream)); } else { - // LOG_WARNING(..., "EmitVertex's stream is not constant"); + LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); ctx.OpEmitStreamVertex(ctx.u32_zero_value); } // Restore fixed pipeline point size after emitting the vertex @@ -142,7 +142,7 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { if (stream.IsImmediate()) { ctx.OpEndStreamPrimitive(ctx.Def(stream)); } else { - // LOG_WARNING(..., "EndPrimitive's stream is not constant"); + LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); ctx.OpEndStreamPrimitive(ctx.u32_zero_value); } } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 6c37af5e7..d2ac2acac 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -270,7 +270,7 @@ static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { case FlowTest::RGT: return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag())); case FlowTest::FCSM_TR: - // LOG_WARNING(ShaderDecompiler, "FCSM_TR CC State (Stubbed)"); + LOG_WARNING(Shader, "(STUBBED) FCSM_TR"); return ir.Imm1(false); case FlowTest::CSM_TA: case FlowTest::CSM_TR: diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index edd6220a8..9b85f8059 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -46,7 +46,7 @@ void TranslatorVisitor::ISBERD(u64 insn) { if (isberd.shift != Shift::Default) { throw NotImplementedException("Shift {}", isberd.shift.Value()); } - // LOG_WARNING(..., "ISBERD is stubbed"); + LOG_WARNING(Shader, "(STUBBED) called"); X(isberd.dest_reg, X(isberd.src_reg)); } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp index fe3cdfa96..20cb2674e 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp @@ -118,7 +118,7 @@ enum class SpecialRegister : u64 { case SpecialRegister::SR_THREAD_KILL: return IR::U32{ir.Select(ir.IsHelperInvocation(), ir.Imm32(-1), ir.Imm32(0))}; case SpecialRegister::SR_INVOCATION_INFO: - // LOG_WARNING(..., "SR_INVOCATION_INFO is stubbed"); + LOG_WARNING(Shader, "(STUBBED) SR_INVOCATION_INFO"); return ir.Imm32(0x00ff'0000); case SpecialRegister::SR_TID: { const IR::Value tid{ir.LocalInvocationId()}; @@ -140,10 +140,10 @@ enum class SpecialRegister : u64 { case SpecialRegister::SR_CTAID_Z: return ir.WorkgroupIdZ(); case SpecialRegister::SR_WSCALEFACTOR_XY: - // LOG_WARNING(..., "SR_WSCALEFACTOR_XY is stubbed"); + LOG_WARNING(Shader, "(STUBBED) SR_WSCALEFACTOR_XY"); return ir.Imm32(Common::BitCast(1.0f)); case SpecialRegister::SR_WSCALEFACTOR_Z: - // LOG_WARNING(..., "SR_WSCALEFACTOR_Z is stubbed"); + LOG_WARNING(Shader, "(STUBBED) SR_WSCALEFACTOR_Z"); return ir.Imm32(Common::BitCast(1.0f)); case SpecialRegister::SR_LANEID: return ir.LaneId(); @@ -160,7 +160,7 @@ enum class SpecialRegister : u64 { case SpecialRegister::SR_Y_DIRECTION: return ir.BitCast(ir.YDirection()); case SpecialRegister::SR_AFFINITY: - // LOG_WARNING(..., "SR_AFFINITY is stubbed"); + LOG_WARNING(Shader, "(STUBBED) SR_AFFINITY"); return ir.Imm32(0); // This is the default value hardware returns. default: throw NotImplementedException("S2R special register {}", special_register); diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp index 0793611ff..7ce370f09 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp @@ -48,7 +48,7 @@ void TranslatorVisitor::VOTE(u64 insn) { } void TranslatorVisitor::VOTE_vtg(u64) { - // LOG_WARNING(ShaderDecompiler, "VOTE.VTG: Stubbed!"); + LOG_WARNING(Shader, "(STUBBED) called"); } } // namespace Shader::Maxwell -- 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/CMakeLists.txt | 1 + .../backend/glasm/emit_context.cpp | 1 + src/shader_recompiler/backend/glasm/emit_glasm.cpp | 1 + src/shader_recompiler/backend/glasm/emit_glasm.h | 1 + .../backend/glasm/emit_glasm_memory.cpp | 2 +- .../backend/glsl/emit_context.cpp | 1 + src/shader_recompiler/backend/glsl/emit_glsl.h | 1 + .../backend/glsl/emit_glsl_instructions.h | 3 - src/shader_recompiler/backend/spirv/emit_context.h | 1 + src/shader_recompiler/profile.h | 72 ------------------- src/shader_recompiler/runtime_info.h | 83 ++++++++++++++++++++++ src/video_core/renderer_opengl/gl_shader_cache.h | 1 + src/video_core/transform_feedback.h | 2 +- 13 files changed, 93 insertions(+), 77 deletions(-) create mode 100644 src/shader_recompiler/runtime_info.h (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 164e94071..f6719ad9d 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -226,6 +226,7 @@ add_library(shader_recompiler STATIC object_pool.h profile.h program_header.h + runtime_info.h shader_info.h ) 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 { diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 54aa88b63..93057ebb9 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp @@ -6,6 +6,7 @@ #include "shader_recompiler/backend/glsl/emit_context.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::GLSL { namespace { diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.h b/src/shader_recompiler/backend/glsl/emit_glsl.h index fe221fa7c..20e5719e6 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl.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::GLSL { diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index 9e812dabb..df28036e4 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -18,9 +18,6 @@ class Value; namespace Shader::Backend::GLSL { class EmitContext; -inline void EmitSetLoopSafetyVariable(EmitContext&) {} -inline void EmitGetLoopSafetyVariable(EmitContext&) {} - #define NotImplemented() throw NotImplementedException("GLSL instruction {}", __func__) // Microinstruction emitters diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 961c9180c..527685fb8 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -12,6 +12,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" #include "shader_recompiler/shader_info.h" namespace Shader::Backend::SPIRV { diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index a3c412a0f..d46be1638 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -4,59 +4,10 @@ #pragma once -#include -#include -#include - #include "common/common_types.h" namespace Shader { -enum class AttributeType : u8 { - Float, - SignedInt, - UnsignedInt, - Disabled, -}; - -enum class InputTopology { - Points, - Lines, - LinesAdjacency, - Triangles, - TrianglesAdjacency, -}; - -enum class CompareFunction { - Never, - Less, - Equal, - LessThanEqual, - Greater, - NotEqual, - GreaterThanEqual, - Always, -}; - -enum class TessPrimitive { - Isolines, - Triangles, - Quads, -}; - -enum class TessSpacing { - Equal, - FractionalOdd, - FractionalEven, -}; - -struct TransformFeedbackVarying { - u32 buffer{}; - u32 stride{}; - u32 offset{}; - u32 components{}; -}; - struct Profile { u32 supported_spirv{0x00010000}; @@ -114,27 +65,4 @@ struct Profile { bool ignore_nan_fp_comparisons{}; }; -struct RuntimeInfo { - std::array generic_input_types{}; - bool convert_depth_mode{}; - bool force_early_z{}; - - TessPrimitive tess_primitive{}; - TessSpacing tess_spacing{}; - bool tess_clockwise{}; - - InputTopology input_topology{}; - - std::optional fixed_state_point_size; - std::optional alpha_test_func; - float alpha_test_reference{}; - - // Static y negate value - bool y_negate{}; - // Use storage buffers instead of global pointers on GLASM - bool glasm_use_storage_buffers{}; - - std::vector xfb_varyings; -}; - } // namespace Shader diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h new file mode 100644 index 000000000..d4b047b4d --- /dev/null +++ b/src/shader_recompiler/runtime_info.h @@ -0,0 +1,83 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "common/common_types.h" + +namespace Shader { + +enum class AttributeType : u8 { + Float, + SignedInt, + UnsignedInt, + Disabled, +}; + +enum class InputTopology { + Points, + Lines, + LinesAdjacency, + Triangles, + TrianglesAdjacency, +}; + +enum class CompareFunction { + Never, + Less, + Equal, + LessThanEqual, + Greater, + NotEqual, + GreaterThanEqual, + Always, +}; + +enum class TessPrimitive { + Isolines, + Triangles, + Quads, +}; + +enum class TessSpacing { + Equal, + FractionalOdd, + FractionalEven, +}; + +struct TransformFeedbackVarying { + u32 buffer{}; + u32 stride{}; + u32 offset{}; + u32 components{}; +}; + +struct RuntimeInfo { + std::array generic_input_types{}; + bool convert_depth_mode{}; + bool force_early_z{}; + + TessPrimitive tess_primitive{}; + TessSpacing tess_spacing{}; + bool tess_clockwise{}; + + InputTopology input_topology{}; + + std::optional fixed_state_point_size; + std::optional alpha_test_func; + float alpha_test_reference{}; + + // Static y negate value + bool y_negate{}; + // Use storage buffers instead of global pointers on GLASM + bool glasm_use_storage_buffers{}; + + std::vector xfb_varyings; +}; + +} // namespace Shader diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 6952a1f2c..ff5707119 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -16,6 +16,7 @@ #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/host_translate_info.h" #include "shader_recompiler/object_pool.h" +#include "shader_recompiler/profile.h" #include "video_core/engines/shader_type.h" #include "video_core/renderer_opengl/gl_compute_pipeline.h" #include "video_core/renderer_opengl/gl_graphics_pipeline.h" diff --git a/src/video_core/transform_feedback.h b/src/video_core/transform_feedback.h index 6832c6db1..8f6946d65 100644 --- a/src/video_core/transform_feedback.h +++ b/src/video_core/transform_feedback.h @@ -8,7 +8,7 @@ #include #include "common/common_types.h" -#include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" #include "video_core/engines/maxwell_3d.h" namespace VideoCommon { -- 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 ----- src/shader_recompiler/backend/glsl/emit_context.h | 2 ++ src/shader_recompiler/backend/glsl/emit_glsl.cpp | 11 ++++++- .../backend/glsl/emit_glsl_instructions.h | 2 -- .../backend/glsl/emit_glsl_not_implemented.cpp | 8 ----- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 19 ++++++++++- .../backend/spirv/emit_spirv_context_get_set.cpp | 8 ----- .../backend/spirv/emit_spirv_instructions.h | 2 -- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 8 ----- src/shader_recompiler/frontend/ir/ir_emitter.h | 3 -- src/shader_recompiler/frontend/ir/opcodes.inc | 2 -- .../frontend/maxwell/structured_control_flow.cpp | 37 +++------------------- src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 32 ++----------------- 16 files changed, 54 insertions(+), 108 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(); } diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h index 8fa87c02c..ecdf6e5bc 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.h +++ b/src/shader_recompiler/backend/glsl/emit_context.h @@ -153,6 +153,8 @@ public: std::vector images; std::array, 32> output_generics{}; + u32 num_safety_loop_vars{}; + bool uses_y_direction{}; bool uses_cc_carry{}; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index ff869923f..32c4f1da2 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -6,6 +6,7 @@ #include #include "common/alignment.h" +#include "common/settings.h" #include "shader_recompiler/backend/glsl/emit_context.h" #include "shader_recompiler/backend/glsl/emit_glsl.h" #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" @@ -156,7 +157,12 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { ctx.Add("for(;;){{"); break; case IR::AbstractSyntaxNode::Type::Repeat: - ctx.Add("if(!{}){{break;}}}}", ctx.var_alloc.Consume(node.data.repeat.cond)); + if (Settings::values.disable_shader_loop_safety_checks) { + ctx.Add("if(!{}){{break;}}}}", ctx.var_alloc.Consume(node.data.repeat.cond)); + } else { + ctx.Add("if(--loop{}<0 || !{}){{break;}}}}", ctx.num_safety_loop_vars++, + ctx.var_alloc.Consume(node.data.repeat.cond)); + } break; default: throw NotImplementedException("AbstractSyntaxNode Type {}", node.type); @@ -198,6 +204,9 @@ void DefineVariables(const EmitContext& ctx, std::string& header) { ctx.var_alloc.Representation(index, type), type_name); } } + for (u32 i = 0; i < ctx.num_safety_loop_vars; ++i) { + header += fmt::format("int loop{}=0x2000;", i); + } } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index df28036e4..6a30785bb 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -44,8 +44,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, const IR::Value& offset); void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp index 0a28a1ffc..f420fe388 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp @@ -46,14 +46,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { NotImplemented(); } -void EmitSetLoopSafetyVariable(EmitContext& ctx) { - NotImplemented(); -} - -void EmitGetLoopSafetyVariable(EmitContext& ctx) { - NotImplemented(); -} - void EmitGetZFlag(EmitContext& ctx) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index fd59b4d0a..278c262f8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -8,6 +8,7 @@ #include #include +#include "common/settings.h" #include "shader_recompiler/backend/spirv/emit_spirv.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/frontend/ir/basic_block.h" @@ -151,9 +152,25 @@ void Traverse(EmitContext& ctx, IR::Program& program) { } break; case IR::AbstractSyntaxNode::Type::Repeat: { + Id cond{ctx.Def(node.data.repeat.cond)}; + if (!Settings::values.disable_shader_loop_safety_checks) { + const Id pointer_type{ctx.TypePointer(spv::StorageClass::Private, ctx.U32[1])}; + const Id safety_counter{ctx.AddGlobalVariable( + pointer_type, spv::StorageClass::Private, ctx.Const(0x2000u))}; + if (ctx.profile.supported_spirv >= 0x00010400) { + ctx.interfaces.push_back(safety_counter); + } + const Id old_counter{ctx.OpLoad(ctx.U32[1], safety_counter)}; + const Id new_counter{ctx.OpISub(ctx.U32[1], old_counter, ctx.Const(1u))}; + ctx.OpStore(safety_counter, new_counter); + + const Id safety_cond{ + ctx.OpSGreaterThanEqual(ctx.U1, new_counter, ctx.u32_zero_value)}; + cond = ctx.OpLogicalAnd(ctx.U1, cond, safety_cond); + } const Id loop_header_label{node.data.repeat.loop_header->Definition()}; const Id merge_label{node.data.repeat.merge->Definition()}; - ctx.OpBranchConditional(ctx.Def(node.data.repeat.cond), loop_header_label, merge_label); + ctx.OpBranchConditional(cond, loop_header_label, merge_label); break; } case IR::AbstractSyntaxNode::Type::Return: diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 2e364baec..85bd72389 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -198,14 +198,6 @@ void EmitGetIndirectBranchVariable(EmitContext&) { throw LogicError("Unreachable instruction"); } -void EmitSetLoopSafetyVariable(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - -void EmitGetLoopSafetyVariable(EmitContext&) { - throw LogicError("Unreachable instruction"); -} - Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) { const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset)}; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index e3e5b03fe..1181e7b4f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -43,8 +43,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); Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index d2ac2acac..2e75208e6 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -147,14 +147,6 @@ void IREmitter::SetIndirectBranchVariable(const U32& value) { Inst(Opcode::SetIndirectBranchVariable, value); } -U32 IREmitter::GetLoopSafetyVariable(u32 id) { - return Inst(Opcode::GetLoopSafetyVariable, id); -} - -void IREmitter::SetLoopSafetyVariable(u32 id, const U32& counter) { - Inst(Opcode::SetLoopSafetyVariable, id, counter); -} - U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { return Inst(Opcode::GetCbufU32, binding, byte_offset); } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 7caab1f61..bb3500c54 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -55,9 +55,6 @@ public: [[nodiscard]] U32 GetIndirectBranchVariable(); void SetIndirectBranchVariable(const U32& value); - [[nodiscard]] U32 GetLoopSafetyVariable(u32 id); - void SetLoopSafetyVariable(u32 id, const U32& counter); - [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, bool is_signed); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index e87aeddd5..8a8d0d759 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -32,8 +32,6 @@ OPCODE(GetGotoVariable, U1, U32, OPCODE(SetGotoVariable, Void, U32, U1, ) OPCODE(GetIndirectBranchVariable, U32, ) OPCODE(SetIndirectBranchVariable, Void, U32, ) -OPCODE(GetLoopSafetyVariable, U32, U32, ) -OPCODE(SetLoopSafetyVariable, Void, U32, U32, ) OPCODE(GetCbufU8, U32, U32, U32, ) OPCODE(GetCbufS8, U32, U32, U32, ) OPCODE(GetCbufU16, U32, U32, U32, ) diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 0fb870a69..10d05dc4c 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -15,7 +15,6 @@ #include -#include "common/settings.h" #include "shader_recompiler/environment.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/ir_emitter.h" @@ -663,7 +662,7 @@ public: Visit(root_stmt, nullptr, nullptr); IR::Block& first_block{*syntax_list.front().data.block}; - IR::IREmitter ir = IR::IREmitter(first_block, first_block.begin()); + IR::IREmitter ir(first_block, first_block.begin()); ir.Prologue(); } @@ -741,27 +740,8 @@ private: } case StatementType::Loop: { IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; - const u32 this_loop_id{loop_id++}; - - if (Settings::values.disable_shader_loop_safety_checks) { - if (current_block) { - current_block->AddBranch(loop_header_block); - } - } else { - IR::Block* const init_block{block_pool.Create(inst_pool)}; - IR::IREmitter ir{*init_block}; - - static constexpr u32 SAFETY_THRESHOLD = 0x1000; - ir.SetLoopSafetyVariable(this_loop_id, ir.Imm32(SAFETY_THRESHOLD)); - - if (current_block) { - current_block->AddBranch(init_block); - } - init_block->AddBranch(loop_header_block); - - auto& init_node{syntax_list.emplace_back()}; - init_node.type = IR::AbstractSyntaxNode::Type::Block; - init_node.data.block = init_block; + if (current_block) { + current_block->AddBranch(loop_header_block); } auto& header_node{syntax_list.emplace_back()}; header_node.type = IR::AbstractSyntaxNode::Type::Block; @@ -779,16 +759,7 @@ private: // The continue block is located at the end of the loop IR::IREmitter ir{*continue_block}; - IR::U1 cond{VisitExpr(ir, *stmt.cond)}; - if (!Settings::values.disable_shader_loop_safety_checks) { - const IR::U32 old_counter{ir.GetLoopSafetyVariable(this_loop_id)}; - const IR::U32 new_counter{ir.ISub(old_counter, ir.Imm32(1))}; - ir.SetLoopSafetyVariable(this_loop_id, new_counter); - - const IR::U1 safety_cond{ir.INotEqual(new_counter, ir.Imm32(0))}; - cond = ir.LogicalAnd(cond, safety_cond); - } - cond = ir.ConditionRef(cond); + const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; loop_header_block->AddBranch(body_block); diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index fff25c4a2..dcaced83f 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -48,22 +48,12 @@ struct GotoVariable : FlagTag { u32 index; }; -struct LoopSafetyVariable { - LoopSafetyVariable() = default; - explicit LoopSafetyVariable(u32 index_) : index{index_} {} - - auto operator<=>(const LoopSafetyVariable&) const noexcept = default; - - u32 index; -}; - struct IndirectBranchVariable { auto operator<=>(const IndirectBranchVariable&) const noexcept = default; }; -using Variant = - std::variant; +using Variant = std::variant; using ValueMap = boost::container::flat_map; struct DefTable { @@ -88,13 +78,6 @@ struct DefTable { goto_vars[variable.index].insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, LoopSafetyVariable variable) { - return loop_safety_vars[variable.index][block]; - } - void SetDef(IR::Block* block, LoopSafetyVariable variable, const IR::Value& value) { - loop_safety_vars[variable.index].insert_or_assign(block, value); - } - const IR::Value& Def(IR::Block* block, IndirectBranchVariable) { return indirect_branch_var[block]; } @@ -132,7 +115,6 @@ struct DefTable { std::array preds; boost::container::flat_map goto_vars; - boost::container::flat_map loop_safety_vars; ValueMap indirect_branch_var; ValueMap zero_flag; ValueMap sign_flag; @@ -152,10 +134,6 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept { return IR::Opcode::UndefU1; } -IR::Opcode UndefOpcode(const LoopSafetyVariable&) noexcept { - return IR::Opcode::UndefU32; -} - IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { return IR::Opcode::UndefU32; } @@ -337,9 +315,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::SetGotoVariable: pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); break; - case IR::Opcode::SetLoopSafetyVariable: - pass.WriteVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); - break; case IR::Opcode::SetIndirectBranchVariable: pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); break; @@ -368,9 +343,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetGotoVariable: inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); break; - case IR::Opcode::GetLoopSafetyVariable: - inst.ReplaceUsesWith(pass.ReadVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block)); - break; case IR::Opcode::GetIndirectBranchVariable: inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); break; -- 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 ---- src/shader_recompiler/backend/glsl/emit_glsl_instructions.h | 1 - src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp | 4 ---- src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | 1 - src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | 4 ---- src/shader_recompiler/frontend/ir/ir_emitter.cpp | 11 ++--------- src/shader_recompiler/frontend/ir/ir_emitter.h | 2 +- src/shader_recompiler/frontend/ir/opcodes.inc | 1 - 9 files changed, 3 insertions(+), 26 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); } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index 6a30785bb..5936d086f 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -365,7 +365,6 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin 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, IR::Inst& inst, std::string_view base, std::string_view shift); void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view base, diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp index fcc9afd85..40f453593 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp @@ -80,10 +80,6 @@ void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { ctx.AddU32("{}=abs(int({}));", inst, value); } -void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value) { - ctx.AddU64("{}=abs(int64_t({}));", inst, value); -} - void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base, std::string_view shift) { ctx.AddU32("{}={}<<{};", inst, base, shift); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 1181e7b4f..f99c02848 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -284,7 +284,6 @@ Id EmitIMul32(EmitContext& ctx, Id a, Id b); Id EmitINeg32(EmitContext& ctx, Id value); Id EmitINeg64(EmitContext& ctx, Id value); Id EmitIAbs32(EmitContext& ctx, Id value); -Id EmitIAbs64(EmitContext& ctx, Id value); Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift); Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index 06ab23b1d..3501d7495 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -84,10 +84,6 @@ Id EmitIAbs32(EmitContext& ctx, Id value) { return ctx.OpSAbs(ctx.U32[1], value); } -Id EmitIAbs64(EmitContext& ctx, Id value) { - return ctx.OpSAbs(ctx.U64, value); -} - Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 2e75208e6..13159a68d 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -1152,15 +1152,8 @@ U32U64 IREmitter::INeg(const U32U64& value) { } } -U32U64 IREmitter::IAbs(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::IAbs32, value); - case Type::U64: - return Inst(Opcode::IAbs64, value); - default: - ThrowInvalidType(value.Type()); - } +U32 IREmitter::IAbs(const U32& value) { + return Inst(Opcode::IAbs32, value); } U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index bb3500c54..53f7b3b06 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -208,7 +208,7 @@ public: [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); [[nodiscard]] U32 IMul(const U32& a, const U32& b); [[nodiscard]] U32U64 INeg(const U32U64& value); - [[nodiscard]] U32U64 IAbs(const U32U64& value); + [[nodiscard]] U32 IAbs(const U32& value); [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 8a8d0d759..9af750283 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -289,7 +289,6 @@ OPCODE(IMul32, U32, U32, OPCODE(INeg32, U32, U32, ) OPCODE(INeg64, U64, U64, ) OPCODE(IAbs32, U32, U32, ) -OPCODE(IAbs64, U64, U64, ) OPCODE(ShiftLeftLogical32, U32, U32, U32, ) OPCODE(ShiftLeftLogical64, U64, U64, U32, ) OPCODE(ShiftRightLogical32, U32, U32, U32, ) -- 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/CMakeLists.txt | 1 + .../backend/glasm/emit_context.cpp | 15 +- src/shader_recompiler/backend/glasm/emit_glasm.cpp | 6 +- .../backend/glasm/emit_glasm_context_get_set.cpp | 6 +- .../backend/glsl/emit_context.cpp | 58 +++--- src/shader_recompiler/backend/glsl/emit_glsl.cpp | 2 +- .../backend/glsl/emit_glsl_context_get_set.cpp | 2 +- .../backend/glsl/emit_glsl_special.cpp | 4 +- .../backend/spirv/emit_context.cpp | 97 +++++----- src/shader_recompiler/backend/spirv/emit_context.h | 2 +- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 19 +- .../backend/spirv/emit_spirv_context_get_set.cpp | 2 +- src/shader_recompiler/environment.h | 5 + src/shader_recompiler/frontend/ir/attribute.h | 6 + src/shader_recompiler/frontend/ir/program.h | 1 + .../frontend/maxwell/translate_program.cpp | 18 +- .../ir_opt/collect_shader_info_pass.cpp | 202 +++++++-------------- src/shader_recompiler/profile.h | 1 + src/shader_recompiler/program_header.h | 62 +++---- src/shader_recompiler/runtime_info.h | 3 +- src/shader_recompiler/shader_info.h | 37 +--- src/shader_recompiler/varying_state.h | 69 +++++++ src/video_core/engines/maxwell_3d.h | 7 +- src/video_core/renderer_opengl/gl_shader_cache.cpp | 7 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 6 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 16 +- src/video_core/shader_environment.cpp | 10 +- src/video_core/vulkan_common/vulkan_device.cpp | 6 + src/video_core/vulkan_common/vulkan_device.h | 6 + 29 files changed, 345 insertions(+), 331 deletions(-) create mode 100644 src/shader_recompiler/varying_state.h (limited to 'src/shader_recompiler/backend/glasm') diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 3b5708cb9..b5b7e5e83 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -229,6 +229,7 @@ add_library(shader_recompiler STATIC program_header.h runtime_info.h shader_info.h + varying_state.h ) target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit) 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))); diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 14c009535..0d7f7bc3b 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp @@ -212,22 +212,22 @@ std::string_view OutputPrimitive(OutputTopology topology) { } void SetupLegacyOutPerVertex(EmitContext& ctx, std::string& header) { - if (!ctx.info.stores_legacy_varyings) { + if (!ctx.info.stores.Legacy()) { return; } - if (ctx.info.stores_fixed_fnc_textures) { + if (ctx.info.stores.FixedFunctionTexture()) { header += "vec4 gl_TexCoord[8];"; } - if (ctx.info.stores_color_front_diffuse) { + if (ctx.info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { header += "vec4 gl_FrontColor;"; } - if (ctx.info.stores_color_front_specular) { + if (ctx.info.stores.AnyComponent(IR::Attribute::ColorFrontSpecularR)) { header += "vec4 gl_FrontSecondaryColor;"; } - if (ctx.info.stores_color_back_diffuse) { + if (ctx.info.stores.AnyComponent(IR::Attribute::ColorBackDiffuseR)) { header += "vec4 gl_BackColor;"; } - if (ctx.info.stores_color_back_specular) { + if (ctx.info.stores.AnyComponent(IR::Attribute::ColorBackSpecularR)) { header += "vec4 gl_BackSecondaryColor;"; } } @@ -237,32 +237,32 @@ void SetupOutPerVertex(EmitContext& ctx, std::string& header) { return; } header += "out gl_PerVertex{vec4 gl_Position;"; - if (ctx.info.stores_point_size) { + if (ctx.info.stores[IR::Attribute::PointSize]) { header += "float gl_PointSize;"; } - if (ctx.info.stores_clip_distance) { + if (ctx.info.stores.ClipDistances()) { header += "float gl_ClipDistance[];"; } - if (ctx.info.stores_viewport_index && ctx.profile.support_viewport_index_layer_non_geometry && - ctx.stage != Stage::Geometry) { + if (ctx.info.stores[IR::Attribute::ViewportIndex] && + ctx.profile.support_viewport_index_layer_non_geometry && ctx.stage != Stage::Geometry) { header += "int gl_ViewportIndex;"; } SetupLegacyOutPerVertex(ctx, header); header += "};"; - if (ctx.info.stores_viewport_index && ctx.stage == Stage::Geometry) { + if (ctx.info.stores[IR::Attribute::ViewportIndex] && ctx.stage == Stage::Geometry) { header += "out int gl_ViewportIndex;"; } } void SetupLegacyInPerFragment(EmitContext& ctx, std::string& header) { - if (!ctx.info.loads_legacy_varyings) { + if (!ctx.info.loads.Legacy()) { return; } header += "in gl_PerFragment{"; - if (ctx.info.loads_fixed_fnc_textures) { + if (ctx.info.loads.FixedFunctionTexture()) { header += "vec4 gl_TexCoord[8];"; } - if (ctx.info.loads_color_front_diffuse) { + if (ctx.info.loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { header += "vec4 gl_Color;"; } header += "};"; @@ -325,14 +325,13 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile SetupOutPerVertex(*this, header); SetupLegacyInPerFragment(*this, header); - for (size_t index = 0; index < info.input_generics.size(); ++index) { - const auto& generic{info.input_generics[index]}; - if (!generic.used || !runtime_info.previous_stage_stores_generic[index]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) { continue; } - header += - fmt::format("layout(location={}){}in vec4 in_attr{}{};", index, - InterpDecorator(generic.interpolation), index, InputArrayDecorator(stage)); + header += fmt::format("layout(location={}){}in vec4 in_attr{}{};", index, + InterpDecorator(info.interpolation[index]), index, + InputArrayDecorator(stage)); } for (size_t index = 0; index < info.uses_patches.size(); ++index) { if (!info.uses_patches[index]) { @@ -349,11 +348,10 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile header += fmt::format("layout(location={})out vec4 frag_color{};", index, index); } } - for (size_t index = 0; index < info.stores_generics.size(); ++index) { - if (!info.stores_generics[index]) { - continue; + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (info.stores.Generic(index)) { + DefineGenericOutput(index, program.invocations); } - DefineGenericOutput(index, program.invocations); } DefineConstantBuffers(bindings); DefineStorageBuffers(bindings); @@ -398,14 +396,14 @@ void EmitContext::SetupExtensions() { header += "#extension GL_NV_shader_thread_shuffle : enable\n"; } } - if ((info.stores_viewport_index || info.stores_layer) && + if ((info.stores[IR::Attribute::ViewportIndex] || info.stores[IR::Attribute::Layer]) && profile.support_viewport_index_layer_non_geometry && stage != Stage::Geometry) { header += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; } if (info.uses_sparse_residency && profile.support_gl_sparse_textures) { header += "#extension GL_ARB_sparse_texture2 : enable\n"; } - if (info.stores_viewport_mask && profile.support_viewport_mask) { + if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) { header += "#extension GL_NV_viewport_array2 : enable\n"; } if (info.uses_typeless_image_reads) { @@ -535,20 +533,20 @@ void EmitContext::DefineHelperFunctions() { fmt::format("float IndexedAttrLoad(int offset{}){{int base_index=offset>>2;uint " "masked_index=uint(base_index)&3u;switch(base_index>>2){{", vertex_arg)}; - if (info.loads_position) { + if (info.loads.AnyComponent(IR::Attribute::PositionX)) { const auto position_idx{is_array ? "gl_in[vertex]." : ""}; func += fmt::format("case {}:return {}{}[masked_index];", static_cast(IR::Attribute::PositionX) >> 2, position_idx, position_name); } const u32 base_attribute_value = static_cast(IR::Attribute::Generic0X) >> 2; - for (u32 i = 0; i < info.input_generics.size(); ++i) { - if (!info.input_generics[i].used) { + for (u32 index = 0; index < IR::NUM_GENERICS; ++index) { + if (!info.loads.Generic(index)) { continue; } const auto vertex_idx{is_array ? "[vertex]" : ""}; func += fmt::format("case {}:return in_attr{}{}[masked_index];", - base_attribute_value + i, i, vertex_idx); + base_attribute_value + index, index, vertex_idx); } func += "default: return 0.0;}}"; header += func; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index 32c4f1da2..8deaf5760 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -171,7 +171,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } std::string GlslVersionSpecifier(const EmitContext& ctx) { - if (ctx.uses_y_direction || ctx.info.stores_legacy_varyings || ctx.info.loads_legacy_varyings) { + if (ctx.uses_y_direction || ctx.info.stores.Legacy() || ctx.info.loads.Legacy()) { return " compatibility"; } return ""; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index 3d2ba2eee..16e2a8502 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp @@ -179,7 +179,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, const char swizzle{"xyzw"[element]}; if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - if (!ctx.runtime_info.previous_stage_stores_generic[index]) { + if (!ctx.runtime_info.previous_stage_stores.Generic(index)) { ctx.AddF32("{}=0.f;", inst, attr); return; } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp index 6420aaa21..298881c7b 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp @@ -20,8 +20,8 @@ void InitializeOutputVaryings(EmitContext& ctx) { if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) { ctx.Add("gl_Position=vec4(0,0,0,1);"); } - for (size_t index = 0; index < ctx.info.stores_generics.size(); ++index) { - if (!ctx.info.stores_generics[index]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (!ctx.info.stores.Generic(index)) { continue; } const auto& info_array{ctx.output_generics.at(index)}; diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 4c6501129..af4fb0c69 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -557,7 +557,7 @@ void EmitContext::DefineCommonConstants() { } void EmitContext::DefineInterfaces(const IR::Program& program) { - DefineInputs(program.info); + DefineInputs(program); DefineOutputs(program); } @@ -693,16 +693,16 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; std::vector literals; std::vector labels; - if (info.loads_position) { + if (info.loads.AnyComponent(IR::Attribute::PositionX)) { literals.push_back(static_cast(IR::Attribute::PositionX) >> 2); labels.push_back(OpLabel()); } const u32 base_attribute_value = static_cast(IR::Attribute::Generic0X) >> 2; - for (u32 i = 0; i < info.input_generics.size(); ++i) { - if (!info.input_generics[i].used) { + for (u32 index = 0; index < static_cast(IR::NUM_GENERICS); ++index) { + if (!info.loads.Generic(index)) { continue; } - literals.push_back(base_attribute_value + i); + literals.push_back(base_attribute_value + index); labels.push_back(OpLabel()); } OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); @@ -710,7 +710,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { AddLabel(default_label); OpReturnValue(Const(0.0f)); size_t label_index{0}; - if (info.loads_position) { + if (info.loads.AnyComponent(IR::Attribute::PositionX)) { AddLabel(labels[label_index]); const Id pointer{is_array ? OpAccessChain(input_f32, input_position, vertex, masked_index) @@ -719,18 +719,18 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { OpReturnValue(result); ++label_index; } - for (size_t i = 0; i < info.input_generics.size(); i++) { - if (!info.input_generics[i].used) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (!info.loads.Generic(index)) { continue; } AddLabel(labels[label_index]); - const auto type{AttrTypes(*this, static_cast(i))}; + const auto type{AttrTypes(*this, static_cast(index))}; if (!type) { OpReturnValue(Const(0.0f)); ++label_index; continue; } - const Id generic_id{input_generics.at(i)}; + const Id generic_id{input_generics.at(index)}; const Id pointer{is_array ? OpAccessChain(type->pointer, generic_id, vertex, masked_index) : OpAccessChain(type->pointer, generic_id, masked_index)}; @@ -758,19 +758,19 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; std::vector literals; std::vector labels; - if (info.stores_position) { + if (info.stores.AnyComponent(IR::Attribute::PositionX)) { literals.push_back(static_cast(IR::Attribute::PositionX) >> 2); labels.push_back(OpLabel()); } const u32 base_attribute_value = static_cast(IR::Attribute::Generic0X) >> 2; - for (size_t i = 0; i < info.stores_generics.size(); i++) { - if (!info.stores_generics[i]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (!info.stores.Generic(index)) { continue; } - literals.push_back(base_attribute_value + static_cast(i)); + literals.push_back(base_attribute_value + static_cast(index)); labels.push_back(OpLabel()); } - if (info.stores_clip_distance) { + if (info.stores.ClipDistances()) { literals.push_back(static_cast(IR::Attribute::ClipDistance0) >> 2); labels.push_back(OpLabel()); literals.push_back(static_cast(IR::Attribute::ClipDistance4) >> 2); @@ -781,28 +781,28 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { AddLabel(default_label); OpReturn(); size_t label_index{0}; - if (info.stores_position) { + if (info.stores.AnyComponent(IR::Attribute::PositionX)) { AddLabel(labels[label_index]); const Id pointer{OpAccessChain(output_f32, output_position, masked_index)}; OpStore(pointer, store_value); OpReturn(); ++label_index; } - for (size_t i = 0; i < info.stores_generics.size(); ++i) { - if (!info.stores_generics[i]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (!info.stores.Generic(index)) { continue; } - if (output_generics[i][0].num_components != 4) { + if (output_generics[index][0].num_components != 4) { throw NotImplementedException("Physical stores and transform feedbacks"); } AddLabel(labels[label_index]); - const Id generic_id{output_generics[i][0].id}; + const Id generic_id{output_generics[index][0].id}; const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)}; OpStore(pointer, store_value); OpReturn(); ++label_index; } - if (info.stores_clip_distance) { + if (info.stores.ClipDistances()) { AddLabel(labels[label_index]); const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; OpStore(pointer, store_value); @@ -1146,7 +1146,10 @@ void EmitContext::DefineImages(const Info& info, u32& binding) { } } -void EmitContext::DefineInputs(const Info& info) { +void EmitContext::DefineInputs(const IR::Program& program) { + const Info& info{program.info}; + const VaryingState loads{info.loads.mask | info.passthrough.mask}; + if (info.uses_workgroup_id) { workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId); } @@ -1183,15 +1186,20 @@ void EmitContext::DefineInputs(const Info& info) { fswzadd_lut_b = ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one); } - if (info.loads_primitive_id) { + if (loads[IR::Attribute::PrimitiveId]) { primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId); } - if (info.loads_position) { + if (loads.AnyComponent(IR::Attribute::PositionX)) { const bool is_fragment{stage != Stage::Fragment}; const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; input_position = DefineInput(*this, F32[4], true, built_in); + if (profile.support_geometry_shader_passthrough) { + if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) { + Decorate(input_position, spv::Decoration::PassthroughNV); + } + } } - if (info.loads_instance_id) { + if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); } else { @@ -1199,7 +1207,7 @@ void EmitContext::DefineInputs(const Info& info) { base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); } } - if (info.loads_vertex_id) { + if (loads[IR::Attribute::VertexId]) { if (profile.support_vertex_instance_id) { vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); } else { @@ -1207,24 +1215,24 @@ void EmitContext::DefineInputs(const Info& info) { base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); } } - if (info.loads_front_face) { + if (loads[IR::Attribute::FrontFace]) { front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); } - if (info.loads_point_coord) { + if (loads[IR::Attribute::PointSpriteS] || loads[IR::Attribute::PointSpriteT]) { point_coord = DefineInput(*this, F32[2], true, spv::BuiltIn::PointCoord); } - if (info.loads_tess_coord) { + if (loads[IR::Attribute::TessellationEvaluationPointU] || + loads[IR::Attribute::TessellationEvaluationPointV]) { tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); } - for (size_t index = 0; index < info.input_generics.size(); ++index) { - if (!runtime_info.previous_stage_stores_generic[index]) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + const AttributeType input_type{runtime_info.generic_input_types[index]}; + if (!runtime_info.previous_stage_stores.Generic(index)) { continue; } - const InputVarying generic{info.input_generics[index]}; - if (!generic.used) { + if (!loads.Generic(index)) { continue; } - const AttributeType input_type{runtime_info.generic_input_types[index]}; if (input_type == AttributeType::Disabled) { continue; } @@ -1234,10 +1242,13 @@ void EmitContext::DefineInputs(const Info& info) { Name(id, fmt::format("in_attr{}", index)); input_generics[index] = id; + if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) { + Decorate(id, spv::Decoration::PassthroughNV); + } if (stage != Stage::Fragment) { continue; } - switch (generic.interpolation) { + switch (info.interpolation[index]) { case Interpolation::Smooth: // Default // Decorate(id, spv::Decoration::Smooth); @@ -1266,42 +1277,42 @@ void EmitContext::DefineInputs(const Info& info) { void EmitContext::DefineOutputs(const IR::Program& program) { const Info& info{program.info}; const std::optional invocations{program.invocations}; - if (info.stores_position || stage == Stage::VertexB) { + if (info.stores.AnyComponent(IR::Attribute::PositionX) || stage == Stage::VertexB) { output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); } - if (info.stores_point_size || runtime_info.fixed_state_point_size) { + if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing PointSize in fragment stage"); } output_point_size = DefineOutput(*this, F32[1], invocations, spv::BuiltIn::PointSize); } - if (info.stores_clip_distance) { + if (info.stores.ClipDistances()) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing ClipDistance in fragment stage"); } const Id type{TypeArray(F32[1], Const(8U))}; clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); } - if (info.stores_layer && + if (info.stores[IR::Attribute::Layer] && (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing Layer in fragment stage"); } layer = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::Layer); } - if (info.stores_viewport_index && + if (info.stores[IR::Attribute::ViewportIndex] && (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing ViewportIndex in fragment stage"); } viewport_index = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::ViewportIndex); } - if (info.stores_viewport_mask && profile.support_viewport_mask) { + if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } - 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)) { DefineGenericOutput(*this, index, invocations); } } diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 527685fb8..e277bc358 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -300,7 +300,7 @@ private: void DefineAttributeMemAccess(const Info& info); void DefineGlobalMemoryFunctions(const Info& info); - void DefineInputs(const Info& info); + void DefineInputs(const IR::Program& program); void DefineOutputs(const IR::Program& program); }; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 278c262f8..ddb86d070 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -281,11 +281,19 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { ctx.AddExecutionMode(main, spv::ExecutionMode::OutputTriangleStrip); break; } - if (program.info.stores_point_size) { + if (program.info.stores[IR::Attribute::PointSize]) { ctx.AddCapability(spv::Capability::GeometryPointSize); } ctx.AddExecutionMode(main, spv::ExecutionMode::OutputVertices, program.output_vertices); ctx.AddExecutionMode(main, spv::ExecutionMode::Invocations, program.invocations); + if (program.is_geometry_passthrough) { + if (ctx.profile.support_geometry_shader_passthrough) { + ctx.AddExtension("SPV_NV_geometry_shader_passthrough"); + ctx.AddCapability(spv::Capability::GeometryShaderPassthroughNV); + } else { + LOG_WARNING(Shader_SPIRV, "Geometry shader passthrough used with no support"); + } + } break; case Stage::Fragment: execution_model = spv::ExecutionModel::Fragment; @@ -377,20 +385,21 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); } - if (info.stores_viewport_index) { + if (info.stores[IR::Attribute::ViewportIndex]) { ctx.AddCapability(spv::Capability::MultiViewport); } - if (info.stores_viewport_mask && profile.support_viewport_mask) { + if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) { ctx.AddExtension("SPV_NV_viewport_array2"); ctx.AddCapability(spv::Capability::ShaderViewportMaskNV); } - if (info.stores_layer || info.stores_viewport_index) { + if (info.stores[IR::Attribute::Layer] || info.stores[IR::Attribute::ViewportIndex]) { if (profile.support_viewport_index_layer_non_geometry && ctx.stage != Stage::Geometry) { ctx.AddExtension("SPV_EXT_shader_viewport_index_layer"); ctx.AddCapability(spv::Capability::ShaderViewportIndexLayerEXT); } } - if (!profile.support_vertex_instance_id && (info.loads_instance_id || info.loads_vertex_id)) { + if (!profile.support_vertex_instance_id && + (info.loads[IR::Attribute::InstanceId] || info.loads[IR::Attribute::VertexId])) { ctx.AddExtension("SPV_KHR_shader_draw_parameters"); ctx.AddCapability(spv::Capability::DrawParameters); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 85bd72389..77fbb2b2f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -298,7 +298,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; const std::optional type{AttrTypes(ctx, index)}; - if (!type || !ctx.runtime_info.previous_stage_stores_generic[index]) { + if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index)) { // Attribute is disabled return ctx.Const(0.0f); } diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 090bc1c08..8369d0d84 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h @@ -31,6 +31,10 @@ public: return sph; } + [[nodiscard]] const std::array& GpPassthroughMask() const noexcept { + return gp_passthrough_mask; + } + [[nodiscard]] Stage ShaderStage() const noexcept { return stage; } @@ -41,6 +45,7 @@ public: protected: ProgramHeader sph{}; + std::array gp_passthrough_mask{}; Stage stage{}; u32 start_address{}; }; diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 8bf2ddf30..ca1199494 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -222,6 +222,8 @@ enum class Attribute : u64 { FrontFace = 255, }; +constexpr size_t NUM_GENERICS = 32; + [[nodiscard]] bool IsGeneric(Attribute attribute) noexcept; [[nodiscard]] u32 GenericAttributeIndex(Attribute attribute); @@ -230,6 +232,10 @@ enum class Attribute : u64 { [[nodiscard]] std::string NameOf(Attribute attribute); +[[nodiscard]] constexpr IR::Attribute operator+(IR::Attribute attribute, size_t value) noexcept { + return static_cast(static_cast(attribute) + value); +} + } // namespace Shader::IR template <> diff --git a/src/shader_recompiler/frontend/ir/program.h b/src/shader_recompiler/frontend/ir/program.h index 9ede5b48d..ebcaa8bc2 100644 --- a/src/shader_recompiler/frontend/ir/program.h +++ b/src/shader_recompiler/frontend/ir/program.h @@ -27,6 +27,7 @@ struct Program { u32 invocations{}; u32 local_memory_size{}; u32 shared_memory_size{}; + bool is_geometry_passthrough{}; }; [[nodiscard]] std::string DumpProgram(const Program& program); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index a8b727f1a..6b4b0ce5b 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -46,7 +46,7 @@ void CollectInterpolationInfo(Environment& env, IR::Program& program) { return; } const ProgramHeader& sph{env.SPH()}; - for (size_t index = 0; index < program.info.input_generics.size(); ++index) { + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { std::optional imap; for (const PixelImap value : sph.ps.GenericInputMap(static_cast(index))) { if (value == PixelImap::Unused) { @@ -60,7 +60,7 @@ void CollectInterpolationInfo(Environment& env, IR::Program& program) { if (!imap) { continue; } - program.info.input_generics[index].interpolation = [&] { + program.info.interpolation[index] = [&] { switch (*imap) { case PixelImap::Unused: case PixelImap::Perspective: @@ -140,6 +140,11 @@ IR::Program TranslateProgram(ObjectPool& inst_pool, ObjectPool>(mask); + } break; } case Stage::Compute: @@ -194,12 +199,9 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b result.stage = Stage::VertexB; result.info = vertex_a.info; result.local_memory_size = std::max(vertex_a.local_memory_size, vertex_b.local_memory_size); - for (size_t index = 0; index < 32; ++index) { - result.info.input_generics[index].used |= vertex_b.info.input_generics[index].used; - if (vertex_b.info.stores_generics[index]) { - result.info.stores_generics[index] = true; - } - } + result.info.loads.mask |= vertex_b.info.loads.mask; + result.info.stores.mask |= vertex_b.info.stores.mask; + Optimization::JoinTextureInfo(result.info, vertex_b.info); Optimization::JoinStorageInfo(result.info, vertex_b.info); Optimization::DeadCodeEliminationPass(result); diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index a82472152..5e32ac784 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -29,130 +29,6 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { }); } -void GetAttribute(Info& info, IR::Attribute attr) { - if (IR::IsGeneric(attr)) { - info.input_generics.at(IR::GenericAttributeIndex(attr)).used = true; - return; - } - if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - info.loads_fixed_fnc_textures = true; - info.loads_legacy_varyings = true; - return; - } - switch (attr) { - case IR::Attribute::PrimitiveId: - info.loads_primitive_id = true; - break; - case IR::Attribute::PositionX: - case IR::Attribute::PositionY: - case IR::Attribute::PositionZ: - case IR::Attribute::PositionW: - info.loads_position = true; - break; - case IR::Attribute::ColorFrontDiffuseR: - case IR::Attribute::ColorFrontDiffuseG: - case IR::Attribute::ColorFrontDiffuseB: - case IR::Attribute::ColorFrontDiffuseA: - info.loads_color_front_diffuse = true; - info.loads_legacy_varyings = true; - break; - case IR::Attribute::PointSpriteS: - case IR::Attribute::PointSpriteT: - info.loads_point_coord = true; - break; - case IR::Attribute::TessellationEvaluationPointU: - case IR::Attribute::TessellationEvaluationPointV: - info.loads_tess_coord = true; - break; - case IR::Attribute::InstanceId: - info.loads_instance_id = true; - break; - case IR::Attribute::VertexId: - info.loads_vertex_id = true; - break; - case IR::Attribute::FrontFace: - info.loads_front_face = true; - break; - default: - throw NotImplementedException("Get attribute {}", attr); - } -} - -void SetAttribute(Info& info, IR::Attribute attr) { - if (IR::IsGeneric(attr)) { - info.stores_generics[IR::GenericAttributeIndex(attr)] = true; - return; - } - if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - info.stores_fixed_fnc_textures = true; - info.stores_legacy_varyings = true; - return; - } - switch (attr) { - case IR::Attribute::Layer: - info.stores_layer = true; - break; - case IR::Attribute::ViewportIndex: - info.stores_viewport_index = true; - break; - case IR::Attribute::PointSize: - info.stores_point_size = true; - break; - case IR::Attribute::PositionX: - case IR::Attribute::PositionY: - case IR::Attribute::PositionZ: - case IR::Attribute::PositionW: - info.stores_position = true; - break; - case IR::Attribute::ColorFrontDiffuseR: - case IR::Attribute::ColorFrontDiffuseG: - case IR::Attribute::ColorFrontDiffuseB: - case IR::Attribute::ColorFrontDiffuseA: - info.stores_color_front_diffuse = true; - info.stores_legacy_varyings = true; - break; - case IR::Attribute::ColorFrontSpecularR: - case IR::Attribute::ColorFrontSpecularG: - case IR::Attribute::ColorFrontSpecularB: - case IR::Attribute::ColorFrontSpecularA: - info.stores_color_front_specular = true; - info.stores_legacy_varyings = true; - break; - case IR::Attribute::ColorBackDiffuseR: - case IR::Attribute::ColorBackDiffuseG: - case IR::Attribute::ColorBackDiffuseB: - case IR::Attribute::ColorBackDiffuseA: - info.stores_color_back_diffuse = true; - info.stores_legacy_varyings = true; - break; - case IR::Attribute::ColorBackSpecularR: - case IR::Attribute::ColorBackSpecularG: - case IR::Attribute::ColorBackSpecularB: - case IR::Attribute::ColorBackSpecularA: - info.stores_color_back_specular = true; - info.stores_legacy_varyings = true; - 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: - info.stores_clip_distance = true; - break; - case IR::Attribute::FogCoordinate: - info.stores_fog_coordinate = true; - break; - case IR::Attribute::ViewportMask: - info.stores_viewport_mask = true; - break; - default: - throw NotImplementedException("Set attribute {}", attr); - } -} - void GetPatch(Info& info, IR::Patch patch) { if (!IR::IsGeneric(patch)) { throw NotImplementedException("Reading non-generic patch {}", patch); @@ -511,10 +387,10 @@ void VisitUsages(Info& info, IR::Inst& inst) { info.uses_demote_to_helper_invocation = true; break; case IR::Opcode::GetAttribute: - GetAttribute(info, inst.Arg(0).Attribute()); + info.loads.mask[static_cast(inst.Arg(0).Attribute())] = true; break; case IR::Opcode::SetAttribute: - SetAttribute(info, inst.Arg(0).Attribute()); + info.stores.mask[static_cast(inst.Arg(0).Attribute())] = true; break; case IR::Opcode::GetPatch: GetPatch(info, inst.Arg(0).Patch()); @@ -943,26 +819,78 @@ void GatherInfoFromHeader(Environment& env, Info& info) { if (!info.loads_indexed_attributes) { return; } - for (size_t i = 0; i < info.input_generics.size(); i++) { - info.input_generics[i].used |= header.ps.IsGenericVectorActive(i); + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + const size_t offset{static_cast(IR::Attribute::Generic0X) + index * 4}; + const auto vector{header.ps.imap_generic_vector[index]}; + info.loads.mask[offset + 0] = vector.x != PixelImap::Unused; + info.loads.mask[offset + 1] = vector.y != PixelImap::Unused; + info.loads.mask[offset + 2] = vector.z != PixelImap::Unused; + info.loads.mask[offset + 3] = vector.w != PixelImap::Unused; } - info.loads_position |= header.ps.imap_systemb.position != 0; return; } if (info.loads_indexed_attributes) { - for (size_t i = 0; i < info.input_generics.size(); i++) { - info.input_generics[i].used |= header.vtg.IsInputGenericVectorActive(i); + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + const IR::Attribute attribute{IR::Attribute::Generic0X + index * 4}; + const auto mask = header.vtg.InputGeneric(index); + for (size_t i = 0; i < 4; ++i) { + info.loads.Set(attribute + i, mask[i]); + } + } + for (size_t index = 0; index < 8; ++index) { + const u16 mask{header.vtg.clip_distances}; + info.loads.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0); } - info.loads_position |= header.vtg.imap_systemb.position != 0; + info.loads.Set(IR::Attribute::PrimitiveId, header.vtg.imap_systemb.primitive_array_id != 0); + info.loads.Set(IR::Attribute::Layer, header.vtg.imap_systemb.rt_array_index != 0); + info.loads.Set(IR::Attribute::ViewportIndex, header.vtg.imap_systemb.viewport_index != 0); + info.loads.Set(IR::Attribute::PointSize, header.vtg.imap_systemb.point_size != 0); + info.loads.Set(IR::Attribute::PositionX, header.vtg.imap_systemb.position_x != 0); + info.loads.Set(IR::Attribute::PositionY, header.vtg.imap_systemb.position_y != 0); + info.loads.Set(IR::Attribute::PositionZ, header.vtg.imap_systemb.position_z != 0); + info.loads.Set(IR::Attribute::PositionW, header.vtg.imap_systemb.position_w != 0); + info.loads.Set(IR::Attribute::PointSpriteS, header.vtg.point_sprite_s != 0); + info.loads.Set(IR::Attribute::PointSpriteT, header.vtg.point_sprite_t != 0); + info.loads.Set(IR::Attribute::FogCoordinate, header.vtg.fog_coordinate != 0); + info.loads.Set(IR::Attribute::TessellationEvaluationPointU, + header.vtg.tessellation_eval_point_u != 0); + info.loads.Set(IR::Attribute::TessellationEvaluationPointV, + header.vtg.tessellation_eval_point_v != 0); + info.loads.Set(IR::Attribute::InstanceId, header.vtg.instance_id != 0); + info.loads.Set(IR::Attribute::VertexId, header.vtg.vertex_id != 0); + // TODO: Legacy varyings } if (info.stores_indexed_attributes) { - for (size_t i = 0; i < info.stores_generics.size(); i++) { - if (header.vtg.IsOutputGenericVectorActive(i)) { - info.stores_generics[i] = true; + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + const IR::Attribute attribute{IR::Attribute::Generic0X + index * 4}; + const auto mask{header.vtg.OutputGeneric(index)}; + for (size_t i = 0; i < 4; ++i) { + info.stores.Set(attribute + i, mask[i]); } } - info.stores_clip_distance |= header.vtg.omap_systemc.clip_distances != 0; - info.stores_position |= header.vtg.omap_systemb.position != 0; + for (size_t index = 0; index < 8; ++index) { + const u16 mask{header.vtg.omap_systemc.clip_distances}; + info.stores.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0); + } + info.stores.Set(IR::Attribute::PrimitiveId, + header.vtg.omap_systemb.primitive_array_id != 0); + info.stores.Set(IR::Attribute::Layer, header.vtg.omap_systemb.rt_array_index != 0); + info.stores.Set(IR::Attribute::ViewportIndex, header.vtg.omap_systemb.viewport_index != 0); + info.stores.Set(IR::Attribute::PointSize, header.vtg.omap_systemb.point_size != 0); + info.stores.Set(IR::Attribute::PositionX, header.vtg.omap_systemb.position_x != 0); + info.stores.Set(IR::Attribute::PositionY, header.vtg.omap_systemb.position_y != 0); + info.stores.Set(IR::Attribute::PositionZ, header.vtg.omap_systemb.position_z != 0); + info.stores.Set(IR::Attribute::PositionW, header.vtg.omap_systemb.position_w != 0); + info.stores.Set(IR::Attribute::PointSpriteS, header.vtg.omap_systemc.point_sprite_s != 0); + info.stores.Set(IR::Attribute::PointSpriteT, header.vtg.omap_systemc.point_sprite_t != 0); + info.stores.Set(IR::Attribute::FogCoordinate, header.vtg.omap_systemc.fog_coordinate != 0); + info.stores.Set(IR::Attribute::TessellationEvaluationPointU, + header.vtg.omap_systemc.tessellation_eval_point_u != 0); + info.stores.Set(IR::Attribute::TessellationEvaluationPointV, + header.vtg.omap_systemc.tessellation_eval_point_v != 0); + info.stores.Set(IR::Attribute::InstanceId, header.vtg.omap_systemc.instance_id != 0); + info.stores.Set(IR::Attribute::VertexId, header.vtg.omap_systemc.vertex_id != 0); + // TODO: Legacy varyings } } } // Anonymous namespace diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index d46be1638..ee1887b56 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -34,6 +34,7 @@ struct Profile { bool support_demote_to_helper_invocation{}; bool support_int64_atomics{}; bool support_derivative_control{}; + bool support_geometry_shader_passthrough{}; bool support_gl_nv_gpu_shader_5{}; bool support_gl_amd_gpu_shader_half_float{}; bool support_gl_texture_shadow_lod{}; diff --git a/src/shader_recompiler/program_header.h b/src/shader_recompiler/program_header.h index 6933750aa..bd6c2bfb5 100644 --- a/src/shader_recompiler/program_header.h +++ b/src/shader_recompiler/program_header.h @@ -37,7 +37,9 @@ struct ProgramHeader { BitField<15, 1, u32> kills_pixels; BitField<16, 1, u32> does_global_store; BitField<17, 4, u32> sass_version; - BitField<21, 5, u32> reserved; + BitField<21, 2, u32> reserved1; + BitField<24, 1, u32> geometry_passthrough; + BitField<25, 1, u32> reserved2; BitField<26, 1, u32> does_load_or_store; BitField<27, 1, u32> does_fp64; BitField<28, 4, u32> stream_out_mask; @@ -79,24 +81,10 @@ struct ProgramHeader { BitField<5, 1, u8> position_y; BitField<6, 1, u8> position_z; BitField<7, 1, u8> position_w; - BitField<0, 4, u8> first; - BitField<4, 4, u8> position; u8 raw; } imap_systemb; - union { - BitField<0, 1, u8> x; - BitField<1, 1, u8> y; - BitField<2, 1, u8> z; - BitField<3, 1, u8> w; - BitField<4, 1, u8> x2; - BitField<5, 1, u8> y2; - BitField<6, 1, u8> z2; - BitField<7, 1, u8> w2; - BitField<0, 4, u8> first; - BitField<4, 4, u8> second; - u8 raw; - } imap_generic_vector[16]; + std::array imap_generic_vector; INSERT_PADDING_BYTES_NOINIT(2); // ImapColor union { @@ -122,24 +110,10 @@ struct ProgramHeader { BitField<5, 1, u8> position_y; BitField<6, 1, u8> position_z; BitField<7, 1, u8> position_w; - BitField<0, 4, u8> first; - BitField<4, 4, u8> position; u8 raw; } omap_systemb; - union { - BitField<0, 1, u8> x; - BitField<1, 1, u8> y; - BitField<2, 1, u8> z; - BitField<3, 1, u8> w; - BitField<4, 1, u8> x2; - BitField<5, 1, u8> y2; - BitField<6, 1, u8> z2; - BitField<7, 1, u8> w2; - BitField<0, 4, u8> first; - BitField<4, 4, u8> second; - u8 raw; - } omap_generic_vector[16]; + std::array omap_generic_vector; INSERT_PADDING_BYTES_NOINIT(2); // OmapColor @@ -157,18 +131,24 @@ struct ProgramHeader { INSERT_PADDING_BYTES_NOINIT(5); // OmapFixedFncTexture[10] INSERT_PADDING_BYTES_NOINIT(1); // OmapReserved - [[nodiscard]] bool IsInputGenericVectorActive(size_t index) const { - if ((index & 1) == 0) { - return imap_generic_vector[index >> 1].first != 0; - } - return imap_generic_vector[index >> 1].second != 0; + [[nodiscard]] std::array InputGeneric(size_t index) const noexcept { + const int data{imap_generic_vector[index >> 1] >> ((index % 2) * 4)}; + return { + (data & 1) != 0, + (data & 2) != 0, + (data & 4) != 0, + (data & 8) != 0, + }; } - [[nodiscard]] bool IsOutputGenericVectorActive(size_t index) const { - if ((index & 1) == 0) { - return omap_generic_vector[index >> 1].first != 0; - } - return omap_generic_vector[index >> 1].second != 0; + [[nodiscard]] std::array OutputGeneric(size_t index) const noexcept { + const int data{omap_generic_vector[index >> 1] >> ((index % 2) * 4)}; + return { + (data & 1) != 0, + (data & 2) != 0, + (data & 4) != 0, + (data & 8) != 0, + }; } } vtg; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 63fe2afaf..f3f83a258 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -10,6 +10,7 @@ #include #include "common/common_types.h" +#include "shader_recompiler/varying_state.h" namespace Shader { @@ -60,7 +61,7 @@ struct TransformFeedbackVarying { struct RuntimeInfo { std::array generic_input_types{}; - std::bitset<32> previous_stage_stores_generic{}; + VaryingState previous_stage_stores; bool convert_depth_mode{}; bool force_early_z{}; diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index a20e15d2e..4ef4dbd40 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -9,6 +9,7 @@ #include "common/common_types.h" #include "shader_recompiler/frontend/ir/type.h" +#include "shader_recompiler/varying_state.h" #include #include @@ -44,11 +45,6 @@ enum class Interpolation { NoPerspective, }; -struct InputVarying { - Interpolation interpolation{Interpolation::Smooth}; - bool used{false}; -}; - struct ConstantBufferDescriptor { u32 index; u32 count; @@ -121,18 +117,10 @@ struct Info { bool uses_subgroup_shuffles{}; std::array uses_patches{}; - std::array input_generics{}; - bool loads_primitive_id{}; - bool loads_position{}; - bool loads_color_front_diffuse{}; - bool loads_fixed_fnc_textures{}; - bool loads_point_coord{}; - bool loads_instance_id{}; - bool loads_vertex_id{}; - bool loads_front_face{}; - bool loads_legacy_varyings{}; - - bool loads_tess_coord{}; + std::array interpolation{}; + VaryingState loads; + VaryingState stores; + VaryingState passthrough; bool loads_indexed_attributes{}; @@ -140,21 +128,6 @@ struct Info { bool stores_sample_mask{}; bool stores_frag_depth{}; - std::bitset<32> stores_generics{}; - bool stores_layer{}; - bool stores_viewport_index{}; - bool stores_point_size{}; - bool stores_position{}; - bool stores_color_front_diffuse{}; - bool stores_color_front_specular{}; - bool stores_color_back_diffuse{}; - bool stores_color_back_specular{}; - bool stores_fixed_fnc_textures{}; - bool stores_clip_distance{}; - bool stores_fog_coordinate{}; - bool stores_viewport_mask{}; - bool stores_legacy_varyings{}; - bool stores_tess_level_outer{}; bool stores_tess_level_inner{}; diff --git a/src/shader_recompiler/varying_state.h b/src/shader_recompiler/varying_state.h new file mode 100644 index 000000000..9d7b24a76 --- /dev/null +++ b/src/shader_recompiler/varying_state.h @@ -0,0 +1,69 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "shader_recompiler/frontend/ir/attribute.h" + +namespace Shader { + +struct VaryingState { + std::bitset<256> mask{}; + + void Set(IR::Attribute attribute, bool state = true) { + mask[static_cast(attribute)] = state; + } + + [[nodiscard]] bool operator[](IR::Attribute attribute) const noexcept { + return mask[static_cast(attribute)]; + } + + [[nodiscard]] bool AnyComponent(IR::Attribute base) const noexcept { + return mask[static_cast(base) + 0] || mask[static_cast(base) + 1] || + mask[static_cast(base) + 2] || mask[static_cast(base) + 3]; + } + + [[nodiscard]] bool AllComponents(IR::Attribute base) const noexcept { + return mask[static_cast(base) + 0] && mask[static_cast(base) + 1] && + mask[static_cast(base) + 2] && mask[static_cast(base) + 3]; + } + + [[nodiscard]] bool IsUniform(IR::Attribute base) const noexcept { + return AnyComponent(base) == AllComponents(base); + } + + [[nodiscard]] bool Generic(size_t index, size_t component) const noexcept { + return mask[static_cast(IR::Attribute::Generic0X) + index * 4 + component]; + } + + [[nodiscard]] bool Generic(size_t index) const noexcept { + return Generic(index, 0) || Generic(index, 1) || Generic(index, 2) || Generic(index, 3); + } + + [[nodiscard]] bool ClipDistances() const noexcept { + return AnyComponent(IR::Attribute::ClipDistance0) || + AnyComponent(IR::Attribute::ClipDistance4); + } + + [[nodiscard]] bool Legacy() const noexcept { + return AnyComponent(IR::Attribute::ColorFrontDiffuseR) || + AnyComponent(IR::Attribute::ColorFrontSpecularR) || + AnyComponent(IR::Attribute::ColorBackDiffuseR) || + AnyComponent(IR::Attribute::ColorBackSpecularR) || FixedFunctionTexture(); + } + + [[nodiscard]] bool FixedFunctionTexture() const noexcept { + for (size_t index = 0; index < 10; ++index) { + if (AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { + return true; + } + } + return false; + } +}; + +} // namespace Shader diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index da2ded671..471d5686a 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -961,7 +961,11 @@ public: SamplerIndex sampler_index; - INSERT_PADDING_WORDS_NOINIT(0x25); + INSERT_PADDING_WORDS_NOINIT(0x2); + + std::array gp_passthrough_mask; + + INSERT_PADDING_WORDS_NOINIT(0x1B); u32 depth_test_enable; @@ -1628,6 +1632,7 @@ ASSERT_REG_POSITION(zeta_width, 0x48a); ASSERT_REG_POSITION(zeta_height, 0x48b); ASSERT_REG_POSITION(zeta_depth, 0x48c); ASSERT_REG_POSITION(sampler_index, 0x48D); +ASSERT_REG_POSITION(gp_passthrough_mask, 0x490); ASSERT_REG_POSITION(depth_test_enable, 0x4B3); ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 5af9b7745..06e39a503 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -61,10 +61,10 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, bool glasm_use_storage_buffers, bool use_assembly_shaders) { Shader::RuntimeInfo info; if (previous_program) { - info.previous_stage_stores_generic = previous_program->info.stores_generics; + info.previous_stage_stores = previous_program->info.stores; } else { - // Mark all stores as available - info.previous_stage_stores_generic.flip(); + // Mark all stores as available for vertex shaders + info.previous_stage_stores.mask.set(); } switch (program.stage) { case Shader::Stage::VertexB: @@ -187,6 +187,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .support_demote_to_helper_invocation = false, .support_int64_atomics = false, .support_derivative_control = device.HasDerivativeControl(), + .support_geometry_shader_passthrough = false, // TODO .support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(), .support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(), .support_gl_texture_shadow_lod = device.HasTextureShadowLod(), diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 70e183e65..6d664ed6b 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -487,10 +487,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { static_vector vertex_binding_divisors; static_vector vertex_attributes; if (key.state.dynamic_vertex_input) { - const auto& input_attributes = stage_infos[0].input_generics; for (size_t index = 0; index < key.state.attributes.size(); ++index) { const u32 type = key.state.DynamicAttributeType(index); - if (!input_attributes[index].used || type == 0) { + if (!stage_infos[0].loads.Generic(index) || type == 0) { continue; } vertex_attributes.push_back({ @@ -526,10 +525,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { }); } } - const auto& input_attributes = stage_infos[0].input_generics; for (size_t index = 0; index < key.state.attributes.size(); ++index) { const auto& attribute = key.state.attributes[index]; - if (!attribute.enabled || !input_attributes[index].used) { + if (!attribute.enabled || !stage_infos[0].loads.Generic(index)) { continue; } vertex_attributes.push_back({ diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ec06b124f..7aaa40ef2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -123,18 +123,21 @@ Shader::AttributeType AttributeType(const FixedPipelineState& state, size_t inde return Shader::AttributeType::Disabled; } -Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key, +Shader::RuntimeInfo MakeRuntimeInfo(std::span programs, + const GraphicsPipelineCacheKey& key, const Shader::IR::Program& program, const Shader::IR::Program* previous_program) { Shader::RuntimeInfo info; if (previous_program) { - info.previous_stage_stores_generic = previous_program->info.stores_generics; + info.previous_stage_stores = previous_program->info.stores; + if (previous_program->is_geometry_passthrough) { + info.previous_stage_stores.mask |= previous_program->info.passthrough.mask; + } } else { - // Mark all stores as available - info.previous_stage_stores_generic.flip(); + info.previous_stage_stores.mask.set(); } const Shader::Stage stage{program.stage}; - const bool has_geometry{key.unique_hashes[4] != 0}; + const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; const float point_size{Common::BitCast(key.state.point_size)}; switch (stage) { @@ -302,6 +305,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw .support_demote_to_helper_invocation = true, .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), .support_derivative_control = true, + .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), @@ -518,7 +522,7 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( const size_t stage_index{index - 1}; infos[stage_index] = &program.info; - const Shader::RuntimeInfo runtime_info{MakeRuntimeInfo(key, program, previous_stage)}; + const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)}; const std::vector code{EmitSPIRV(profile, runtime_info, program, binding)}; device.SaveShader(code); modules[stage_index] = BuildShader(device, code); diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index d463e2b56..429cab30d 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -22,7 +22,7 @@ namespace VideoCommon { constexpr std::array MAGIC_NUMBER{'y', 'u', 'z', 'u', 'c', 'a', 'c', 'h'}; -constexpr u32 CACHE_VERSION = 4; +constexpr u32 CACHE_VERSION = 5; constexpr size_t INST_SIZE = sizeof(u64); @@ -155,6 +155,10 @@ void GenericEnvironment::Serialize(std::ofstream& file) const { .write(reinterpret_cast(&shared_memory_size), sizeof(shared_memory_size)); } else { file.write(reinterpret_cast(&sph), sizeof(sph)); + if (stage == Shader::Stage::Geometry) { + file.write(reinterpret_cast(&gp_passthrough_mask), + sizeof(gp_passthrough_mask)); + } } } @@ -202,6 +206,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, u32 start_address_) : GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} { gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph)); + gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask; switch (program) { case Maxwell::ShaderProgram::VertexA: stage = Shader::Stage::VertexA; @@ -319,6 +324,9 @@ void FileEnvironment::Deserialize(std::ifstream& file) { .read(reinterpret_cast(&shared_memory_size), sizeof(shared_memory_size)); } else { file.read(reinterpret_cast(&sph), sizeof(sph)); + if (stage == Shader::Stage::Geometry) { + file.read(reinterpret_cast(&gp_passthrough_mask), sizeof(gp_passthrough_mask)); + } } } diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 7b184d2f8..da4721e6b 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -350,6 +350,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_INFO(Render_Vulkan, "Device doesn't support viewport masks"); } + if (!nv_geometry_shader_passthrough) { + LOG_INFO(Render_Vulkan, "Device doesn't support passthrough geometry shaders"); + } + VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; if (khr_uniform_buffer_standard_layout) { std430_layout = { @@ -768,6 +772,8 @@ std::vector Device::LoadExtensions(bool requires_surface) { }; test(nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true); test(nv_viewport_array2, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, true); + test(nv_geometry_shader_passthrough, VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, + true); test(khr_uniform_buffer_standard_layout, VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true); test(khr_spirv_1_4, VK_KHR_SPIRV_1_4_EXTENSION_NAME, true); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index a9c0a0e4d..d0adc0127 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -194,6 +194,11 @@ public: return nv_viewport_array2; } + /// Returns true if the device supports VK_NV_geometry_shader_passthrough. + bool IsNvGeometryShaderPassthroughSupported() const { + return nv_geometry_shader_passthrough; + } + /// Returns true if the device supports VK_KHR_uniform_buffer_standard_layout. bool IsKhrUniformBufferStandardLayoutSupported() const { return khr_uniform_buffer_standard_layout; @@ -363,6 +368,7 @@ private: bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil. bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. + bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough. bool khr_uniform_buffer_standard_layout{}; ///< Support for scalar uniform buffer layouts. bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4. bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts. -- 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 ++++++++++++++++++---- src/video_core/renderer_opengl/gl_device.cpp | 1 + src/video_core/renderer_opengl/gl_device.h | 5 ++++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 +- 5 files changed, 33 insertions(+), 8 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], diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 27be347e6..6818951f2 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -160,6 +160,7 @@ Device::Device() { has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; has_debugging_tool_attached = IsDebugToolAttached(extensions); has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float"); + has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough; has_nv_gpu_shader_5 = GLAD_GL_NV_gpu_shader5; has_shader_int64 = HasExtension(extensions, "GL_ARB_gpu_shader_int64"); has_amd_shader_half_float = GLAD_GL_AMD_gpu_shader_half_float; diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index ad7b01b06..45ddf5e01 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -120,6 +120,10 @@ public: return has_depth_buffer_float; } + bool HasGeometryShaderPassthrough() const { + return has_geometry_shader_passthrough; + } + bool HasNvGpuShader5() const { return has_nv_gpu_shader_5; } @@ -174,6 +178,7 @@ private: bool use_asynchronous_shaders{}; bool use_driver_cache{}; bool has_depth_buffer_float{}; + bool has_geometry_shader_passthrough{}; bool has_nv_gpu_shader_5{}; bool has_shader_int64{}; bool has_amd_shader_half_float{}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 06e39a503..af8e9f44d 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -187,7 +187,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .support_demote_to_helper_invocation = false, .support_int64_atomics = false, .support_derivative_control = device.HasDerivativeControl(), - .support_geometry_shader_passthrough = false, // TODO + .support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(), .support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(), .support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(), .support_gl_texture_shadow_lod = device.HasTextureShadowLod(), -- 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 +++++++++++++++++++--- .../backend/glsl/emit_glsl_integer.cpp | 14 +++++++--- 2 files changed, 38 insertions(+), 6 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, diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp index 2892074e1..38419f88f 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp @@ -27,6 +27,14 @@ void SetSignFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) { ctx.AddU1("{}=int({})<0;", *sign, result); sign->Invalidate(); } + +void BitwiseLogicalOp(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, + char lop) { + const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)}; + ctx.Add("{}={}{}{};", result, a, lop, b); + SetZeroFlag(ctx, inst, result); + SetSignFlag(ctx, inst, result); +} } // Anonymous namespace void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { @@ -113,15 +121,15 @@ void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, std::string_vi } void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { - ctx.AddU32("{}={}&{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, '&'); } void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { - ctx.AddU32("{}={}|{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, '|'); } void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { - ctx.AddU32("{}={}^{};", inst, a, b); + BitwiseLogicalOp(ctx, inst, a, b, '^'); } void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base, -- 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 +++++--- src/shader_recompiler/backend/glsl/emit_context.cpp | 2 +- src/shader_recompiler/backend/glsl/emit_context.h | 6 +++--- src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | 4 ++-- src/shader_recompiler/backend/spirv/emit_context.cpp | 5 +++-- src/shader_recompiler/exception.h | 8 ++++---- .../frontend/maxwell/structured_control_flow.cpp | 2 +- 7 files changed, 19 insertions(+), 16 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'; } diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 36527bbd4..0dcdff152 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp @@ -597,7 +597,7 @@ std::string EmitContext::DefineGlobalMemoryFunctions() { func += comparison; const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; - func += fmt::format(return_statement, ssbo_name, ssbo_addr); + func += fmt::format(fmt::runtime(return_statement), ssbo_name, ssbo_addr); }}; std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){"}; std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){"}; diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h index dd7397489..d9b639d29 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.h +++ b/src/shader_recompiler/backend/glsl/emit_context.h @@ -51,9 +51,9 @@ public: const auto var_def{var_alloc.AddDefine(inst, type)}; if (var_def.empty()) { // skip assigment. - code += fmt::format(format_str + 3, std::forward(args)...); + code += fmt::format(fmt::runtime(format_str + 3), std::forward(args)...); } else { - code += fmt::format(format_str, var_def, std::forward(args)...); + code += fmt::format(fmt::runtime(format_str), var_def, std::forward(args)...); } // TODO: Remove this code += '\n'; @@ -131,7 +131,7 @@ public: 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'; } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index d5424301b..580063fa9 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp @@ -61,14 +61,14 @@ void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, : fmt ::format("bitfieldExtract({},int({}),{})", cbuf_cast, bit_offset, num_bits)}; if (!component_indexing_bug) { - const auto result{fmt::format(extraction, swizzle)}; + const auto result{fmt::format(fmt::runtime(extraction), swizzle)}; ctx.Add("{}={};", ret, result); return; } const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; for (u32 i = 0; i < 4; ++i) { const auto swizzle_string{fmt::format(".{}", "xyzw"[i])}; - const auto result{fmt::format(extraction, swizzle_string)}; + const auto result{fmt::format(fmt::runtime(extraction), swizzle_string)}; ctx.Add("if(({}&3)=={}){}={};", cbuf_offset, i, ret, result); } } diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 0926dcf14..865f34291 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -244,8 +244,9 @@ std::string_view StageName(Stage stage) { template void Name(EmitContext& ctx, Id object, std::string_view format_str, Args&&... args) { - ctx.Name(object, - fmt::format(format_str, StageName(ctx.stage), std::forward(args)...).c_str()); + ctx.Name(object, fmt::format(fmt::runtime(format_str), StageName(ctx.stage), + std::forward(args)...) + .c_str()); } void DefineConstBuffers(EmitContext& ctx, const Info& info, Id UniformDefinitions::*member_type, diff --git a/src/shader_recompiler/exception.h b/src/shader_recompiler/exception.h index 43f08162d..337e7f0c8 100644 --- a/src/shader_recompiler/exception.h +++ b/src/shader_recompiler/exception.h @@ -37,21 +37,21 @@ class LogicError : public Exception { public: template LogicError(const char* message, Args&&... args) - : Exception{fmt::format(message, std::forward(args)...)} {} + : Exception{fmt::format(fmt::runtime(message), std::forward(args)...)} {} }; class RuntimeError : public Exception { public: template RuntimeError(const char* message, Args&&... args) - : Exception{fmt::format(message, std::forward(args)...)} {} + : Exception{fmt::format(fmt::runtime(message), std::forward(args)...)} {} }; class NotImplementedException : public Exception { public: template NotImplementedException(const char* message, Args&&... args) - : Exception{fmt::format(message, std::forward(args)...)} { + : Exception{fmt::format(fmt::runtime(message), std::forward(args)...)} { Append(" is not implemented"); } }; @@ -60,7 +60,7 @@ class InvalidArgument : public Exception { public: template InvalidArgument(const char* message, Args&&... args) - : Exception{fmt::format(message, std::forward(args)...)} {} + : Exception{fmt::format(fmt::runtime(message), std::forward(args)...)} {} }; } // namespace Shader diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 10d05dc4c..06fde0017 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -174,7 +174,7 @@ std::string DumpTree(const Tree& tree, u32 indentation = 0) { switch (stmt->type) { case StatementType::Code: ret += fmt::format("{} Block {:04x} -> {:04x} (0x{:016x});\n", indent, - stmt->block->begin, stmt->block->end, + stmt->block->begin.Offset(), stmt->block->end.Offset(), reinterpret_cast(stmt->block)); break; case StatementType::Goto: -- 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 +-- .../backend/glsl/emit_glsl_floating_point.cpp | 2 +- src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 15 ++++++++++----- src/shader_recompiler/frontend/ir/opcodes.h | 3 ++- src/shader_recompiler/frontend/maxwell/control_flow.h | 1 - .../frontend/maxwell/structured_control_flow.cpp | 9 ++------- .../translate/impl/atomic_operations_global_memory.cpp | 12 ++++++------ .../translate/impl/integer_floating_point_conversion.cpp | 4 +++- .../maxwell/translate/impl/load_store_attribute.cpp | 12 ++++++------ .../maxwell/translate/impl/surface_atomic_operations.cpp | 3 --- .../maxwell/translate/impl/surface_load_store.cpp | 8 ++++---- .../ir_opt/global_memory_to_storage_buffer_pass.cpp | 6 +++--- src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 4 +--- 14 files changed, 40 insertions(+), 44 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{}; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp index b11be5bd7..2edcf592e 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp @@ -22,7 +22,7 @@ void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string } bool IsPrecise(const IR::Inst& inst) { - return {inst.Flags().no_contraction}; + return inst.Flags().no_contraction; } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 647804814..3588f052b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -109,7 +109,7 @@ private: return; } if (offset.IsImmediate()) { - Add(spv::ImageOperandsMask::ConstOffset, ctx.SConst(offset.U32())); + Add(spv::ImageOperandsMask::ConstOffset, ctx.SConst(static_cast(offset.U32()))); return; } IR::Inst* const inst{offset.InstRecursive()}; @@ -117,16 +117,21 @@ private: switch (inst->GetOpcode()) { case IR::Opcode::CompositeConstructU32x2: Add(spv::ImageOperandsMask::ConstOffset, - ctx.SConst(inst->Arg(0).U32(), inst->Arg(1).U32())); + ctx.SConst(static_cast(inst->Arg(0).U32()), + static_cast(inst->Arg(1).U32()))); return; case IR::Opcode::CompositeConstructU32x3: Add(spv::ImageOperandsMask::ConstOffset, - ctx.SConst(inst->Arg(0).U32(), inst->Arg(1).U32(), inst->Arg(2).U32())); + ctx.SConst(static_cast(inst->Arg(0).U32()), + static_cast(inst->Arg(1).U32()), + static_cast(inst->Arg(2).U32()))); return; case IR::Opcode::CompositeConstructU32x4: Add(spv::ImageOperandsMask::ConstOffset, - ctx.SConst(inst->Arg(0).U32(), inst->Arg(1).U32(), inst->Arg(2).U32(), - inst->Arg(3).U32())); + ctx.SConst(static_cast(inst->Arg(0).U32()), + static_cast(inst->Arg(1).U32()), + static_cast(inst->Arg(2).U32()), + static_cast(inst->Arg(3).U32()))); return; default: break; diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h index 56b001902..9ab108292 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.h +++ b/src/shader_recompiler/frontend/ir/opcodes.h @@ -67,7 +67,8 @@ constexpr OpcodeMeta META_TABLE[]{ }; constexpr size_t CalculateNumArgsOf(Opcode op) { const auto& arg_types{META_TABLE[static_cast(op)].arg_types}; - return std::distance(arg_types.begin(), std::ranges::find(arg_types, Type::Void)); + return static_cast( + std::distance(arg_types.begin(), std::ranges::find(arg_types, Type::Void))); } constexpr u8 NUM_ARGS[]{ diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.h b/src/shader_recompiler/frontend/maxwell/control_flow.h index 0e515c3b6..a6bd3e196 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.h +++ b/src/shader_recompiler/frontend/maxwell/control_flow.h @@ -161,7 +161,6 @@ private: Environment& env; ObjectPool& block_pool; boost::container::small_vector functions; - FunctionId current_function_id{0}; Location program_start; bool exits_to_dispatcher{}; Block* dispatch_block{}; diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 06fde0017..221454b99 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -313,9 +313,7 @@ bool NeedsLift(Node goto_stmt, Node label_stmt) noexcept { class GotoPass { public: - explicit GotoPass(Flow::CFG& cfg, ObjectPool& inst_pool_, - ObjectPool& block_pool_, ObjectPool& stmt_pool) - : inst_pool{inst_pool_}, block_pool{block_pool_}, pool{stmt_pool} { + explicit GotoPass(Flow::CFG& cfg, ObjectPool& stmt_pool) : pool{stmt_pool} { std::vector gotos{BuildTree(cfg)}; for (const Node& goto_stmt : gotos | std::views::reverse) { RemoveGoto(goto_stmt); @@ -616,8 +614,6 @@ private: return parent_tree.insert(std::next(loop), *new_goto); } - ObjectPool& inst_pool; - ObjectPool& block_pool; ObjectPool& pool; Statement root_stmt{FunctionTag{}}; }; @@ -864,7 +860,6 @@ private: ObjectPool& block_pool; Environment& env; IR::AbstractSyntaxList& syntax_list; - u32 loop_id{}; // TODO: C++20 Remove this when all compilers support constexpr std::vector #if __cpp_lib_constexpr_vector >= 201907 @@ -878,7 +873,7 @@ private: IR::AbstractSyntaxList BuildASL(ObjectPool& inst_pool, ObjectPool& block_pool, Environment& env, Flow::CFG& cfg) { ObjectPool stmt_pool{64}; - GotoPass goto_pass{cfg, inst_pool, block_pool, stmt_pool}; + GotoPass goto_pass{cfg, stmt_pool}; Statement& root{goto_pass.RootStatement()}; IR::AbstractSyntaxList syntax_list; TranslatePass{inst_pool, block_pool, stmt_pool, env, root, syntax_list}; diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/atomic_operations_global_memory.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/atomic_operations_global_memory.cpp index 66f39e44e..d9f999e05 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/atomic_operations_global_memory.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/atomic_operations_global_memory.cpp @@ -59,14 +59,14 @@ IR::U32U64 ApplyIntegerAtomOp(IR::IREmitter& ir, const IR::U32U64& offset, const IR::Value ApplyFpAtomOp(IR::IREmitter& ir, const IR::U64& offset, const IR::Value& op_b, AtomOp op, AtomSize size) { static constexpr IR::FpControl f16_control{ - .no_contraction{false}, - .rounding{IR::FpRounding::RN}, - .fmz_mode{IR::FmzMode::DontCare}, + .no_contraction = false, + .rounding = IR::FpRounding::RN, + .fmz_mode = IR::FmzMode::DontCare, }; static constexpr IR::FpControl f32_control{ - .no_contraction{false}, - .rounding{IR::FpRounding::RN}, - .fmz_mode{IR::FmzMode::FTZ}, + .no_contraction = false, + .rounding = IR::FpRounding::RN, + .fmz_mode = IR::FmzMode::FTZ, }; switch (op) { case AtomOp::ADD: diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp index e0e157275..0b8119ddd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp @@ -104,7 +104,9 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) { .rounding = CastFpRounding(i2f.fp_rounding), .fmz_mode = IR::FmzMode::DontCare, }; - auto value{v.ir.ConvertIToF(dst_bitsize, conversion_src_bitsize, is_signed, src, fp_control)}; + auto value{v.ir.ConvertIToF(static_cast(dst_bitsize), + static_cast(conversion_src_bitsize), is_signed, src, + fp_control)}; if (i2f.neg != 0) { if (i2f.abs != 0 || !is_signed) { // We know the value is positive diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp index 7d7dcc3cb..924fb7a40 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp @@ -80,10 +80,10 @@ void TranslatorVisitor::ALD(u64 insn) { for (u32 element = 0; element < num_elements; ++element) { if (ald.patch != 0) { const IR::Patch patch{offset / 4 + element}; - F(ald.dest_reg + element, ir.GetPatch(patch)); + F(ald.dest_reg + static_cast(element), ir.GetPatch(patch)); } else { const IR::Attribute attr{offset / 4 + element}; - F(ald.dest_reg + element, ir.GetAttribute(attr, vertex)); + F(ald.dest_reg + static_cast(element), ir.GetAttribute(attr, vertex)); } } return; @@ -92,7 +92,7 @@ void TranslatorVisitor::ALD(u64 insn) { throw NotImplementedException("Indirect patch read"); } HandleIndexed(*this, ald.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { - F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset, vertex)); + F(ald.dest_reg + static_cast(element), ir.GetAttributeIndexed(final_offset, vertex)); }); } @@ -121,10 +121,10 @@ void TranslatorVisitor::AST(u64 insn) { for (u32 element = 0; element < num_elements; ++element) { if (ast.patch != 0) { const IR::Patch patch{offset / 4 + element}; - ir.SetPatch(patch, F(ast.src_reg + element)); + ir.SetPatch(patch, F(ast.src_reg + static_cast(element))); } else { const IR::Attribute attr{offset / 4 + element}; - ir.SetAttribute(attr, F(ast.src_reg + element), vertex); + ir.SetAttribute(attr, F(ast.src_reg + static_cast(element)), vertex); } } return; @@ -133,7 +133,7 @@ void TranslatorVisitor::AST(u64 insn) { throw NotImplementedException("Indexed tessellation patch store"); } HandleIndexed(*this, ast.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { - ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element), vertex); + ir.SetAttributeIndexed(final_offset, F(ast.src_reg + static_cast(element)), vertex); }); } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp index 44144f154..63b588ad4 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp @@ -69,9 +69,6 @@ TextureType GetType(Type type) { } IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) { - const auto array{[&](int index) { - return v.ir.BitFieldExtract(v.X(reg + index), v.ir.Imm32(0), v.ir.Imm32(16)); - }}; switch (type) { case Type::_1D: case Type::BUFFER_1D: diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp index 7dc793ad7..681220a8d 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp @@ -160,10 +160,10 @@ unsigned SwizzleMask(u64 swizzle) { IR::Value MakeColor(IR::IREmitter& ir, IR::Reg reg, int num_regs) { std::array colors; for (int i = 0; i < num_regs; ++i) { - colors[i] = ir.GetReg(reg + i); + colors[static_cast(i)] = ir.GetReg(reg + i); } for (int i = num_regs; i < 4; ++i) { - colors[i] = ir.Imm32(0); + colors[static_cast(i)] = ir.Imm32(0); } return ir.CompositeConstruct(colors[0], colors[1], colors[2], colors[3]); } @@ -211,12 +211,12 @@ void TranslatorVisitor::SULD(u64 insn) { if (is_typed) { const int num_regs{SizeInRegs(suld.size)}; for (int i = 0; i < num_regs; ++i) { - X(dest_reg + i, IR::U32{ir.CompositeExtract(result, i)}); + X(dest_reg + i, IR::U32{ir.CompositeExtract(result, static_cast(i))}); } } else { const unsigned mask{SwizzleMask(suld.swizzle)}; const int bits{std::popcount(mask)}; - if (!IR::IsAligned(dest_reg, bits == 3 ? 4 : bits)) { + if (!IR::IsAligned(dest_reg, bits == 3 ? 4 : static_cast(bits))) { throw NotImplementedException("Unaligned destination register"); } for (unsigned component = 0; component < 4; ++component) { diff --git a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp index 70449eeca..f9de17b25 100644 --- a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp +++ b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp @@ -314,8 +314,8 @@ std::optional Track(const IR::Value& value, const Bias* bias) return std::nullopt; } const StorageBufferAddr storage_buffer{ - .index{index.U32()}, - .offset{offset.U32()}, + .index = index.U32(), + .offset = offset.U32(), }; if (!Common::IsAligned(storage_buffer.offset, 16)) { // The SSBO pointer has to be aligned @@ -484,7 +484,7 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) { .cbuf_index = storage_buffer.index, .cbuf_offset = storage_buffer.offset, .count = 1, - .is_written{info.writes.contains(storage_buffer)}, + .is_written = info.writes.contains(storage_buffer), }); } for (const StorageInst& storage_inst : info.to_replace) { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 622267147..2bd48d697 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -104,9 +104,7 @@ public: template static auto MakeConfigureSpecFunc() { - return [](GraphicsPipeline* pipeline, bool is_indexed) { - pipeline->ConfigureImpl(is_indexed); - }; + return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl(is_indexed); }; } private: -- 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 +++++-- src/shader_recompiler/backend/glsl/emit_glsl.cpp | 9 +++++++-- .../frontend/maxwell/control_flow.cpp | 13 ++++++------- .../frontend/maxwell/structured_control_flow.cpp | 8 ++++---- .../frontend/maxwell/translate_program.cpp | 20 +++++++++++++------- .../ir_opt/constant_propagation_pass.cpp | 5 +++-- .../ir_opt/dead_code_elimination_pass.cpp | 2 -- src/shader_recompiler/ir_opt/dual_vertex_pass.cpp | 6 ------ .../ir_opt/global_memory_to_storage_buffer_pass.cpp | 1 - .../ir_opt/lower_int64_to_int32.cpp | 5 +++-- src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 10 ++++++---- 11 files changed, 47 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 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); } } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index c5e819a0a..8a430d573 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -2,8 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include +#include +#include #include "common/div_ceil.h" #include "common/settings.h" @@ -120,7 +122,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); } } diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp index e7abea82f..1a954a509 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -151,18 +150,18 @@ std::pair Stack::Pop(Token token) const { } std::optional Stack::Peek(Token token) const { - const auto reverse_entries{entries | std::views::reverse}; - const auto it{std::ranges::find(reverse_entries, token, &StackEntry::token)}; - if (it == reverse_entries.end()) { + const auto it{std::find_if(entries.rbegin(), entries.rend(), + [token](const auto& entry) { return entry.token == token; })}; + if (it == entries.rend()) { return std::nullopt; } return it->target; } Stack Stack::Remove(Token token) const { - const auto reverse_entries{entries | std::views::reverse}; - const auto it{std::ranges::find(reverse_entries, token, &StackEntry::token)}; - const auto pos{std::distance(reverse_entries.begin(), it)}; + const auto it{std::find_if(entries.rbegin(), entries.rend(), + [token](const auto& entry) { return entry.token == token; })}; + const auto pos{std::distance(entries.rbegin(), it)}; Stack result; result.entries.insert(result.entries.end(), entries.begin(), entries.end() - pos - 1); return result; diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 221454b99..8b3e0a15c 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -167,7 +166,7 @@ std::string DumpExpr(const Statement* stmt) { } } -std::string DumpTree(const Tree& tree, u32 indentation = 0) { +[[maybe_unused]] std::string DumpTree(const Tree& tree, u32 indentation = 0) { std::string ret; std::string indent(indentation, ' '); for (auto stmt = tree.begin(); stmt != tree.end(); ++stmt) { @@ -315,8 +314,9 @@ class GotoPass { public: explicit GotoPass(Flow::CFG& cfg, ObjectPool& stmt_pool) : pool{stmt_pool} { std::vector gotos{BuildTree(cfg)}; - for (const Node& goto_stmt : gotos | std::views::reverse) { - RemoveGoto(goto_stmt); + const auto end{gotos.rend()}; + for (auto goto_stmt = gotos.rbegin(); goto_stmt != end; ++goto_stmt) { + RemoveGoto(*goto_stmt); } } diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 83c77967d..c067d459c 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include "common/settings.h" @@ -20,12 +19,19 @@ namespace Shader::Maxwell { namespace { IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { - auto syntax_blocks{syntax_list | std::views::filter([](const auto& node) { - return node.type == IR::AbstractSyntaxNode::Type::Block; - })}; - IR::BlockList blocks(std::ranges::distance(syntax_blocks)); - std::ranges::transform(syntax_blocks, blocks.begin(), - [](const IR::AbstractSyntaxNode& node) { return node.data.block; }); + size_t num_syntax_blocks{}; + for (const auto& node : syntax_list) { + if (node.type == IR::AbstractSyntaxNode::Type::Block) { + ++num_syntax_blocks; + } + } + IR::BlockList blocks; + blocks.reserve(num_syntax_blocks); + for (const auto& node : syntax_list) { + if (node.type == IR::AbstractSyntaxNode::Type::Block) { + blocks.push_back(node.data.block); + } + } return blocks; } diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 3c72203ad..8dd6d6c2c 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include #include @@ -599,7 +598,9 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { } // Anonymous namespace void ConstantPropagationPass(IR::Program& program) { - for (IR::Block* const block : program.post_order_blocks | std::views::reverse) { + const auto end{program.post_order_blocks.rend()}; + for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { + IR::Block* const block{*it}; for (IR::Inst& inst : block->Instructions()) { ConstantPropagation(*block, inst); } diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp index 1e4a3fdae..400836301 100644 --- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp +++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include - #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/ir_opt/passes.h" diff --git a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp index 3d2c205c2..055ba9c54 100644 --- a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp +++ b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp @@ -2,12 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include -#include - -#include "common/bit_cast.h" -#include "common/bit_util.h" -#include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/ir_opt/passes.h" diff --git a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp index f9de17b25..4197b0095 100644 --- a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp +++ b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/src/shader_recompiler/ir_opt/lower_int64_to_int32.cpp b/src/shader_recompiler/ir_opt/lower_int64_to_int32.cpp index abf7c87c7..e80d3d1d9 100644 --- a/src/shader_recompiler/ir_opt/lower_int64_to_int32.cpp +++ b/src/shader_recompiler/ir_opt/lower_int64_to_int32.cpp @@ -2,7 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include #include #include "shader_recompiler/exception.h" @@ -207,7 +206,9 @@ void Lower(IR::Block& block, IR::Inst& inst) { } // Anonymous namespace void LowerInt64ToInt32(IR::Program& program) { - for (IR::Block* const block : program.post_order_blocks | std::views::reverse) { + const auto end{program.post_order_blocks.rend()}; + for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { + IR::Block* const block{*it}; for (IR::Inst& inst : block->Instructions()) { Lower(*block, inst); } diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index dcaced83f..53145fb5e 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -14,7 +14,6 @@ // https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6 // -#include #include #include #include @@ -243,7 +242,9 @@ public: void SealBlock(IR::Block* block) { const auto it{incomplete_phis.find(block)}; if (it != incomplete_phis.end()) { - for (auto& [variant, phi] : it->second) { + for (auto& pair : it->second) { + auto& variant{pair.first}; + auto& phi{pair.second}; std::visit([&](auto& variable) { AddPhiOperands(variable, *phi, block); }, variant); } } @@ -373,8 +374,9 @@ void VisitBlock(Pass& pass, IR::Block* block) { void SsaRewritePass(IR::Program& program) { Pass pass; - for (IR::Block* const block : program.post_order_blocks | std::views::reverse) { - VisitBlock(pass, block); + const auto end{program.post_order_blocks.rend()}; + for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) { + VisitBlock(pass, *block); } } -- cgit v1.2.3