mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-01 15:02:40 +00:00
ComputeValue rewrite
This commit is contained in:
parent
47cc275203
commit
301f51e57d
@ -630,6 +630,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||
src/common/assert.h
|
||||
src/common/bit_field.h
|
||||
src/common/bounded_threadsafe_queue.h
|
||||
src/common/cartesian_invoke.h
|
||||
src/common/concepts.h
|
||||
src/common/config.cpp
|
||||
src/common/config.h
|
||||
@ -845,6 +846,21 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
||||
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
||||
src/shader_recompiler/ir/compute_value/compute.cpp
|
||||
src/shader_recompiler/ir/compute_value/compute.h
|
||||
src/shader_recompiler/ir/compute_value/do_bitcast.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_bitcast.h
|
||||
src/shader_recompiler/ir/compute_value/do_composite.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_composite.h
|
||||
src/shader_recompiler/ir/compute_value/do_convert.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_convert.h
|
||||
src/shader_recompiler/ir/compute_value/do_float_operations.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_float_operations.h
|
||||
src/shader_recompiler/ir/compute_value/do_integer_operations.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_integer_operations.h
|
||||
src/shader_recompiler/ir/compute_value/do_logical_operations.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_logical_operations.h
|
||||
src/shader_recompiler/ir/compute_value/do_nop_functions.h
|
||||
src/shader_recompiler/ir/compute_value/do_packing.cpp
|
||||
src/shader_recompiler/ir/compute_value/do_packing.h
|
||||
src/shader_recompiler/ir/compute_value/imm_value.cpp
|
||||
src/shader_recompiler/ir/compute_value/imm_value.h
|
||||
src/shader_recompiler/ir/abstract_syntax_list.cpp
|
||||
|
43
src/common/cartesian_invoke.h
Normal file
43
src/common/cartesian_invoke.h
Normal file
@ -0,0 +1,43 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace Common {
|
||||
namespace Detail {
|
||||
|
||||
template <typename Func, typename OutputIt, std::size_t N, std::size_t Level, typename... ArgLists>
|
||||
void CartesianInvokeImpl(Func func, OutputIt out_it,
|
||||
std::tuple<typename ArgLists::const_iterator...>& arglists_its,
|
||||
const std::tuple<const ArgLists&...>& arglists_tuple) {
|
||||
if constexpr (Level == N) {
|
||||
auto get_tuple = [&]<std::size_t... I>(std::index_sequence<I...>) {
|
||||
return std::forward_as_tuple(*std::get<I>(arglists_its)...);
|
||||
};
|
||||
*out_it++ = std::move(std::apply(func, get_tuple(std::make_index_sequence<N>{})));
|
||||
return;
|
||||
} else {
|
||||
const auto& arglist = std::get<Level>(arglists_tuple);
|
||||
for (auto it = arglist.begin(); it != arglist.end(); ++it) {
|
||||
std::get<Level>(arglists_its) = it;
|
||||
CartesianInvokeImpl<Func, OutputIt, N, Level + 1, ArgLists...>(
|
||||
func, out_it, arglists_its, arglists_tuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
template <typename Func, typename OutputIt, typename... ArgLists>
|
||||
void CartesianInvoke(Func func, OutputIt out_it, const ArgLists&... arg_lists) {
|
||||
constexpr std::size_t N = sizeof...(ArgLists);
|
||||
const std::tuple<const ArgLists&...> arglists_tuple = std::forward_as_tuple(arg_lists...);
|
||||
|
||||
std::tuple<typename ArgLists::const_iterator...> arglists_it;
|
||||
Detail::CartesianInvokeImpl<Func, OutputIt, N, 0, ArgLists...>(func, out_it, arglists_it,
|
||||
arglists_tuple);
|
||||
}
|
||||
|
||||
} // namespace Common
|
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -2,724 +2,51 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "common/func_traits.h"
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_bitcast.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_composite.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_convert.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_float_operations.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_integer_operations.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_logical_operations.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_nop_functions.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_packing.h"
|
||||
|
||||
namespace Shader::IR {
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
template <typename Func, typename OutputIt, size_t N, size_t Level, typename... ArgLists>
|
||||
static void CartesianInvokeImpl(Func func, OutputIt out_it,
|
||||
std::tuple<typename ArgLists::const_iterator...>& arglists_its,
|
||||
const std::tuple<const ArgLists&...>& arglists_tuple) {
|
||||
if constexpr (Level == N) {
|
||||
auto get_tuple = [&]<size_t... I>(std::index_sequence<I...>) {
|
||||
return std::forward_as_tuple(*std::get<I>(arglists_its)...);
|
||||
};
|
||||
*out_it++ = std::move(std::apply(func, get_tuple(std::make_index_sequence<N>{})));
|
||||
return;
|
||||
} else {
|
||||
const auto& arglist = std::get<Level>(arglists_tuple);
|
||||
for (auto it = arglist.begin(); it != arglist.end(); ++it) {
|
||||
std::get<Level>(arglists_its) = it;
|
||||
CartesianInvokeImpl<Func, OutputIt, N, Level + 1, ArgLists...>(
|
||||
func, out_it, arglists_its, arglists_tuple);
|
||||
}
|
||||
template <auto func, size_t... I>
|
||||
static void Invoke(ImmValueList& inst_values, const std::array<ImmValueList, sizeof...(I)>& args,
|
||||
std::index_sequence<I...>) {
|
||||
func(inst_values, args[I]...);
|
||||
}
|
||||
|
||||
template <auto func>
|
||||
static void Invoke(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
using Traits = Common::FuncTraits<decltype(func)>;
|
||||
constexpr size_t num_args = Traits::NUM_ARGS - 1;
|
||||
ASSERT(inst->NumArgs() >= num_args);
|
||||
std::array<ImmValueList, num_args> args{};
|
||||
for (size_t i = 0; i < num_args; ++i) {
|
||||
Compute(inst->Arg(i), args[i], cache);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func, typename OutputIt, typename... ArgLists>
|
||||
static void CartesianInvoke(Func func, OutputIt out_it, const ArgLists&... arg_lists) {
|
||||
constexpr size_t N = sizeof...(ArgLists);
|
||||
const std::tuple<const ArgLists&...> arglists_tuple = std::forward_as_tuple(arg_lists...);
|
||||
|
||||
std::tuple<typename ArgLists::const_iterator...> arglists_it;
|
||||
CartesianInvokeImpl<Func, OutputIt, N, 0, ArgLists...>(func, out_it, arglists_it,
|
||||
arglists_tuple);
|
||||
}
|
||||
|
||||
static void SetSigned(ImmValueList& values, bool is_signed) {
|
||||
for (auto& value : values) {
|
||||
value.SetSigned(is_signed);
|
||||
}
|
||||
}
|
||||
|
||||
static void OperationAbs(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.abs(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationAdd(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a + b; };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationSub(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a - b; };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationFma(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1, args2;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
ComputeImmValues(inst->Arg(2), args2, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& c) {
|
||||
return ImmValue::fma(ImmF32F64(a), ImmF32F64(b), ImmF32F64(c));
|
||||
};
|
||||
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1, args2);
|
||||
}
|
||||
|
||||
static void OperationMin(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1, is_legacy_args;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
if (inst->NumArgs() > 2) {
|
||||
ComputeImmValues(inst->Arg(2), is_legacy_args, cache);
|
||||
} else {
|
||||
is_legacy_args.insert(ImmValue(false));
|
||||
}
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& is_legacy) {
|
||||
if (is_legacy.U1()) {
|
||||
if (a.isnan())
|
||||
return b;
|
||||
if (b.isnan())
|
||||
return a;
|
||||
}
|
||||
return std::min(a, b);
|
||||
};
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1,
|
||||
is_legacy_args);
|
||||
}
|
||||
|
||||
static void OperationMax(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1, is_legacy_args;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
if (inst->NumArgs() > 2) {
|
||||
ComputeImmValues(inst->Arg(2), is_legacy_args, cache);
|
||||
} else {
|
||||
is_legacy_args.insert(ImmValue(false));
|
||||
}
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& is_legacy) {
|
||||
if (is_legacy.U1()) {
|
||||
if (a.isnan())
|
||||
return b;
|
||||
if (b.isnan())
|
||||
return a;
|
||||
}
|
||||
return std::max(a, b);
|
||||
};
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1,
|
||||
is_legacy_args);
|
||||
}
|
||||
|
||||
static void OperationMul(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a * b; };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationDiv(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a / b; };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationMod(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a % b; };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationNeg(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return -a; };
|
||||
|
||||
SetSigned(args, true);
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationRecip(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.recip(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationRecipSqrt(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.rsqrt(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationSqrt(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.sqrt(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationSin(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.sin(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationExp2(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.exp2(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationLdexp(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a.ldexp(ImmU32(b)); };
|
||||
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationCos(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.cos(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationLog2(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.log2(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationClamp(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1, args2;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
ComputeImmValues(inst->Arg(2), args2, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& c) {
|
||||
return a.clamp(b, c);
|
||||
};
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, is_signed);
|
||||
SetSigned(args2, is_signed);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1, args2);
|
||||
}
|
||||
|
||||
static void OperationRound(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.round(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationFloor(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.floor(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationCeil(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.ceil(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationTrunc(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.trunc(); };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationFract(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return a.fract(); };
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationShiftLeft(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a << ImmU32(b); };
|
||||
|
||||
SetSigned(args1, false);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationShiftRight(Inst* inst, bool is_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a >> ImmU32(b); };
|
||||
|
||||
SetSigned(args0, is_signed);
|
||||
SetSigned(args1, false);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationBitwiseNot(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a) { return ~a; };
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationBitwiseAnd(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a & b; };
|
||||
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationBitwiseOr(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a | b; };
|
||||
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationBitwiseXor(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a ^ b; };
|
||||
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationConvert(Inst* inst, bool is_signed, Type new_type, bool new_signed,
|
||||
ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [new_type, new_signed](const ImmValue& a) {
|
||||
return a.Convert(new_type, new_signed);
|
||||
};
|
||||
|
||||
SetSigned(args, is_signed);
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
static void OperationBitCast(Inst* inst, Type new_type, bool new_signed, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args;
|
||||
ComputeImmValues(inst->Arg(0), args, cache);
|
||||
|
||||
const auto op = [new_type, new_signed](const ImmValue& a) {
|
||||
return a.Bitcast(new_type, new_signed);
|
||||
};
|
||||
|
||||
std::transform(args.begin(), args.end(), std::inserter(inst_values, inst_values.begin()), op);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static void OperationCompositeConstruct(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
std::array<ImmValueList, N> args;
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
ComputeImmValues(inst->Arg(i), args[i], cache);
|
||||
}
|
||||
|
||||
const auto op = []<typename... Args>(const Args&... args) { return ImmValue(args...); };
|
||||
|
||||
const auto call_cartesian = [&]<size_t... I>(std::index_sequence<I...>) {
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args[I]...);
|
||||
};
|
||||
call_cartesian(std::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
static void OperationCompositeExtract(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) { return a.Extract(ImmU32(b)); };
|
||||
|
||||
SetSigned(args1, false);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1);
|
||||
}
|
||||
|
||||
static void OperationInsert(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
||||
ImmValueList args0, args1, args2;
|
||||
ComputeImmValues(inst->Arg(0), args0, cache);
|
||||
ComputeImmValues(inst->Arg(1), args1, cache);
|
||||
ComputeImmValues(inst->Arg(2), args2, cache);
|
||||
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& c) {
|
||||
return a.Insert(b, ImmU32(c));
|
||||
};
|
||||
|
||||
SetSigned(args2, false);
|
||||
CartesianInvoke(op, std::inserter(inst_values, inst_values.begin()), args0, args1, args2);
|
||||
Invoke<func>(inst_values, args, std::make_index_sequence<num_args>{});
|
||||
}
|
||||
|
||||
static void DoInstructionOperation(Inst* inst, ImmValueList& inst_values,
|
||||
ComputeImmValuesCache& cache) {
|
||||
switch (inst->GetOpcode()) {
|
||||
case Opcode::CompositeConstructU32x2:
|
||||
case Opcode::CompositeConstructU32x2x2:
|
||||
case Opcode::CompositeConstructF16x2:
|
||||
case Opcode::CompositeConstructF32x2:
|
||||
case Opcode::CompositeConstructF32x2x2:
|
||||
case Opcode::CompositeConstructF64x2:
|
||||
OperationCompositeConstruct<2>(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::CompositeConstructU32x3:
|
||||
case Opcode::CompositeConstructF16x3:
|
||||
case Opcode::CompositeConstructF32x3:
|
||||
case Opcode::CompositeConstructF64x3:
|
||||
OperationCompositeConstruct<3>(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::CompositeConstructU32x4:
|
||||
case Opcode::CompositeConstructF16x4:
|
||||
case Opcode::CompositeConstructF32x4:
|
||||
case Opcode::CompositeConstructF64x4:
|
||||
OperationCompositeConstruct<4>(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::CompositeExtractU32x2:
|
||||
case Opcode::CompositeExtractU32x3:
|
||||
case Opcode::CompositeExtractU32x4:
|
||||
case Opcode::CompositeExtractF16x2:
|
||||
case Opcode::CompositeExtractF16x3:
|
||||
case Opcode::CompositeExtractF16x4:
|
||||
case Opcode::CompositeExtractF32x2:
|
||||
case Opcode::CompositeExtractF32x3:
|
||||
case Opcode::CompositeExtractF32x4:
|
||||
case Opcode::CompositeExtractF64x2:
|
||||
case Opcode::CompositeExtractF64x3:
|
||||
case Opcode::CompositeExtractF64x4:
|
||||
OperationCompositeExtract(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::CompositeInsertU32x2:
|
||||
case Opcode::CompositeInsertU32x3:
|
||||
case Opcode::CompositeInsertU32x4:
|
||||
case Opcode::CompositeInsertF16x2:
|
||||
case Opcode::CompositeInsertF16x3:
|
||||
case Opcode::CompositeInsertF16x4:
|
||||
case Opcode::CompositeInsertF32x2:
|
||||
case Opcode::CompositeInsertF32x3:
|
||||
case Opcode::CompositeInsertF32x4:
|
||||
case Opcode::CompositeInsertF64x2:
|
||||
case Opcode::CompositeInsertF64x3:
|
||||
case Opcode::CompositeInsertF64x4:
|
||||
OperationInsert(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastU16F16:
|
||||
OperationBitCast(inst, IR::Type::U16, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastU32F32:
|
||||
OperationBitCast(inst, IR::Type::U32, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastU64F64:
|
||||
OperationBitCast(inst, IR::Type::U64, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastF16U16:
|
||||
OperationBitCast(inst, IR::Type::F16, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastF32U32:
|
||||
OperationBitCast(inst, IR::Type::F32, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitCastF64U64:
|
||||
OperationBitCast(inst, IR::Type::F64, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPAbs32:
|
||||
case Opcode::FPAbs64:
|
||||
case Opcode::IAbs32:
|
||||
OperationAbs(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPAdd32:
|
||||
case Opcode::FPAdd64:
|
||||
OperationAdd(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::IAdd32:
|
||||
case Opcode::IAdd64:
|
||||
OperationAdd(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPSub32:
|
||||
OperationSub(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ISub32:
|
||||
case Opcode::ISub64:
|
||||
OperationSub(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPMul32:
|
||||
case Opcode::FPMul64:
|
||||
OperationMul(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::IMul32:
|
||||
case Opcode::IMul64:
|
||||
OperationMul(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPDiv32:
|
||||
case Opcode::FPDiv64:
|
||||
case Opcode::SDiv32:
|
||||
OperationDiv(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::UDiv32:
|
||||
OperationDiv(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::SMod32:
|
||||
OperationMod(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::UMod32:
|
||||
OperationMod(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::INeg32:
|
||||
case Opcode::INeg64:
|
||||
OperationNeg(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPFma32:
|
||||
case Opcode::FPFma64:
|
||||
OperationFma(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPMin32:
|
||||
case Opcode::FPMin64:
|
||||
case Opcode::SMin32:
|
||||
OperationMin(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::UMin32:
|
||||
OperationMin(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPMax32:
|
||||
case Opcode::FPMax64:
|
||||
case Opcode::SMax32:
|
||||
OperationMax(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::UMax32:
|
||||
OperationMax(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPNeg32:
|
||||
case Opcode::FPNeg64:
|
||||
OperationNeg(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPRecip32:
|
||||
case Opcode::FPRecip64:
|
||||
OperationRecip(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPRecipSqrt32:
|
||||
case Opcode::FPRecipSqrt64:
|
||||
OperationRecipSqrt(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPSqrt:
|
||||
OperationSqrt(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPSin:
|
||||
OperationSin(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPCos:
|
||||
OperationCos(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPExp2:
|
||||
OperationExp2(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPLdexp:
|
||||
OperationLdexp(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPLog2:
|
||||
OperationLog2(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPClamp32:
|
||||
case Opcode::FPClamp64:
|
||||
case Opcode::SClamp32:
|
||||
OperationClamp(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::UClamp32:
|
||||
OperationClamp(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPRoundEven32:
|
||||
case Opcode::FPRoundEven64:
|
||||
OperationRound(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPFloor32:
|
||||
case Opcode::FPFloor64:
|
||||
OperationFloor(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPCeil32:
|
||||
case Opcode::FPCeil64:
|
||||
OperationCeil(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPTrunc32:
|
||||
case Opcode::FPTrunc64:
|
||||
OperationTrunc(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::FPFract32:
|
||||
case Opcode::FPFract64:
|
||||
OperationFract(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ShiftLeftLogical32:
|
||||
case Opcode::ShiftLeftLogical64:
|
||||
OperationShiftLeft(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ShiftRightLogical32:
|
||||
case Opcode::ShiftRightLogical64:
|
||||
OperationShiftRight(inst, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ShiftRightArithmetic32:
|
||||
case Opcode::ShiftRightArithmetic64:
|
||||
OperationShiftRight(inst, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitwiseAnd32:
|
||||
case Opcode::BitwiseAnd64:
|
||||
case Opcode::LogicalAnd:
|
||||
OperationBitwiseAnd(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitwiseOr32:
|
||||
case Opcode::BitwiseOr64:
|
||||
case Opcode::LogicalOr:
|
||||
OperationBitwiseOr(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitwiseXor32:
|
||||
case Opcode::LogicalXor:
|
||||
OperationBitwiseXor(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::BitwiseNot32:
|
||||
case Opcode::LogicalNot:
|
||||
OperationBitwiseNot(inst, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertU16U32:
|
||||
OperationConvert(inst, false, Type::U16, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertS32F32:
|
||||
case Opcode::ConvertS32F64:
|
||||
OperationConvert(inst, true, Type::U32, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertU32F32:
|
||||
OperationConvert(inst, true, Type::U32, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertU32U16:
|
||||
OperationConvert(inst, false, Type::U32, false, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertF32F16:
|
||||
case Opcode::ConvertF32F64:
|
||||
case Opcode::ConvertF32S32:
|
||||
OperationConvert(inst, true, Type::F32, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertF32U32:
|
||||
OperationConvert(inst, false, Type::F32, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertF64F32:
|
||||
case Opcode::ConvertF64S32:
|
||||
OperationConvert(inst, true, Type::F64, true, inst_values, cache);
|
||||
break;
|
||||
case Opcode::ConvertF64U32:
|
||||
OperationConvert(inst, false, Type::F64, true, inst_values, cache);
|
||||
#define OPCODE(name, result_type, ...) \
|
||||
case Opcode::name: \
|
||||
Invoke<&Do##name>(inst, inst_values, cache); \
|
||||
break;
|
||||
#include "shader_recompiler/ir/opcodes.inc"
|
||||
#undef OPCODE
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE_MSG("Invalid opcode: {}", inst->GetOpcode());
|
||||
}
|
||||
|
||||
static bool IsSelectInst(Inst* inst) {
|
||||
@ -737,7 +64,7 @@ static bool IsSelectInst(Inst* inst) {
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeImmValues(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache) {
|
||||
void Compute(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache) {
|
||||
Value resolved = value.Resolve();
|
||||
if (ImmValue::IsSupportedValue(resolved)) {
|
||||
values.insert(ImmValue(resolved));
|
||||
@ -755,16 +82,16 @@ void ComputeImmValues(const Value& value, ImmValueList& values, ComputeImmValues
|
||||
auto& inst_values = cache.emplace(inst, ImmValueList{}).first->second;
|
||||
if (inst->GetOpcode() == Opcode::Phi) {
|
||||
for (size_t i = 0; i < inst->NumArgs(); ++i) {
|
||||
ComputeImmValues(inst->Arg(i), inst_values, cache);
|
||||
Compute(inst->Arg(i), inst_values, cache);
|
||||
}
|
||||
}
|
||||
if (IsSelectInst(inst)) {
|
||||
ComputeImmValues(inst->Arg(1), inst_values, cache);
|
||||
ComputeImmValues(inst->Arg(2), inst_values, cache);
|
||||
Compute(inst->Arg(1), inst_values, cache);
|
||||
Compute(inst->Arg(2), inst_values, cache);
|
||||
} else {
|
||||
DoInstructionOperation(inst, inst_values, cache);
|
||||
}
|
||||
values.insert(inst_values.begin(), inst_values.end());
|
||||
}
|
||||
|
||||
} // namespace Shader::IR
|
||||
} // namespace Shader::IR::ComputeValue
|
@ -3,8 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include "shader_recompiler/ir/compute_value/imm_value.h"
|
||||
#include "shader_recompiler/ir/value.h"
|
||||
|
||||
@ -12,11 +12,11 @@
|
||||
// that can represent. If the value can't be computed statically, the list will
|
||||
// be empty.
|
||||
|
||||
namespace Shader::IR {
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
using ImmValueList = boost::container::flat_set<ImmValue>;
|
||||
using ImmValueList = std::unordered_set<ImmValue>;
|
||||
using ComputeImmValuesCache = boost::container::flat_map<Inst*, ImmValueList>;
|
||||
|
||||
void ComputeImmValues(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache);
|
||||
void Compute(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache);
|
||||
|
||||
} // namespace Shader::IR
|
||||
} // namespace Shader::IR::ComputeValue
|
32
src/shader_recompiler/ir/compute_value/do_bitcast.cpp
Normal file
32
src/shader_recompiler/ir/compute_value/do_bitcast.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/do_bitcast.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoBitCastU16F16(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
void DoBitCastU32F32(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
void DoBitCastU64F64(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
void DoBitCastF16U16(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
void DoBitCastF32U32(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
void DoBitCastF64U64(ImmValueList& inst_values, const ImmValueList& src_values) {
|
||||
inst_values.insert(src_values.begin(), src_values.end());
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
17
src/shader_recompiler/ir/compute_value/do_bitcast.h
Normal file
17
src/shader_recompiler/ir/compute_value/do_bitcast.h
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoBitCastU16F16(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
void DoBitCastU32F32(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
void DoBitCastU64F64(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
void DoBitCastF16U16(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
void DoBitCastF32U32(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
void DoBitCastF64U64(ImmValueList& inst_values, const ImmValueList& src_values);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
230
src/shader_recompiler/ir/compute_value/do_composite.cpp
Normal file
230
src/shader_recompiler/ir/compute_value/do_composite.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_composite.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
static void CommonCompositeConstruct(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b) {
|
||||
return ImmValue(a, b);
|
||||
};
|
||||
Common::CartesianInvoke(op, std::insert_iterator(inst_values, inst_values.begin()), arg0, arg1);
|
||||
}
|
||||
|
||||
static void CommonCompositeConstruct(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& c) {
|
||||
return ImmValue(a, b, c);
|
||||
};
|
||||
Common::CartesianInvoke(op, std::insert_iterator(inst_values, inst_values.begin()), arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
static void CommonCompositeConstruct(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3) {
|
||||
const auto op = [](const ImmValue& a, const ImmValue& b, const ImmValue& c, const ImmValue& d) {
|
||||
return ImmValue(a, b, c, d);
|
||||
};
|
||||
Common::CartesianInvoke(op, std::insert_iterator(inst_values, inst_values.begin()), arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void DoCompositeConstructU32x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeConstructU32x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
void DoCompositeConstructU32x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void DoCompositeConstructU32x2x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
Common::CartesianInvoke(ImmValue::CompositeFrom2x2, std::insert_iterator(inst_values, inst_values.begin()), arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeExtractU32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractU32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractU32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertU32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertU32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertU32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeShuffleU32x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleU32x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleU32x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeConstructF16x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF16x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF16x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF32x2x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
Common::CartesianInvoke(ImmValue::CompositeFrom2x2, std::insert_iterator(inst_values, inst_values.begin()), arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF16x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF16x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF16x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF16x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF16x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF16x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF16x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF16x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF16x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeConstructF32x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF32x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF32x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF32x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF32x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF32x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeConstructF64x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF64x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
void DoCompositeConstructF64x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3) {
|
||||
CommonCompositeConstruct(inst_values, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF64x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF64x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeExtractF64x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Extract, std::insert_iterator(inst_values, inst_values.begin()), vec, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF64x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF64x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeInsertF64x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx) {
|
||||
Common::CartesianInvoke(ImmValue::Insert, std::insert_iterator(inst_values, inst_values.begin()), vec, val, idx);
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF64x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF64x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoCompositeShuffleF64x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
64
src/shader_recompiler/ir/compute_value/do_composite.h
Normal file
64
src/shader_recompiler/ir/compute_value/do_composite.h
Normal file
@ -0,0 +1,64 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoCompositeConstructU32x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeConstructU32x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoCompositeConstructU32x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3);
|
||||
void DoCompositeConstructU32x2x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeExtractU32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractU32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractU32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeInsertU32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertU32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertU32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeShuffleU32x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1);
|
||||
void DoCompositeShuffleU32x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2);
|
||||
void DoCompositeShuffleU32x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3);
|
||||
|
||||
void DoCompositeConstructF16x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeConstructF16x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoCompositeConstructF16x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3);
|
||||
void DoCompositeExtractF16x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF16x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF16x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeInsertF16x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF16x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF16x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeShuffleF16x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1);
|
||||
void DoCompositeShuffleF16x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2);
|
||||
void DoCompositeShuffleF16x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3);
|
||||
|
||||
void DoCompositeConstructF32x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeConstructF32x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoCompositeConstructF32x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3);
|
||||
void DoCompositeConstructF32x2x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeExtractF32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeInsertF32x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF32x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF32x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeShuffleF32x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1);
|
||||
void DoCompositeShuffleF32x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2);
|
||||
void DoCompositeShuffleF32x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3);
|
||||
|
||||
void DoCompositeConstructF64x2(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1);
|
||||
void DoCompositeConstructF64x3(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoCompositeConstructF64x4(ImmValueList& inst_values, const ImmValueList& arg0, const ImmValueList& arg1, const ImmValueList& arg2, const ImmValueList& arg3);
|
||||
void DoCompositeExtractF64x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF64x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeExtractF64x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& idx);
|
||||
void DoCompositeInsertF64x2(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF64x3(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeInsertF64x4(ImmValueList& inst_values, const ImmValueList& vec, const ImmValueList& val, const ImmValueList& idx);
|
||||
void DoCompositeShuffleF64x2(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1);
|
||||
void DoCompositeShuffleF64x3(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2);
|
||||
void DoCompositeShuffleF64x4(ImmValueList& inst_values, const ImmValueList& vec0, const ImmValueList& vec1, const ImmValueList& idx0, const ImmValueList& idx1, const ImmValueList& idx2, const ImmValueList& idx3);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
81
src/shader_recompiler/ir/compute_value/do_convert.cpp
Normal file
81
src/shader_recompiler/ir/compute_value/do_convert.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_convert.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoConvertS32F32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::U32, true, Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertS32F64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::U32, true, Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertU32F32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::U32, false, Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF16F32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
// Common::CartesianInvoke(ImmValue::Convert<Type::F16, true, Type::F32, true>,
|
||||
// std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
UNREACHABLE_MSG("F32 to F16 conversion is not implemented");
|
||||
}
|
||||
|
||||
void DoConvertF32F16(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
// Common::CartesianInvoke(ImmValue::Convert<Type::F32, true, Type::F16, true>,
|
||||
// std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
UNREACHABLE_MSG("F16 to F32 conversion is not implemented");
|
||||
}
|
||||
|
||||
void DoConvertF32F64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F32, true, Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF64F32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F64, true, Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF32S32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F32, true, Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF32U32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F32, true, Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF64S32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F64, true, Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF64U32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F64, true, Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertF32U16(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::F32, true, Type::U16, false>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertU16U32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::U16, false, Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
void DoConvertU32U16(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Convert<Type::U32, false, Type::U16, false>,
|
||||
std::insert_iterator(inst_values, inst_values.begin()), args);
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
25
src/shader_recompiler/ir/compute_value/do_convert.h
Normal file
25
src/shader_recompiler/ir/compute_value/do_convert.h
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoConvertS32F32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertS32F64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertU32F32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF16F32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF32F16(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF32F64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF64F32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF32S32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF32U32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF64S32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF64U32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertF32U16(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertU16U32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoConvertU32U16(ImmValueList& inst_values, const ImmValueList& args);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
254
src/shader_recompiler/ir/compute_value/do_float_operations.cpp
Normal file
254
src/shader_recompiler/ir/compute_value/do_float_operations.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_float_operations.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoFPAbs32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Abs<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPAbs64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Abs<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPAdd32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Add<Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPAdd64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Add<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPSub32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Sub<Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPFma32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args2) {
|
||||
Common::CartesianInvoke(ImmValue::Fma<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1,
|
||||
args2);
|
||||
}
|
||||
|
||||
void DoFPFma64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args2) {
|
||||
Common::CartesianInvoke(ImmValue::Fma<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1,
|
||||
args2);
|
||||
}
|
||||
|
||||
void DoFPMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args_legacy) {
|
||||
const auto& op = [](const ImmValue& a, const ImmValue& b, const ImmValue& legacy) {
|
||||
if (legacy.U1()) {
|
||||
if (ImmValue::IsNan<Type::F32>(a))
|
||||
return b;
|
||||
if (ImmValue::IsNan<Type::F32>(b))
|
||||
return a;
|
||||
}
|
||||
return ImmValue::Max<Type::F32, true>(a, b);
|
||||
};
|
||||
Common::CartesianInvoke(op, std::insert_iterator(inst_values, inst_values.end()), args0, args1,
|
||||
args_legacy);
|
||||
}
|
||||
|
||||
void DoFPMax64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Max<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args_legacy) {
|
||||
const auto& op = [](const ImmValue& a, const ImmValue& b, const ImmValue& legacy) {
|
||||
if (legacy.U1()) {
|
||||
if (ImmValue::IsNan<Type::F64>(a))
|
||||
return b;
|
||||
if (ImmValue::IsNan<Type::F64>(b))
|
||||
return a;
|
||||
}
|
||||
return ImmValue::Min<Type::F32, true>(a, b);
|
||||
};
|
||||
Common::CartesianInvoke(op, std::insert_iterator(inst_values, inst_values.end()), args0, args1,
|
||||
args_legacy);
|
||||
}
|
||||
|
||||
void DoFPMin64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Min<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPMul32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mul<Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPMul64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mul<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Div<Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPDiv64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Div<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoFPNeg32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Neg<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPNeg64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Neg<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPRecip32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Recip<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPRecip64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Recip<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPRecipSqrt32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Rsqrt<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPRecipSqrt64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Rsqrt<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPSqrt(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Sqrt<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPSin(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Sin<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPExp2(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Exp2<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPLdexp(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& exponents) {
|
||||
Common::CartesianInvoke(ImmValue::Ldexp<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, exponents);
|
||||
}
|
||||
|
||||
void DoFPCos(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Cos<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPLog2(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Log2<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPSaturate32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPSaturate32 not implemented");
|
||||
}
|
||||
|
||||
void DoFPSaturate64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPSaturate64 not implemented");
|
||||
}
|
||||
|
||||
void DoFPClamp32(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& mins,
|
||||
const ImmValueList& maxs) {
|
||||
Common::CartesianInvoke(ImmValue::Clamp<Type::F32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, mins, maxs);
|
||||
}
|
||||
|
||||
void DoFPClamp64(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& mins,
|
||||
const ImmValueList& maxs) {
|
||||
Common::CartesianInvoke(ImmValue::Clamp<Type::F64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, mins, maxs);
|
||||
}
|
||||
|
||||
void DoFPRoundEven32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Round<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPRoundEven64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Round<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPFloor32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Floor<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPFloor64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Floor<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPCeil32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Ceil<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPCeil64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Ceil<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPTrunc32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Trunc<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPTrunc64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Trunc<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPFract32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Fract<Type::F32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPFract64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Fract<Type::F64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoFPFrexpSig32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPFrexpSig32 not implemented");
|
||||
}
|
||||
|
||||
void DoFPFrexpSig64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPFrexpSig64 not implemented");
|
||||
}
|
||||
|
||||
void DoFPFrexpExp32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPFrexpExp32 not implemented");
|
||||
}
|
||||
|
||||
void DoFPFrexpExp64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
UNREACHABLE_MSG("FPFrexpExp64 not implemented");
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
62
src/shader_recompiler/ir/compute_value/do_float_operations.h
Normal file
62
src/shader_recompiler/ir/compute_value/do_float_operations.h
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoFPAbs32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPAbs64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPAdd32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPAdd64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPSub32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPFma32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args2);
|
||||
void DoFPFma64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args2);
|
||||
void DoFPMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args_legacy);
|
||||
void DoFPMax64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1,
|
||||
const ImmValueList& args_legacy);
|
||||
void DoFPMin64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPMul32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPMul64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPDiv64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoFPNeg32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPNeg64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPRecip32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPRecip64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPRecipSqrt32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPRecipSqrt64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPSqrt(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPSin(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPExp2(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPLdexp(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& exponents);
|
||||
void DoFPCos(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPLog2(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPSaturate32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPSaturate64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPClamp32(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& mins,
|
||||
const ImmValueList& maxs);
|
||||
void DoFPClamp64(ImmValueList& inst_values, const ImmValueList& args, const ImmValueList& mins,
|
||||
const ImmValueList& maxs);
|
||||
void DoFPRoundEven32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPRoundEven64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFloor32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFloor64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPCeil32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPCeil64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPTrunc32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPTrunc64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFract32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFract64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFrexpSig32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFrexpSig64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFrexpExp32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoFPFrexpExp64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
233
src/shader_recompiler/ir/compute_value/do_integer_operations.cpp
Normal file
233
src/shader_recompiler/ir/compute_value/do_integer_operations.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_integer_operations.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoIAdd32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Add<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoIAdd64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Add<Type::U64, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoIAddCary32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
UNREACHABLE_MSG("IAddCary32 not implemented");
|
||||
}
|
||||
|
||||
void DoISub32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Sub<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoISub64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Sub<Type::U64, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoIMul32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mul<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoIMul64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mul<Type::U64, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoSMulExt(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
UNREACHABLE_MSG("SMulExt not implemented");
|
||||
}
|
||||
|
||||
void DoUMulExt(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
UNREACHABLE_MSG("UMulExt not implemented");
|
||||
}
|
||||
|
||||
void DoSDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Div<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoUDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Div<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoSMod32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mod<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoUMod32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Mod<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoINeg32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Neg<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoINeg64(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Neg<Type::U64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoIAbs32(ImmValueList& inst_values, const ImmValueList& args) {
|
||||
Common::CartesianInvoke(ImmValue::Abs<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args);
|
||||
}
|
||||
|
||||
void DoShiftLeftLogical32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::LShift<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoShiftLeftLogical64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::LShift<Type::U64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoShiftRightLogical32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::RShift<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoShiftRightLogical64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::RShift<Type::U64, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoShiftRightArithmetic32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::RShift<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoShiftRightArithmetic64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift) {
|
||||
Common::CartesianInvoke(ImmValue::RShift<Type::U64, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args, shift);
|
||||
}
|
||||
|
||||
void DoBitwiseAnd32(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::And<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoBitwiseAnd64(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::And<Type::U64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoBitwiseOr32(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Or<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoBitwiseOr64(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Or<Type::U64>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoBitwiseXor32(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Xor<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoBitFieldInsert(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& insert, const ImmValueList& offset,
|
||||
const ImmValueList& count) {
|
||||
UNREACHABLE_MSG("BitFieldInsert not implemented");
|
||||
}
|
||||
|
||||
void DoBitFieldSExtract(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& offset, const ImmValueList& count) {
|
||||
UNREACHABLE_MSG("BitFieldSExtract not implemented");
|
||||
}
|
||||
|
||||
void DoBitFieldUExtract(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& offset, const ImmValueList& count) {
|
||||
UNREACHABLE_MSG("BitFieldUExtract not implemented");
|
||||
}
|
||||
|
||||
void DoBitReverse32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("BitReverse32 not implemented");
|
||||
}
|
||||
|
||||
void DoBitCount32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("BitCount32 not implemented");
|
||||
}
|
||||
|
||||
void DoBitCount64(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("BitCount64 not implemented");
|
||||
}
|
||||
|
||||
void DoBitwiseNot32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
Common::CartesianInvoke(ImmValue::Not<Type::U32>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), arg);
|
||||
}
|
||||
|
||||
void DoFindSMsb32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("FindSMsb32 not implemented");
|
||||
}
|
||||
|
||||
void DoFindUMsb32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("FindUMsb32 not implemented");
|
||||
}
|
||||
|
||||
void DoFindILsb32(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("FindILsb32 not implemented");
|
||||
}
|
||||
|
||||
void DoFindILsb64(ImmValueList& inst_values, const ImmValueList& arg) {
|
||||
UNREACHABLE_MSG("FindILsb64 not implemented");
|
||||
}
|
||||
|
||||
void DoSMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Min<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoUMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Min<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoSMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Max<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoUMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1) {
|
||||
Common::CartesianInvoke(ImmValue::Max<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), args0, args1);
|
||||
}
|
||||
|
||||
void DoSClamp32(ImmValueList& inst_values, const ImmValueList& value, const ImmValueList& min,
|
||||
const ImmValueList& max) {
|
||||
Common::CartesianInvoke(ImmValue::Clamp<Type::U32, true>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), value, min, max);
|
||||
}
|
||||
|
||||
void DoUClamp32(ImmValueList& inst_values, const ImmValueList& value, const ImmValueList& min,
|
||||
const ImmValueList& max) {
|
||||
Common::CartesianInvoke(ImmValue::Clamp<Type::U32, false>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), value, min, max);
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
@ -0,0 +1,70 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoIAdd32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoIAdd64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoIAddCary32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoISub32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoISub64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoIMul32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoIMul64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoSMulExt(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoUMulExt(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoSDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoUDiv32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoSMod32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoUMod32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoINeg32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoINeg64(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoIAbs32(ImmValueList& inst_values, const ImmValueList& args);
|
||||
void DoShiftLeftLogical32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoShiftLeftLogical64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoShiftRightLogical32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoShiftRightLogical64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoShiftRightArithmetic32(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoShiftRightArithmetic64(ImmValueList& inst_values, const ImmValueList& args,
|
||||
const ImmValueList& shift);
|
||||
void DoBitwiseAnd32(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1);
|
||||
void DoBitwiseAnd64(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1);
|
||||
void DoBitwiseOr32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoBitwiseOr64(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoBitwiseXor32(ImmValueList& inst_values, const ImmValueList& args0,
|
||||
const ImmValueList& args1);
|
||||
void DoBitFieldInsert(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& insert, const ImmValueList& offset,
|
||||
const ImmValueList& count);
|
||||
void DoBitFieldSExtract(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& offset, const ImmValueList& count);
|
||||
void DoBitFieldUExtract(ImmValueList& inst_values, const ImmValueList& arg,
|
||||
const ImmValueList& offset, const ImmValueList& count);
|
||||
void DoBitReverse32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoBitCount32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoBitCount64(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoBitwiseNot32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoFindSMsb32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoFindUMsb32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoFindILsb32(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoFindILsb64(ImmValueList& inst_values, const ImmValueList& arg);
|
||||
void DoSMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoUMin32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoSMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoUMax32(ImmValueList& inst_values, const ImmValueList& args0, const ImmValueList& args1);
|
||||
void DoSClamp32(ImmValueList& inst_values, const ImmValueList& value, const ImmValueList& min,
|
||||
const ImmValueList& max);
|
||||
void DoUClamp32(ImmValueList& inst_values, const ImmValueList& value, const ImmValueList& min,
|
||||
const ImmValueList& max);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/cartesian_invoke.h"
|
||||
#include "shader_recompiler/ir/compute_value/do_logical_operations.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoLogicalOr(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
Common::CartesianInvoke(ImmValue::Or<Type::U1>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), arg1, arg2);
|
||||
}
|
||||
|
||||
void DoLogicalAnd(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
Common::CartesianInvoke(ImmValue::And<Type::U1>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), arg1, arg2);
|
||||
}
|
||||
|
||||
void DoLogicalXor(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2) {
|
||||
Common::CartesianInvoke(ImmValue::Xor<Type::U1>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), arg1, arg2);
|
||||
}
|
||||
|
||||
void DoLogicalNot(ImmValueList& inst_values, const ImmValueList& arg1) {
|
||||
Common::CartesianInvoke(ImmValue::Not<Type::U1>,
|
||||
std::insert_iterator(inst_values, inst_values.end()), arg1);
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
@ -0,0 +1,15 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoLogicalOr(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoLogicalAnd(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoLogicalXor(ImmValueList& inst_values, const ImmValueList& arg1, const ImmValueList& arg2);
|
||||
void DoLogicalNot(ImmValueList& inst_values, const ImmValueList& arg1);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
210
src/shader_recompiler/ir/compute_value/do_nop_functions.h
Normal file
210
src/shader_recompiler/ir/compute_value/do_nop_functions.h
Normal file
@ -0,0 +1,210 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
#define NOP_FUNCTION(name) inline void Do##name(ImmValueList& inst_values) {}
|
||||
|
||||
NOP_FUNCTION(Phi)
|
||||
NOP_FUNCTION(Identity)
|
||||
NOP_FUNCTION(Void)
|
||||
NOP_FUNCTION(ConditionRef)
|
||||
NOP_FUNCTION(Reference)
|
||||
NOP_FUNCTION(PhiMove)
|
||||
|
||||
NOP_FUNCTION(Prologue)
|
||||
NOP_FUNCTION(Epilogue)
|
||||
NOP_FUNCTION(Discard)
|
||||
NOP_FUNCTION(DiscardCond)
|
||||
NOP_FUNCTION(DebugPrint)
|
||||
|
||||
NOP_FUNCTION(ReadConst)
|
||||
NOP_FUNCTION(ReadConstBuffer)
|
||||
|
||||
NOP_FUNCTION(Barrier)
|
||||
NOP_FUNCTION(WorkgroupMemoryBarrier)
|
||||
NOP_FUNCTION(DeviceMemoryBarrier)
|
||||
|
||||
NOP_FUNCTION(EmitVertex)
|
||||
NOP_FUNCTION(EmitPrimitive)
|
||||
|
||||
NOP_FUNCTION(LoadSharedU32)
|
||||
NOP_FUNCTION(LoadSharedU64)
|
||||
NOP_FUNCTION(WriteSharedU32)
|
||||
NOP_FUNCTION(WriteSharedU64)
|
||||
|
||||
NOP_FUNCTION(SharedAtomicIAdd32)
|
||||
NOP_FUNCTION(SharedAtomicSMin32)
|
||||
NOP_FUNCTION(SharedAtomicUMin32)
|
||||
NOP_FUNCTION(SharedAtomicSMax32)
|
||||
NOP_FUNCTION(SharedAtomicUMax32)
|
||||
NOP_FUNCTION(SharedAtomicAnd32)
|
||||
NOP_FUNCTION(SharedAtomicOr32)
|
||||
NOP_FUNCTION(SharedAtomicXor32)
|
||||
|
||||
NOP_FUNCTION(GetUserData)
|
||||
NOP_FUNCTION(GetThreadBitScalarReg)
|
||||
NOP_FUNCTION(SetThreadBitScalarReg)
|
||||
NOP_FUNCTION(GetScalarRegister)
|
||||
NOP_FUNCTION(SetScalarRegister)
|
||||
NOP_FUNCTION(GetVectorRegister)
|
||||
NOP_FUNCTION(SetVectorRegister)
|
||||
NOP_FUNCTION(GetGotoVariable)
|
||||
NOP_FUNCTION(SetGotoVariable)
|
||||
NOP_FUNCTION(GetAttribute)
|
||||
NOP_FUNCTION(GetAttributeU32)
|
||||
NOP_FUNCTION(SetAttribute)
|
||||
NOP_FUNCTION(GetPatch)
|
||||
NOP_FUNCTION(SetPatch)
|
||||
NOP_FUNCTION(GetTessGenericAttribute)
|
||||
NOP_FUNCTION(SetTcsGenericAttribute)
|
||||
NOP_FUNCTION(ReadTcsGenericOuputAttribute)
|
||||
|
||||
NOP_FUNCTION(GetScc)
|
||||
NOP_FUNCTION(GetExec)
|
||||
NOP_FUNCTION(GetVcc)
|
||||
NOP_FUNCTION(GetVccLo)
|
||||
NOP_FUNCTION(GetVccHi)
|
||||
NOP_FUNCTION(GetM0)
|
||||
NOP_FUNCTION(SetScc)
|
||||
NOP_FUNCTION(SetExec)
|
||||
NOP_FUNCTION(SetVcc)
|
||||
NOP_FUNCTION(SetSccLo)
|
||||
NOP_FUNCTION(SetVccLo)
|
||||
NOP_FUNCTION(SetVccHi)
|
||||
NOP_FUNCTION(SetM0)
|
||||
|
||||
NOP_FUNCTION(UndefU1)
|
||||
NOP_FUNCTION(UndefU8)
|
||||
NOP_FUNCTION(UndefU16)
|
||||
NOP_FUNCTION(UndefU32)
|
||||
NOP_FUNCTION(UndefU64)
|
||||
|
||||
NOP_FUNCTION(LoadBufferU8)
|
||||
NOP_FUNCTION(LoadBufferU16)
|
||||
NOP_FUNCTION(LoadBufferU32)
|
||||
NOP_FUNCTION(LoadBufferU32x2)
|
||||
NOP_FUNCTION(LoadBufferU32x3)
|
||||
NOP_FUNCTION(LoadBufferU32x4)
|
||||
NOP_FUNCTION(LoadBufferF32)
|
||||
NOP_FUNCTION(LoadBufferF32x2)
|
||||
NOP_FUNCTION(LoadBufferF32x3)
|
||||
NOP_FUNCTION(LoadBufferF32x4)
|
||||
NOP_FUNCTION(LoadBufferFormatF32)
|
||||
NOP_FUNCTION(StoreBufferU8)
|
||||
NOP_FUNCTION(StoreBufferU16)
|
||||
NOP_FUNCTION(StoreBufferU32)
|
||||
NOP_FUNCTION(StoreBufferU32x2)
|
||||
NOP_FUNCTION(StoreBufferU32x3)
|
||||
NOP_FUNCTION(StoreBufferU32x4)
|
||||
NOP_FUNCTION(StoreBufferF32)
|
||||
NOP_FUNCTION(StoreBufferF32x2)
|
||||
NOP_FUNCTION(StoreBufferF32x3)
|
||||
NOP_FUNCTION(StoreBufferF32x4)
|
||||
NOP_FUNCTION(StoreBufferFormatF32)
|
||||
|
||||
NOP_FUNCTION(BufferAtomicIAdd32)
|
||||
NOP_FUNCTION(BufferAtomicSMin32)
|
||||
NOP_FUNCTION(BufferAtomicUMin32)
|
||||
NOP_FUNCTION(BufferAtomicSMax32)
|
||||
NOP_FUNCTION(BufferAtomicUMax32)
|
||||
NOP_FUNCTION(BufferAtomicInc32)
|
||||
NOP_FUNCTION(BufferAtomicDec32)
|
||||
NOP_FUNCTION(BufferAtomicAnd32)
|
||||
NOP_FUNCTION(BufferAtomicOr32)
|
||||
NOP_FUNCTION(BufferAtomicXor32)
|
||||
NOP_FUNCTION(BufferAtomicSwap32)
|
||||
|
||||
// Select instructions are handled separately
|
||||
NOP_FUNCTION(SelectU1)
|
||||
NOP_FUNCTION(SelectU8)
|
||||
NOP_FUNCTION(SelectU16)
|
||||
NOP_FUNCTION(SelectU32)
|
||||
NOP_FUNCTION(SelectU64)
|
||||
NOP_FUNCTION(SelectF32)
|
||||
NOP_FUNCTION(SelectF64)
|
||||
|
||||
NOP_FUNCTION(FPOrdEqual32)
|
||||
NOP_FUNCTION(FPOrdEqual64)
|
||||
NOP_FUNCTION(FPUnordEqual32)
|
||||
NOP_FUNCTION(FPUnordEqual64)
|
||||
NOP_FUNCTION(FPOrdNotEqual32)
|
||||
NOP_FUNCTION(FPOrdNotEqual64)
|
||||
NOP_FUNCTION(FPUnordNotEqual32)
|
||||
NOP_FUNCTION(FPUnordNotEqual64)
|
||||
NOP_FUNCTION(FPOrdLessThan32)
|
||||
NOP_FUNCTION(FPOrdLessThan64)
|
||||
NOP_FUNCTION(FPUnordLessThan32)
|
||||
NOP_FUNCTION(FPUnordLessThan64)
|
||||
NOP_FUNCTION(FPOrdGreaterThan32)
|
||||
NOP_FUNCTION(FPOrdGreaterThan64)
|
||||
NOP_FUNCTION(FPUnordGreaterThan32)
|
||||
NOP_FUNCTION(FPUnordGreaterThan64)
|
||||
NOP_FUNCTION(FPOrdLessThanEqual32)
|
||||
NOP_FUNCTION(FPOrdLessThanEqual64)
|
||||
NOP_FUNCTION(FPUnordLessThanEqual32)
|
||||
NOP_FUNCTION(FPUnordLessThanEqual64)
|
||||
NOP_FUNCTION(FPOrdGreaterThanEqual32)
|
||||
NOP_FUNCTION(FPOrdGreaterThanEqual64)
|
||||
NOP_FUNCTION(FPUnordGreaterThanEqual32)
|
||||
NOP_FUNCTION(FPUnordGreaterThanEqual64)
|
||||
NOP_FUNCTION(FPIsNan32)
|
||||
NOP_FUNCTION(FPIsNan64)
|
||||
NOP_FUNCTION(FPIsInf32)
|
||||
NOP_FUNCTION(FPIsInf64)
|
||||
NOP_FUNCTION(FPCmpClass32)
|
||||
|
||||
NOP_FUNCTION(SLessThan32)
|
||||
NOP_FUNCTION(SLessThan64)
|
||||
NOP_FUNCTION(ULessThan32)
|
||||
NOP_FUNCTION(ULessThan64)
|
||||
NOP_FUNCTION(IEqual32)
|
||||
NOP_FUNCTION(IEqual64)
|
||||
NOP_FUNCTION(SLessThanEqual)
|
||||
NOP_FUNCTION(ULessThanEqual)
|
||||
NOP_FUNCTION(SGreaterThan)
|
||||
NOP_FUNCTION(UGreaterThan)
|
||||
NOP_FUNCTION(INotEqual32)
|
||||
NOP_FUNCTION(INotEqual64)
|
||||
NOP_FUNCTION(SGreaterThanEqual)
|
||||
NOP_FUNCTION(UGreaterThanEqual)
|
||||
|
||||
NOP_FUNCTION(ImageSampleRaw)
|
||||
NOP_FUNCTION(ImageSampleImplicitLod)
|
||||
NOP_FUNCTION(ImageSampleExplicitLod)
|
||||
NOP_FUNCTION(ImageSampleDrefImplicitLod)
|
||||
NOP_FUNCTION(ImageSampleDrefExplicitLod)
|
||||
NOP_FUNCTION(ImageGather)
|
||||
NOP_FUNCTION(ImageGatherDref)
|
||||
NOP_FUNCTION(ImageQueryDimensions)
|
||||
NOP_FUNCTION(ImageQueryLod)
|
||||
NOP_FUNCTION(ImageGradient)
|
||||
NOP_FUNCTION(ImageRead)
|
||||
NOP_FUNCTION(ImageWrite)
|
||||
|
||||
NOP_FUNCTION(ImageAtomicIAdd32)
|
||||
NOP_FUNCTION(ImageAtomicSMin32)
|
||||
NOP_FUNCTION(ImageAtomicUMin32)
|
||||
NOP_FUNCTION(ImageAtomicSMax32)
|
||||
NOP_FUNCTION(ImageAtomicUMax32)
|
||||
NOP_FUNCTION(ImageAtomicInc32)
|
||||
NOP_FUNCTION(ImageAtomicDec32)
|
||||
NOP_FUNCTION(ImageAtomicAnd32)
|
||||
NOP_FUNCTION(ImageAtomicOr32)
|
||||
NOP_FUNCTION(ImageAtomicXor32)
|
||||
NOP_FUNCTION(ImageAtomicExchange32)
|
||||
|
||||
NOP_FUNCTION(CubeFaceIndex)
|
||||
|
||||
NOP_FUNCTION(LaneId)
|
||||
NOP_FUNCTION(WarpId)
|
||||
NOP_FUNCTION(QuadShuffle)
|
||||
NOP_FUNCTION(ReadFirstLane)
|
||||
NOP_FUNCTION(ReadLane)
|
||||
NOP_FUNCTION(WriteLane)
|
||||
NOP_FUNCTION(DataAppend)
|
||||
NOP_FUNCTION(DataConsume)
|
||||
|
||||
#undef NOP_FUNCTION
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
132
src/shader_recompiler/ir/compute_value/do_packing.cpp
Normal file
132
src/shader_recompiler/ir/compute_value/do_packing.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/do_packing.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoPackUint2x32(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUint2x32(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackFloat2x32(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUnorm2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUnorm2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSnorm2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSnorm2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUint2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUint2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSint2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSint2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackHalf2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackHalf2x16(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUnorm4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUnorm4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSnorm4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSnorm4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUint4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUint4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSint4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSint4x8(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUfloat10_11_11(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUfloat10_11_11(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackUint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackUint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoPackSint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
void DoUnpackSint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0) {
|
||||
UNREACHABLE_MSG("Unimplemented");
|
||||
}
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
42
src/shader_recompiler/ir/compute_value/do_packing.h
Normal file
42
src/shader_recompiler/ir/compute_value/do_packing.h
Normal file
@ -0,0 +1,42 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
void DoPackUint2x32(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUint2x32(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackFloat2x32(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUnorm2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUnorm2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSnorm2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSnorm2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUint2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUint2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSint2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSint2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackHalf2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackHalf2x16(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUnorm4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUnorm4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSnorm4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSnorm4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUint4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUint4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSint4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSint4x8(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUfloat10_11_11(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUfloat10_11_11(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSnorm2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackUint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackUint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoPackSint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
void DoUnpackSint2_10_10_10(ImmValueList& inst_values, const ImmValueList& args0);
|
||||
|
||||
} // namespace Shader::IR::ComputeValue
|
File diff suppressed because it is too large
Load Diff
@ -11,62 +11,9 @@
|
||||
#include "shader_recompiler/ir/type.h"
|
||||
#include "shader_recompiler/ir/value.h"
|
||||
|
||||
namespace Shader::IR {
|
||||
namespace Shader::IR::ComputeValue {
|
||||
|
||||
// Like IR::Value but can only hold immediate values. Additionally, can hold vectors of values.
|
||||
// Has arithmetic operations defined for it. Usefull for computing a value at shader compile time.
|
||||
|
||||
template <IR::Type type_, bool is_signed_>
|
||||
class TypedImmValue;
|
||||
|
||||
using ImmU1 = TypedImmValue<Type::U1, false>;
|
||||
using ImmU8 = TypedImmValue<Type::U8, false>;
|
||||
using ImmS8 = TypedImmValue<Type::U8, true>;
|
||||
using ImmU16 = TypedImmValue<Type::U16, false>;
|
||||
using ImmS16 = TypedImmValue<Type::U16, true>;
|
||||
using ImmU32 = TypedImmValue<Type::U32, false>;
|
||||
using ImmS32 = TypedImmValue<Type::U32, true>;
|
||||
using ImmF32 = TypedImmValue<Type::F32, true>;
|
||||
using ImmU64 = TypedImmValue<Type::U64, false>;
|
||||
using ImmS64 = TypedImmValue<Type::U64, true>;
|
||||
using ImmF64 = TypedImmValue<Type::F64, true>;
|
||||
using ImmS32F32 = TypedImmValue<Type::U32 | Type::F32, true>;
|
||||
using ImmS64F64 = TypedImmValue<Type::U64 | Type::F64, true>;
|
||||
using ImmU32U64 = TypedImmValue<Type::U32 | Type::U64, false>;
|
||||
using ImmS32S64 = TypedImmValue<Type::U32 | Type::U64, true>;
|
||||
using ImmU16U32U64 = TypedImmValue<Type::U16 | Type::U32 | Type::U64, false>;
|
||||
using ImmS16S32S64 = TypedImmValue<Type::U16 | Type::U32 | Type::U64, true>;
|
||||
using ImmF32F64 = TypedImmValue<Type::F32 | Type::F64, true>;
|
||||
using ImmUAny = TypedImmValue<Type::U1 | Type::U8 | Type::U16 | Type::U32 | Type::U64, false>;
|
||||
using ImmSAny = TypedImmValue<Type::U8 | Type::U16 | Type::U32 | Type::U64, true>;
|
||||
using ImmU32x2 = TypedImmValue<Type::U32x2, false>;
|
||||
using ImmU32x3 = TypedImmValue<Type::U32x3, false>;
|
||||
using ImmU32x4 = TypedImmValue<Type::U32x4, false>;
|
||||
using ImmS32x2 = TypedImmValue<Type::U32x2, true>;
|
||||
using ImmS32x3 = TypedImmValue<Type::U32x3, true>;
|
||||
using ImmS32x4 = TypedImmValue<Type::U32x4, true>;
|
||||
using ImmF32x2 = TypedImmValue<Type::F32x2, true>;
|
||||
using ImmF32x3 = TypedImmValue<Type::F32x3, true>;
|
||||
using ImmF32x4 = TypedImmValue<Type::F32x4, true>;
|
||||
using ImmF64x2 = TypedImmValue<Type::F64x2, true>;
|
||||
using ImmF64x3 = TypedImmValue<Type::F64x3, true>;
|
||||
using ImmF64x4 = TypedImmValue<Type::F64x4, true>;
|
||||
using ImmS32F32x2 = TypedImmValue<Type::U32x2 | Type::F32x2, true>;
|
||||
using ImmS32F32x3 = TypedImmValue<Type::U32x3 | Type::F32x3, true>;
|
||||
using ImmS32F32x4 = TypedImmValue<Type::U32x4 | Type::F32x4, true>;
|
||||
using ImmF32F64x2 = TypedImmValue<Type::F32x2 | Type::F64x2, true>;
|
||||
using ImmF32F64x3 = TypedImmValue<Type::F32x3 | Type::F64x3, true>;
|
||||
using ImmF32F64x4 = TypedImmValue<Type::F32x4 | Type::F64x4, true>;
|
||||
using ImmU32xAny = TypedImmValue<Type::U32 | Type::U32x2 | Type::U32x3 | Type::U32x4, false>;
|
||||
using ImmS32xAny = TypedImmValue<Type::U32 | Type::U32x2 | Type::U32x3 | Type::U32x4, true>;
|
||||
using ImmF32xAny = TypedImmValue<Type::F32 | Type::F32x2 | Type::F32x3 | Type::F32x4, true>;
|
||||
using ImmF64xAny = TypedImmValue<Type::F64 | Type::F64x2 | Type::F64x3 | Type::F64x4, true>;
|
||||
using ImmS32F32xAny = TypedImmValue<Type::U32 | Type::F32 | Type::U32x2 | Type::F32x2 |
|
||||
Type::U32x3 | Type::F32x3 | Type::U32x4 | Type::F32x4,
|
||||
true>;
|
||||
using ImmF32F64xAny = TypedImmValue<Type::F32 | Type::F64 | Type::F32x2 | Type::F64x2 |
|
||||
Type::F32x3 | Type::F64x3 | Type::F32x4 | Type::F64x4,
|
||||
true>;
|
||||
// Holds an immediate value and provides helper functions to do arithmetic operations on it.
|
||||
|
||||
class ImmValue {
|
||||
public:
|
||||
@ -93,6 +40,12 @@ public:
|
||||
ImmValue(f32 value1, f32 value2) noexcept;
|
||||
ImmValue(f32 value1, f32 value2, f32 value3) noexcept;
|
||||
ImmValue(f32 value1, f32 value2, f32 value3, f32 value4) noexcept;
|
||||
ImmValue(u64 value1, u64 value2) noexcept;
|
||||
ImmValue(u64 value1, u64 value2, u64 value3) noexcept;
|
||||
ImmValue(u64 value1, u64 value2, u64 value3, u64 value4) noexcept;
|
||||
ImmValue(s64 value1, s64 value2) noexcept;
|
||||
ImmValue(s64 value1, s64 value2, s64 value3) noexcept;
|
||||
ImmValue(s64 value1, s64 value2, s64 value3, s64 value4) noexcept;
|
||||
ImmValue(f64 value1, f64 value2) noexcept;
|
||||
ImmValue(f64 value1, f64 value2, f64 value3) noexcept;
|
||||
ImmValue(f64 value1, f64 value2, f64 value3, f64 value4) noexcept;
|
||||
@ -101,107 +54,142 @@ public:
|
||||
ImmValue(const ImmValue& value1, const ImmValue& value2, const ImmValue& value3,
|
||||
const ImmValue& value4) noexcept;
|
||||
|
||||
[[nodiscard]] bool IsEmpty() const noexcept;
|
||||
[[nodiscard]] IR::Type Type() const noexcept;
|
||||
[[nodiscard]] IR::Type BaseType() const noexcept;
|
||||
[[nodiscard]] u32 Dimensions() const noexcept;
|
||||
[[nodiscard]] static ImmValue CompositeFrom2x2(const ImmValue& value1,
|
||||
const ImmValue& value2) noexcept;
|
||||
|
||||
[[nodiscard]] bool IsSigned() const noexcept;
|
||||
void SetSigned(bool signed_) noexcept;
|
||||
void SameSignAs(const ImmValue& other) noexcept;
|
||||
[[nodiscard]] bool U1() const noexcept;
|
||||
[[nodiscard]] u8 U8() const noexcept;
|
||||
[[nodiscard]] s8 S8() const noexcept;
|
||||
[[nodiscard]] u16 U16() const noexcept;
|
||||
[[nodiscard]] s16 S16() const noexcept;
|
||||
[[nodiscard]] u32 U32() const noexcept;
|
||||
[[nodiscard]] s32 S32() const noexcept;
|
||||
[[nodiscard]] f32 F32() const noexcept;
|
||||
[[nodiscard]] u64 U64() const noexcept;
|
||||
[[nodiscard]] s64 S64() const noexcept;
|
||||
[[nodiscard]] f64 F64() const noexcept;
|
||||
|
||||
[[nodiscard]] ImmValue Convert(IR::Type new_type, bool new_signed) const noexcept;
|
||||
[[nodiscard]] ImmValue Bitcast(IR::Type new_type, bool new_signed) const noexcept;
|
||||
[[nodiscard]] ImmValue Extract(const ImmU32& index) const noexcept;
|
||||
[[nodiscard]] ImmValue Insert(const ImmValue& value, const ImmU32& indndex) const noexcept;
|
||||
|
||||
[[nodiscard]] bool U1() const;
|
||||
[[nodiscard]] u8 U8() const;
|
||||
[[nodiscard]] s8 S8() const;
|
||||
[[nodiscard]] u16 U16() const;
|
||||
[[nodiscard]] s16 S16() const;
|
||||
[[nodiscard]] u32 U32() const;
|
||||
[[nodiscard]] s32 S32() const;
|
||||
[[nodiscard]] f32 F32() const;
|
||||
[[nodiscard]] u64 U64() const;
|
||||
[[nodiscard]] s64 S64() const;
|
||||
[[nodiscard]] f64 F64() const;
|
||||
|
||||
[[nodiscard]] std::tuple<u32, u32> U32x2() const;
|
||||
[[nodiscard]] std::tuple<u32, u32, u32> U32x3() const;
|
||||
[[nodiscard]] std::tuple<u32, u32, u32, u32> U32x4() const;
|
||||
[[nodiscard]] std::tuple<s32, s32> S32x2() const;
|
||||
[[nodiscard]] std::tuple<s32, s32, s32> S32x3() const;
|
||||
[[nodiscard]] std::tuple<s32, s32, s32, s32> S32x4() const;
|
||||
[[nodiscard]] std::tuple<f32, f32> F32x2() const;
|
||||
[[nodiscard]] std::tuple<f32, f32, f32> F32x3() const;
|
||||
[[nodiscard]] std::tuple<f32, f32, f32, f32> F32x4() const;
|
||||
[[nodiscard]] std::tuple<f64, f64> F64x2() const;
|
||||
[[nodiscard]] std::tuple<f64, f64, f64> F64x3() const;
|
||||
[[nodiscard]] std::tuple<f64, f64, f64, f64> F64x4() const;
|
||||
[[nodiscard]] std::tuple<u32, u32> U32x2() const noexcept;
|
||||
[[nodiscard]] std::tuple<u32, u32, u32> U32x3() const noexcept;
|
||||
[[nodiscard]] std::tuple<u32, u32, u32, u32> U32x4() const noexcept;
|
||||
[[nodiscard]] std::tuple<s32, s32> S32x2() const noexcept;
|
||||
[[nodiscard]] std::tuple<s32, s32, s32> S32x3() const noexcept;
|
||||
[[nodiscard]] std::tuple<s32, s32, s32, s32> S32x4() const noexcept;
|
||||
[[nodiscard]] std::tuple<f32, f32> F32x2() const noexcept;
|
||||
[[nodiscard]] std::tuple<f32, f32, f32> F32x3() const noexcept;
|
||||
[[nodiscard]] std::tuple<f32, f32, f32, f32> F32x4() const noexcept;
|
||||
[[nodiscard]] std::tuple<f64, f64> F64x2() const noexcept;
|
||||
[[nodiscard]] std::tuple<f64, f64, f64> F64x3() const noexcept;
|
||||
[[nodiscard]] std::tuple<f64, f64, f64, f64> F64x4() const noexcept;
|
||||
|
||||
ImmValue& operator=(const ImmValue& value) noexcept = default;
|
||||
|
||||
[[nodiscard]] bool operator==(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] bool operator!=(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] bool operator<(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] bool operator>(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] bool operator<=(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] bool operator>=(const ImmValue& other) const noexcept;
|
||||
|
||||
[[nodiscard]] ImmValue operator+(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator-(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator*(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator/(const ImmValue& other) const;
|
||||
[[nodiscard]] ImmValue operator%(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator&(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator|(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator^(const ImmValue& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator<<(const ImmU32& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator>>(const ImmU32& other) const noexcept;
|
||||
[[nodiscard]] ImmValue operator~() const noexcept;
|
||||
[[nodiscard]] static ImmValue Extract(const ImmValue& vec, const ImmValue& index) noexcept;
|
||||
[[nodiscard]] static ImmValue Insert(const ImmValue& vec, const ImmValue& value,
|
||||
const ImmValue& index) noexcept;
|
||||
|
||||
[[nodiscard]] ImmValue operator++(int) noexcept;
|
||||
[[nodiscard]] ImmValue operator--(int) noexcept;
|
||||
template <IR::Type NewType, bool NewSigned, IR::Type OldType, bool OldSigned>
|
||||
[[nodiscard]] static ImmValue Convert(const ImmValue& in) noexcept;
|
||||
|
||||
ImmValue& operator++() noexcept;
|
||||
ImmValue& operator--() noexcept;
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Add(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
[[nodiscard]] ImmValue operator-() const noexcept;
|
||||
[[nodiscard]] ImmValue operator+() const noexcept;
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Sub(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
ImmValue& operator+=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator-=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator*=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator/=(const ImmValue& other);
|
||||
ImmValue& operator%=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator&=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator|=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator^=(const ImmValue& other) noexcept;
|
||||
ImmValue& operator<<=(const ImmU32& other) noexcept;
|
||||
ImmValue& operator>>=(const ImmU32& other) noexcept;
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Mul(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
[[nodiscard]] ImmValue abs() const noexcept;
|
||||
[[nodiscard]] ImmValue recip() const noexcept;
|
||||
[[nodiscard]] ImmValue sqrt() const noexcept;
|
||||
[[nodiscard]] ImmValue rsqrt() const noexcept;
|
||||
[[nodiscard]] ImmValue sin() const noexcept;
|
||||
[[nodiscard]] ImmValue cos() const noexcept;
|
||||
[[nodiscard]] ImmValue exp2() const noexcept;
|
||||
[[nodiscard]] ImmValue ldexp(const ImmU32& exp) const noexcept;
|
||||
[[nodiscard]] ImmValue log2() const noexcept;
|
||||
[[nodiscard]] ImmValue clamp(const ImmValue& min, const ImmValue& max) const noexcept;
|
||||
[[nodiscard]] ImmValue floor() const noexcept;
|
||||
[[nodiscard]] ImmValue ceil() const noexcept;
|
||||
[[nodiscard]] ImmValue round() const noexcept;
|
||||
[[nodiscard]] ImmValue trunc() const noexcept;
|
||||
[[nodiscard]] ImmValue fract() const noexcept;
|
||||
[[nodiscard]] bool isnan() const noexcept;
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Div(const ImmValue& a, const ImmValue& b);
|
||||
|
||||
[[nodiscard]] static ImmValue fma(const ImmF32F64& a, const ImmF32F64& b,
|
||||
const ImmF32F64& c) noexcept;
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Mod(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
static bool IsSupportedValue(const IR::Value& value) noexcept;
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue And(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Or(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Xor(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue LShift(const ImmValue& a, const ImmValue& shift) noexcept;
|
||||
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue RShift(const ImmValue& a, const ImmValue& shift) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Not(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Neg(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Abs(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Recip(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Sqrt(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Rsqrt(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Sin(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Cos(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Exp2(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Ldexp(const ImmValue& in, const ImmValue& exp) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Log2(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Min(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Max(const ImmValue& a, const ImmValue& b) noexcept;
|
||||
|
||||
template <IR::Type Type, bool IsSigned>
|
||||
[[nodiscard]] static ImmValue Clamp(const ImmValue& in, const ImmValue& min,
|
||||
const ImmValue& max) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Floor(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Ceil(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Round(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Trunc(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Fract(const ImmValue& in) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static ImmValue Fma(const ImmValue& a, const ImmValue& b,
|
||||
const ImmValue& c) noexcept;
|
||||
|
||||
template <IR::Type Type>
|
||||
[[nodiscard]] static bool IsNan(const ImmValue& in) noexcept;
|
||||
|
||||
[[nodiscard]] static bool IsSupportedValue(const IR::Value& value) noexcept;
|
||||
|
||||
private:
|
||||
union Value {
|
||||
@ -218,168 +206,113 @@ private:
|
||||
f64 imm_f64;
|
||||
};
|
||||
|
||||
IR::Type type{};
|
||||
bool is_signed{};
|
||||
std::array<Value, 4> imm_values;
|
||||
|
||||
friend class std::hash<ImmValue>;
|
||||
};
|
||||
static_assert(std::is_trivially_copyable_v<ImmValue>);
|
||||
|
||||
template <IR::Type type_, bool is_signed_>
|
||||
class TypedImmValue : public ImmValue {
|
||||
public:
|
||||
inline static constexpr IR::Type static_type = type_;
|
||||
inline static constexpr bool static_is_signed = is_signed_;
|
||||
|
||||
TypedImmValue() = default;
|
||||
|
||||
template <IR::Type other_type, bool other_signed>
|
||||
requires((other_type & type_) != IR::Type::Void && other_signed == is_signed_)
|
||||
explicit(false) TypedImmValue(const TypedImmValue<other_type, other_signed>& other)
|
||||
: ImmValue(other) {}
|
||||
|
||||
explicit TypedImmValue(const ImmValue& value) : ImmValue(value) {
|
||||
if ((value.Type() & type_) == IR::Type::Void && value.IsSigned() == is_signed_) {
|
||||
throw InvalidArgument("Incompatible types {} {} and {} {}",
|
||||
is_signed_ ? "signed" : "unsigned", type_, value.Type(),
|
||||
value.IsSigned() ? "signed" : "unsigned");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline bool ImmValue::IsEmpty() const noexcept {
|
||||
return type == Type::Void;
|
||||
}
|
||||
|
||||
inline IR::Type ImmValue::Type() const noexcept {
|
||||
return type;
|
||||
}
|
||||
|
||||
inline bool ImmValue::U1() const {
|
||||
ASSERT(type == Type::U1 && !is_signed);
|
||||
inline bool ImmValue::U1() const noexcept {
|
||||
return imm_values[0].imm_u1;
|
||||
}
|
||||
|
||||
inline u8 ImmValue::U8() const {
|
||||
ASSERT(type == Type::U8 && !is_signed);
|
||||
inline u8 ImmValue::U8() const noexcept {
|
||||
return imm_values[0].imm_u8;
|
||||
}
|
||||
|
||||
inline s8 ImmValue::S8() const {
|
||||
ASSERT(type == Type::U8 && is_signed);
|
||||
inline s8 ImmValue::S8() const noexcept {
|
||||
return imm_values[0].imm_s8;
|
||||
}
|
||||
|
||||
inline u16 ImmValue::U16() const {
|
||||
ASSERT(type == Type::U16 && !is_signed);
|
||||
inline u16 ImmValue::U16() const noexcept {
|
||||
return imm_values[0].imm_u16;
|
||||
}
|
||||
|
||||
inline s16 ImmValue::S16() const {
|
||||
ASSERT(type == Type::U16 && is_signed);
|
||||
inline s16 ImmValue::S16() const noexcept {
|
||||
return imm_values[0].imm_s16;
|
||||
}
|
||||
|
||||
inline u32 ImmValue::U32() const {
|
||||
ASSERT(type == Type::U32 && !is_signed);
|
||||
inline u32 ImmValue::U32() const noexcept {
|
||||
return imm_values[0].imm_u32;
|
||||
}
|
||||
|
||||
inline s32 ImmValue::S32() const {
|
||||
ASSERT(type == Type::U32 && is_signed);
|
||||
inline s32 ImmValue::S32() const noexcept {
|
||||
return imm_values[0].imm_s32;
|
||||
}
|
||||
|
||||
inline f32 ImmValue::F32() const {
|
||||
ASSERT(type == Type::F32 && is_signed);
|
||||
inline f32 ImmValue::F32() const noexcept {
|
||||
return imm_values[0].imm_f32;
|
||||
}
|
||||
|
||||
inline u64 ImmValue::U64() const {
|
||||
ASSERT(type == Type::U64 && !is_signed);
|
||||
inline u64 ImmValue::U64() const noexcept {
|
||||
return imm_values[0].imm_u64;
|
||||
}
|
||||
|
||||
inline s64 ImmValue::S64() const {
|
||||
ASSERT(type == Type::U64 && is_signed);
|
||||
inline s64 ImmValue::S64() const noexcept {
|
||||
return imm_values[0].imm_s64;
|
||||
}
|
||||
|
||||
inline f64 ImmValue::F64() const {
|
||||
ASSERT(type == Type::F64 && is_signed);
|
||||
inline f64 ImmValue::F64() const noexcept {
|
||||
return imm_values[0].imm_f64;
|
||||
}
|
||||
|
||||
inline std::tuple<u32, u32> ImmValue::U32x2() const {
|
||||
ASSERT(type == Type::U32x2 && !is_signed);
|
||||
inline std::tuple<u32, u32> ImmValue::U32x2() const noexcept {
|
||||
return {imm_values[0].imm_u32, imm_values[1].imm_u32};
|
||||
}
|
||||
|
||||
inline std::tuple<u32, u32, u32> ImmValue::U32x3() const {
|
||||
ASSERT(type == Type::U32x3 && !is_signed);
|
||||
inline std::tuple<u32, u32, u32> ImmValue::U32x3() const noexcept {
|
||||
return {imm_values[0].imm_u32, imm_values[1].imm_u32, imm_values[2].imm_u32};
|
||||
}
|
||||
|
||||
inline std::tuple<u32, u32, u32, u32> ImmValue::U32x4() const {
|
||||
ASSERT(type == Type::U32x4 && !is_signed);
|
||||
inline std::tuple<u32, u32, u32, u32> ImmValue::U32x4() const noexcept {
|
||||
return {imm_values[0].imm_u32, imm_values[1].imm_u32, imm_values[2].imm_u32,
|
||||
imm_values[3].imm_u32};
|
||||
}
|
||||
|
||||
inline std::tuple<s32, s32> ImmValue::S32x2() const {
|
||||
ASSERT(type == Type::U32x2 && is_signed);
|
||||
inline std::tuple<s32, s32> ImmValue::S32x2() const noexcept {
|
||||
return {imm_values[0].imm_s32, imm_values[1].imm_s32};
|
||||
}
|
||||
|
||||
inline std::tuple<s32, s32, s32> ImmValue::S32x3() const {
|
||||
ASSERT(type == Type::U32x3 && is_signed);
|
||||
inline std::tuple<s32, s32, s32> ImmValue::S32x3() const noexcept {
|
||||
return {imm_values[0].imm_s32, imm_values[1].imm_s32, imm_values[2].imm_s32};
|
||||
}
|
||||
|
||||
inline std::tuple<s32, s32, s32, s32> ImmValue::S32x4() const {
|
||||
ASSERT(type == Type::U32x4 && is_signed);
|
||||
inline std::tuple<s32, s32, s32, s32> ImmValue::S32x4() const noexcept {
|
||||
return {imm_values[0].imm_s32, imm_values[1].imm_s32, imm_values[2].imm_s32,
|
||||
imm_values[3].imm_s32};
|
||||
}
|
||||
|
||||
inline std::tuple<f32, f32> ImmValue::F32x2() const {
|
||||
ASSERT(type == Type::F32x2 && is_signed);
|
||||
inline std::tuple<f32, f32> ImmValue::F32x2() const noexcept {
|
||||
return {imm_values[0].imm_f32, imm_values[1].imm_f32};
|
||||
}
|
||||
|
||||
inline std::tuple<f32, f32, f32> ImmValue::F32x3() const {
|
||||
ASSERT(type == Type::F32x3 && is_signed);
|
||||
inline std::tuple<f32, f32, f32> ImmValue::F32x3() const noexcept {
|
||||
return {imm_values[0].imm_f32, imm_values[1].imm_f32, imm_values[2].imm_f32};
|
||||
}
|
||||
|
||||
inline std::tuple<f32, f32, f32, f32> ImmValue::F32x4() const {
|
||||
ASSERT(type == Type::F32x4 && is_signed);
|
||||
inline std::tuple<f32, f32, f32, f32> ImmValue::F32x4() const noexcept {
|
||||
return {imm_values[0].imm_f32, imm_values[1].imm_f32, imm_values[2].imm_f32,
|
||||
imm_values[3].imm_f32};
|
||||
}
|
||||
|
||||
inline std::tuple<f64, f64> ImmValue::F64x2() const {
|
||||
ASSERT(type == Type::F64x2 && is_signed);
|
||||
inline std::tuple<f64, f64> ImmValue::F64x2() const noexcept {
|
||||
return {imm_values[0].imm_f64, imm_values[1].imm_f64};
|
||||
}
|
||||
|
||||
inline std::tuple<f64, f64, f64> ImmValue::F64x3() const {
|
||||
ASSERT(type == Type::F64x3 && is_signed);
|
||||
inline std::tuple<f64, f64, f64> ImmValue::F64x3() const noexcept {
|
||||
return {imm_values[0].imm_f64, imm_values[1].imm_f64, imm_values[2].imm_f64};
|
||||
}
|
||||
|
||||
inline std::tuple<f64, f64, f64, f64> ImmValue::F64x4() const {
|
||||
ASSERT(type == Type::F64x4 && is_signed);
|
||||
inline std::tuple<f64, f64, f64, f64> ImmValue::F64x4() const noexcept {
|
||||
return {imm_values[0].imm_f64, imm_values[1].imm_f64, imm_values[2].imm_f64,
|
||||
imm_values[3].imm_f64};
|
||||
}
|
||||
|
||||
} // namespace Shader::IR
|
||||
} // namespace Shader::IR::ComputeValue
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<Shader::IR::ImmValue> {
|
||||
std::size_t operator()(const Shader::IR::ImmValue& value) const;
|
||||
struct hash<Shader::IR::ComputeValue::ImmValue> {
|
||||
std::size_t operator()(const Shader::IR::ComputeValue::ImmValue& value) const;
|
||||
};
|
||||
} // namespace std
|
Loading…
Reference in New Issue
Block a user