Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
lizzie
05c721bb41
[compat] fix libusb when disabled error (solaris, fbsd, etc) (#2649)
This fixes an issue in builds where libusb is disabled, it also uses and prioritizes system dependencies over vendored ones (so ports is easier)

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2649
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-10-22 19:12:33 +02:00
lizzie
71241b7560
[dynarmic] remove bloated LUT usage that makes giant functions for no good reason (#2801)
Long story short, each of these LUT generates a function that is only ran once, spam the entire code with bunch of little "specialized templates" (remember, N * M * L) and basically bloat codesize for no good reason
Additionally it tries to outsmart the compiler which it's not always a good idea - herein I replace most (except 1) of those "helper" LUTs with something the compiler can actually work satisfiably

Happy reminder of the sheer amount of functions spammed:
mcl::list thing generates a number from 0 to 63 for (fsize 64), add the 0-31 for fsize 32, 0-15 for fsize 16 and you got around... 64+32+16 = 112 functions for a single parameter
Now include in the equation rounding_mode, which is about, what, 6? so 112*6 = 672

Yeah

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2801
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-10-22 12:23:13 +02:00
lizzie
e0c554976a
[video_core] fix compilation errors from bad merge, fix string_view UB (#2812)
- fixes string_view corruption
- fixes the latest master
Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2812
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-10-22 06:42:01 +02:00
10 changed files with 248 additions and 235 deletions

View file

@ -183,7 +183,8 @@ option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries")
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) # FreeBSD doesn't have a cubeb port yet, vendoring it isn't required (it's optional anyways)
cmake_dependent_option(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT PLATFORM_FREEBSD" OFF)
set(EXT_DEFAULT OFF) set(EXT_DEFAULT OFF)
if (MSVC OR ANDROID) if (MSVC OR ANDROID)
@ -198,7 +199,8 @@ cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" "${PL
# sirit # sirit
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${EXT_DEFAULT}) option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${EXT_DEFAULT})
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) # Re-allow on FreeBSD once its on mainline ports
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR APPLE" OFF)
cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT WIN32 OR NOT ARCHITECTURE_arm64" OFF) cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT WIN32 OR NOT ARCHITECTURE_arm64" OFF)
mark_as_advanced(FORCE ENABLE_OPENGL) mark_as_advanced(FORCE ENABLE_OPENGL)

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2022 MerryMage * Copyright (c) 2022 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@ -566,37 +569,49 @@ void EmitIR<IR::Opcode::FPVectorRecipStepFused64>(oaknut::CodeGenerator& code, E
EmitThreeOpArranged<64>(code, ctx, inst, [&](auto Vresult, auto Va, auto Vb) { code.FRECPS(Vresult, Va, Vb); }); EmitThreeOpArranged<64>(code, ctx, inst, [&](auto Vresult, auto Va, auto Vb) { code.FRECPS(Vresult, Va, Vb); });
} }
/// @brief Assembly thunk "parameters" are in template parameters
/// TODO: we have space for a 5th parameter? :)
template<typename FPT, FP::RoundingMode rounding_mode, bool exact>
static void EmitIRVectorRoundInt16Thunk(VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr));
}
template<> template<>
void EmitIR<IR::Opcode::FPVectorRoundInt16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::FPVectorRoundInt16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto rounding = static_cast<FP::RoundingMode>(inst->GetArg(1).GetU8()); const auto rounding = FP::RoundingMode(inst->GetArg(1).GetU8());
const bool exact = inst->GetArg(2).GetU1(); const bool exact = inst->GetArg(2).GetU1();
// Don't even think about making this a LUT -- it's bad
using rounding_list = mp::list< using FPT = u16; // Yes it's u16, no fsize madness
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>, switch (rounding) {
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>, case FP::RoundingMode::ToNearest_TieEven:
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>, exact
mp::lift_value<FP::RoundingMode::TowardsZero>, ? EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::ToNearest_TieEven, true>)
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>; : EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::ToNearest_TieEven, false>);
using exact_list = mp::list<std::true_type, std::false_type>; break;
case FP::RoundingMode::TowardsPlusInfinity:
static const auto lut = Common::GenerateLookupTableFromList( exact
[]<typename I>(I) { ? EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsPlusInfinity, true>)
using FPT = u16; : EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsPlusInfinity, false>);
return std::pair{ break;
mp::lower_to_tuple_v<I>, case FP::RoundingMode::TowardsMinusInfinity:
Common::FptrCast( exact
[](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) { ? EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsMinusInfinity, true>)
constexpr FP::RoundingMode rounding_mode = mp::get<0, I>::value; : EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsMinusInfinity, false>);
constexpr bool exact = mp::get<1, I>::value; break;
case FP::RoundingMode::TowardsZero:
for (size_t i = 0; i < output.size(); ++i) { exact
output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr)); ? EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsZero, true>)
: EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::TowardsZero, false>);
break;
case FP::RoundingMode::ToNearest_TieAwayFromZero:
exact
? EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, true>)
: EmitTwoOpFallback<3>(code, ctx, inst, EmitIRVectorRoundInt16Thunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, false>);
break;
default:
UNREACHABLE();
} }
})};
},
mp::cartesian_product<rounding_list, exact_list>{});
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
} }
template<> template<>

View file

@ -1071,57 +1071,42 @@ void EmitX64::EmitFPRecipStepFused64(EmitContext& ctx, IR::Inst* inst) {
EmitFPRecipStepFused<64>(code, ctx, inst); EmitFPRecipStepFused<64>(code, ctx, inst);
} }
/// @brief An assembly thunk for the general rounding of FP
/// Conciously making this be a template, because the cost of comparing "fsize" for every
/// round is not worth it. Remember we are making only 3 copies (u16,u32,u64)
/// Extra args layout:
/// 0-7 rounding_mode
/// 8-15 exact (!= 0)
template<typename FPT>
static u64 EmitFPRoundThunk(u64 input, FP::FPSR& fpsr, FP::FPCR fpcr, u32 extra_args) {
auto const exact = ((extra_args >> 16) & 0xff) != 0;
auto const rounding_mode = FP::RoundingMode((extra_args >> 8) & 0xff);
return FP::FPRoundInt<FPT>(FPT(input), fpcr, rounding_mode, exact, fpsr);
}
static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, size_t fsize) { static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, size_t fsize) {
const auto rounding_mode = static_cast<FP::RoundingMode>(inst->GetArg(1).GetU8()); auto const rounding_mode = FP::RoundingMode(inst->GetArg(1).GetU8());
const bool exact = inst->GetArg(2).GetU1(); bool const exact = inst->GetArg(2).GetU1();
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode); auto const round_imm = ConvertRoundingModeToX64Immediate(rounding_mode);
if (fsize != 16 && code.HasHostFeature(HostFeature::SSE41) && round_imm && !exact) { if (fsize != 16 && code.HasHostFeature(HostFeature::SSE41) && round_imm && !exact) {
if (fsize == 64) { fsize == 64
FPTwoOp<64>(code, ctx, inst, [&](Xbyak::Xmm result) { ? FPTwoOp<64>(code, ctx, inst, [&](Xbyak::Xmm result) { code.roundsd(result, result, *round_imm); })
code.roundsd(result, result, *round_imm); : FPTwoOp<32>(code, ctx, inst, [&](Xbyak::Xmm result) { code.roundss(result, result, *round_imm); });
});
} else { } else {
FPTwoOp<32>(code, ctx, inst, [&](Xbyak::Xmm result) {
code.roundss(result, result, *round_imm);
});
}
return;
}
using fsize_list = mp::list<mp::lift_value<size_t(16)>,
mp::lift_value<size_t(32)>,
mp::lift_value<size_t(64)>>;
using rounding_list = mp::list<
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsZero>,
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
using exact_list = mp::list<std::true_type, std::false_type>;
static const auto lut = Common::GenerateLookupTableFromList(
[]<typename I>(I) {
return std::pair{
mp::lower_to_tuple_v<I>,
Common::FptrCast(
[](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) {
constexpr size_t fsize = mp::get<0, I>::value;
constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value;
constexpr bool exact = mp::get<2, I>::value;
using InputSize = mcl::unsigned_integer_of_size<fsize>;
return FP::FPRoundInt<InputSize>(static_cast<InputSize>(input), fpcr, rounding_mode, exact, fpsr);
})};
},
mp::cartesian_product<fsize_list, rounding_list, exact_list>{});
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
// See EmitFPRoundThunk
auto const extra_args = u32(rounding_mode) | (u32(exact) << 8);
ctx.reg_alloc.HostCall(inst, args[0]); ctx.reg_alloc.HostCall(inst, args[0]);
code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value());
code.CallFunction(lut.at(std::make_tuple(fsize, rounding_mode, exact))); code.mov(code.ABI_PARAM4.cvt32(), extra_args);
switch (fsize) {
case 64: code.CallFunction(EmitFPRoundThunk<u64>); break;
case 32: code.CallFunction(EmitFPRoundThunk<u32>); break;
case 16: code.CallFunction(EmitFPRoundThunk<u16>); break;
default: UNREACHABLE();
}
}
} }
void EmitX64::EmitFPRoundInt16(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPRoundInt16(EmitContext& ctx, IR::Inst* inst) {
@ -1621,12 +1606,29 @@ void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
} }
} }
/// @brief Thunk used in assembly
/// The extra args is conformed as follows:
/// 0-7 fbits
/// 8-15 rounding
/// 16-23 isize
/// 24-31 unsigned_ (!= 0)
/// Better than spamming thousands of templates aye?
template<size_t fsize>
static u64 EmitFPToFixedThunk(u64 input, FP::FPSR& fpsr, FP::FPCR fpcr, u32 extra_args) {
using FPT = mcl::unsigned_integer_of_size<fsize>;
auto const unsigned_ = ((extra_args >> 24) & 0xff) != 0;
auto const isize = ((extra_args >> 16) & 0xff);
auto const rounding = FP::RoundingMode((extra_args >> 8) & 0xff);
auto const fbits = ((extra_args >> 0) & 0xff);
return FP::FPToFixed<FPT>(isize, FPT(input), fbits, unsigned_, fpcr, rounding, fpsr);
}
template<size_t fsize, bool unsigned_, size_t isize> template<size_t fsize, bool unsigned_, size_t isize>
static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const size_t fbits = args[1].GetImmediateU8(); const size_t fbits = args[1].GetImmediateU8();
const auto rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8()); const auto rounding_mode = FP::RoundingMode(args[2].GetImmediateU8());
if constexpr (fsize != 16) { if constexpr (fsize != 16) {
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode); const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode);
@ -1732,34 +1734,14 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
return; return;
} }
} }
// See EmitFPToFixedThunk
using fbits_list = mp::lift_sequence<std::make_index_sequence<isize + 1>>; auto const extra_args = (u32(unsigned_) << 24) | (u32(isize) << 16)
using rounding_list = mp::list< | (u32(rounding_mode) << 8) | (u32(fbits));
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsZero>,
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
static const auto lut = Common::GenerateLookupTableFromList(
[]<typename I>(I) {
return std::pair{
mp::lower_to_tuple_v<I>,
Common::FptrCast(
[](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) {
constexpr size_t fbits = mp::get<0, I>::value;
constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value;
using FPT = mcl::unsigned_integer_of_size<fsize>;
return FP::FPToFixed<FPT>(isize, static_cast<FPT>(input), fbits, unsigned_, fpcr, rounding_mode, fpsr);
})};
},
mp::cartesian_product<fbits_list, rounding_list>{});
ctx.reg_alloc.HostCall(inst, args[0]); ctx.reg_alloc.HostCall(inst, args[0]);
code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value());
code.CallFunction(lut.at(std::make_tuple(fbits, rounding_mode))); code.mov(code.ABI_PARAM4.cvt32(), extra_args);
code.CallFunction(EmitFPToFixedThunk<fsize>);
} }
void EmitX64::EmitFPDoubleToFixedS16(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPDoubleToFixedS16(EmitContext& ctx, IR::Inst* inst) {

View file

@ -439,9 +439,9 @@ void EmitThreeOpVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template<typename Lambda> template<typename F>
void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, Lambda lambda, bool fpcr_controlled) { void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, F lambda, bool fpcr_controlled) {
const auto fn = static_cast<mcl::equivalent_function_type<Lambda>*>(lambda); const auto fn = static_cast<mcl::equivalent_function_type<F>*>(lambda);
const u32 fpcr = ctx.FPCR(fpcr_controlled).Value(); const u32 fpcr = ctx.FPCR(fpcr_controlled).Value();
@ -459,8 +459,8 @@ void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak
code.add(rsp, stack_space + ABI_SHADOW_SPACE); code.add(rsp, stack_space + ABI_SHADOW_SPACE);
} }
template<size_t fpcr_controlled_arg_index = 1, typename Lambda> template<size_t fpcr_controlled_arg_index = 1, typename F>
void EmitTwoOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { void EmitTwoOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, F lambda) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
@ -665,8 +665,14 @@ void EmitX64::EmitFPVectorEqual64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, a); ctx.reg_alloc.DefineValue(inst, a);
} }
template<FP::RoundingMode rounding_mode>
static void EmitFPVectorFromHalf32Thunk(VectorArray<u32>& output, const VectorArray<u16>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FP::FPConvert<u32, u16>(input[i], fpcr, rounding_mode, fpsr);
}
void EmitX64::EmitFPVectorFromHalf32(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPVectorFromHalf32(EmitContext& ctx, IR::Inst* inst) {
const auto rounding_mode = static_cast<FP::RoundingMode>(inst->GetArg(1).GetU8()); const auto rounding_mode = FP::RoundingMode(inst->GetArg(1).GetU8());
const bool fpcr_controlled = inst->GetArg(2).GetU1(); const bool fpcr_controlled = inst->GetArg(2).GetU1();
if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) { if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) {
@ -679,32 +685,27 @@ void EmitX64::EmitFPVectorFromHalf32(EmitContext& ctx, IR::Inst* inst) {
ForceToDefaultNaN<32>(code, ctx.FPCR(fpcr_controlled), result); ForceToDefaultNaN<32>(code, ctx.FPCR(fpcr_controlled), result);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
return; } else {
switch (rounding_mode) {
case FP::RoundingMode::ToNearest_TieEven:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorFromHalf32Thunk<FP::RoundingMode::ToNearest_TieEven>);
break;
case FP::RoundingMode::TowardsPlusInfinity:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorFromHalf32Thunk<FP::RoundingMode::TowardsPlusInfinity>);
break;
case FP::RoundingMode::TowardsMinusInfinity:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorFromHalf32Thunk<FP::RoundingMode::TowardsMinusInfinity>);
break;
case FP::RoundingMode::TowardsZero:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorFromHalf32Thunk<FP::RoundingMode::TowardsZero>);
break;
case FP::RoundingMode::ToNearest_TieAwayFromZero:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorFromHalf32Thunk<FP::RoundingMode::ToNearest_TieAwayFromZero>);
break;
default:
UNREACHABLE();
} }
using rounding_list = mp::list<
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsZero>,
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
static const auto lut = Common::GenerateLookupTableFromList(
[]<typename I>(I) {
return std::pair{
mp::lower_to_tuple_v<I>,
Common::FptrCast(
[](VectorArray<u32>& output, const VectorArray<u16>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
constexpr FP::RoundingMode rounding_mode = mp::get<0, I>::value;
for (size_t i = 0; i < output.size(); ++i) {
output[i] = FP::FPConvert<u32, u16>(input[i], fpcr, rounding_mode, fpsr);
} }
})};
},
mp::cartesian_product<rounding_list>{});
EmitTwoOpFallback<2>(code, ctx, inst, lut.at(std::make_tuple(rounding_mode)));
} }
void EmitX64::EmitFPVectorFromSignedFixed32(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPVectorFromSignedFixed32(EmitContext& ctx, IR::Inst* inst) {
@ -1681,25 +1682,26 @@ void EmitX64::EmitFPVectorRecipStepFused64(EmitContext& ctx, IR::Inst* inst) {
EmitRecipStepFused<64>(code, ctx, inst); EmitRecipStepFused<64>(code, ctx, inst);
} }
template<typename FPT, FP::RoundingMode rounding_mode, bool exact>
static void EmitFPVectorRoundIntThunk(VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr));
}
template<size_t fsize> template<size_t fsize>
void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
const auto rounding = static_cast<FP::RoundingMode>(inst->GetArg(1).GetU8()); const auto rounding = FP::RoundingMode(inst->GetArg(1).GetU8());
const bool exact = inst->GetArg(2).GetU1(); const bool exact = inst->GetArg(2).GetU1();
if constexpr (fsize != 16) { if constexpr (fsize != 16) {
if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) { if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) {
const u8 round_imm = [&]() -> u8 { const u8 round_imm = [&]() -> u8 {
switch (rounding) { switch (rounding) {
case FP::RoundingMode::ToNearest_TieEven: case FP::RoundingMode::ToNearest_TieEven: return 0b00;
return 0b00; case FP::RoundingMode::TowardsPlusInfinity: return 0b10;
case FP::RoundingMode::TowardsPlusInfinity: case FP::RoundingMode::TowardsMinusInfinity: return 0b01;
return 0b10; case FP::RoundingMode::TowardsZero: return 0b11;
case FP::RoundingMode::TowardsMinusInfinity: default: UNREACHABLE();
return 0b01;
case FP::RoundingMode::TowardsZero:
return 0b11;
default:
UNREACHABLE();
} }
}(); }();
@ -1711,32 +1713,37 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
} }
} }
using rounding_list = mp::list< // Do not make a LUT out of this, let the compiler do it's thing
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>, using FPT = mcl::unsigned_integer_of_size<fsize>;
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>, switch (rounding) {
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>, case FP::RoundingMode::ToNearest_TieEven:
mp::lift_value<FP::RoundingMode::TowardsZero>, exact
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>; ? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieEven, true>)
using exact_list = mp::list<std::true_type, std::false_type>; : EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieEven, false>);
break;
static const auto lut = Common::GenerateLookupTableFromList( case FP::RoundingMode::TowardsPlusInfinity:
[]<typename I>(I) { exact
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC ? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsPlusInfinity, true>)
return std::pair{ : EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsPlusInfinity, false>);
mp::lower_to_tuple_v<I>, break;
Common::FptrCast( case FP::RoundingMode::TowardsMinusInfinity:
[](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) { exact
constexpr FP::RoundingMode rounding_mode = mp::get<0, I>::value; ? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsMinusInfinity, true>)
constexpr bool exact = mp::get<1, I>::value; : EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsMinusInfinity, false>);
break;
for (size_t i = 0; i < output.size(); ++i) { case FP::RoundingMode::TowardsZero:
output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr)); exact
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsZero, true>)
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsZero, false>);
break;
case FP::RoundingMode::ToNearest_TieAwayFromZero:
exact
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, true>)
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, false>);
break;
default:
UNREACHABLE();
} }
})};
},
mp::cartesian_product<rounding_list, exact_list>{});
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
} }
void EmitX64::EmitFPVectorRoundInt16(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPVectorRoundInt16(EmitContext& ctx, IR::Inst* inst) {
@ -1965,8 +1972,14 @@ void EmitX64::EmitFPVectorSub64(EmitContext& ctx, IR::Inst* inst) {
EmitThreeOpVectorOperation<64, DefaultIndexer>(code, ctx, inst, &Xbyak::CodeGenerator::subpd); EmitThreeOpVectorOperation<64, DefaultIndexer>(code, ctx, inst, &Xbyak::CodeGenerator::subpd);
} }
template<FP::RoundingMode rounding_mode>
static void EmitFPVectorToHalf32Thunk(VectorArray<u16>& output, const VectorArray<u32>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = i < input.size() ? FP::FPConvert<u16, u32>(input[i], fpcr, rounding_mode, fpsr) : 0;
}
void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) {
const auto rounding_mode = static_cast<FP::RoundingMode>(inst->GetArg(1).GetU8()); const auto rounding_mode = FP::RoundingMode(inst->GetArg(1).GetU8());
const bool fpcr_controlled = inst->GetArg(2).GetU1(); const bool fpcr_controlled = inst->GetArg(2).GetU1();
if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) { if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) {
@ -1976,41 +1989,39 @@ void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
ForceToDefaultNaN<32>(code, ctx.FPCR(fpcr_controlled), result); ForceToDefaultNaN<32>(code, ctx.FPCR(fpcr_controlled), result);
code.vcvtps2ph(result, result, static_cast<u8>(*round_imm)); code.vcvtps2ph(result, result, u8(*round_imm));
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
return;
}
using rounding_list = mp::list<
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
mp::lift_value<FP::RoundingMode::TowardsZero>,
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
static const auto lut = Common::GenerateLookupTableFromList(
[]<typename I>(I) {
return std::pair{
mp::lower_to_tuple_v<I>,
Common::FptrCast(
[](VectorArray<u16>& output, const VectorArray<u32>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
constexpr FP::RoundingMode rounding_mode = mp::get<0, I>::value;
for (size_t i = 0; i < output.size(); ++i) {
if (i < input.size()) {
output[i] = FP::FPConvert<u16, u32>(input[i], fpcr, rounding_mode, fpsr);
} else { } else {
output[i] = 0; switch (rounding_mode) {
case FP::RoundingMode::ToNearest_TieEven:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorToHalf32Thunk<FP::RoundingMode::ToNearest_TieEven>);
break;
case FP::RoundingMode::TowardsPlusInfinity:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorToHalf32Thunk<FP::RoundingMode::TowardsPlusInfinity>);
break;
case FP::RoundingMode::TowardsMinusInfinity:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorToHalf32Thunk<FP::RoundingMode::TowardsMinusInfinity>);
break;
case FP::RoundingMode::TowardsZero:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorToHalf32Thunk<FP::RoundingMode::TowardsZero>);
break;
case FP::RoundingMode::ToNearest_TieAwayFromZero:
EmitTwoOpFallback<2>(code, ctx, inst, EmitFPVectorToHalf32Thunk<FP::RoundingMode::ToNearest_TieAwayFromZero>);
break;
default:
UNREACHABLE();
} }
} }
})};
},
mp::cartesian_product<rounding_list>{});
EmitTwoOpFallback<2>(code, ctx, inst, lut.at(std::make_tuple(rounding_mode)));
} }
// Assembly thunk; just remember not to specialise too much otherwise i-cache death!
// template<typename FPT, size_t fbits, FP::RoundingMode rounding_mode>
// static void EmitFPVectorToFixedThunk(VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
// for (size_t i = 0; i < output.size(); ++i)
// output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
// }
template<size_t fsize, bool unsigned_> template<size_t fsize, bool unsigned_>
void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
const size_t fbits = inst->GetArg(1).GetU8(); const size_t fbits = inst->GetArg(1).GetU8();
@ -2108,7 +2119,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
FCODE(andp)(tmp, xmm0); FCODE(andp)(tmp, xmm0);
FCODE(subp)(src, tmp); FCODE(subp)(src, tmp);
perform_conversion(src); perform_conversion(src);
ICODE(psll)(xmm0, static_cast<u8>(fsize - 1)); ICODE(psll)(xmm0, u8(fsize - 1));
FCODE(orp)(src, xmm0); FCODE(orp)(src, xmm0);
// Saturate to max // Saturate to max
@ -2116,7 +2127,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
} }
} else { } else {
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
constexpr u64 integer_max = static_cast<FPT>((std::numeric_limits<std::conditional_t<unsigned_, FPT, std::make_signed_t<FPT>>>::max)()); constexpr u64 integer_max = FPT((std::numeric_limits<std::conditional_t<unsigned_, FPT, std::make_signed_t<FPT>>>::max)());
code.movaps(xmm0, GetVectorOf<fsize, float_upper_limit_signed>(code)); code.movaps(xmm0, GetVectorOf<fsize, float_upper_limit_signed>(code));
FCODE(cmplep)(xmm0, src); FCODE(cmplep)(xmm0, src);
@ -2138,22 +2149,18 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
mp::lift_value<FP::RoundingMode::TowardsZero>, mp::lift_value<FP::RoundingMode::TowardsZero>,
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>; mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
static const auto lut = Common::GenerateLookupTableFromList( static const auto lut = Common::GenerateLookupTableFromList([]<typename I>(I) {
[]<typename I>(I) {
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
return std::pair{ return std::pair{
mp::lower_to_tuple_v<I>, mp::lower_to_tuple_v<I>,
Common::FptrCast( Common::FptrCast([](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
[](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
constexpr size_t fbits = mp::get<0, I>::value; constexpr size_t fbits = mp::get<0, I>::value;
constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value; constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value;
for (size_t i = 0; i < output.size(); ++i)
for (size_t i = 0; i < output.size(); ++i) { output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
output[i] = static_cast<FPT>(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr)); })
} };
})}; }, mp::cartesian_product<fbits_list, rounding_list>{});
},
mp::cartesian_product<fbits_list, rounding_list>{});
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding))); EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding)));
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage * Copyright (c) 2018 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD

View file

@ -40,9 +40,7 @@ inline auto GenerateLookupTableFromList(Function f, mcl::mp::list<Values...>) {
using PairT = std::common_type_t<std::invoke_result_t<Function, Values>...>; using PairT = std::common_type_t<std::invoke_result_t<Function, Values>...>;
#endif #endif
using MapT = mcl::mp::apply<std::map, PairT>; using MapT = mcl::mp::apply<std::map, PairT>;
static_assert(mcl::is_instance_of_template_v<std::pair, PairT>); static_assert(mcl::is_instance_of_template_v<std::pair, PairT>);
const std::initializer_list<PairT> pair_array{f(Values{})...}; const std::initializer_list<PairT> pair_array{f(Values{})...};
return MapT(pair_array.begin(), pair_array.end()); return MapT(pair_array.begin(), pair_array.end());
} }

View file

@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
@ -83,7 +86,7 @@ if (ENABLE_LIBUSB)
drivers/gc_adapter.h drivers/gc_adapter.h
) )
target_link_libraries(input_common PRIVATE libusb::usb) target_link_libraries(input_common PRIVATE libusb::usb)
target_compile_definitions(input_common PRIVATE HAVE_LIBUSB) target_compile_definitions(input_common PRIVATE ENABLE_LIBUSB)
endif() endif()
create_target_directory_groups(input_common) create_target_directory_groups(input_common)

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2017 Citra Emulator Project // SPDX-FileCopyrightText: 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -19,7 +22,7 @@
#include "input_common/input_poller.h" #include "input_common/input_poller.h"
#include "input_common/main.h" #include "input_common/main.h"
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
#include "input_common/drivers/gc_adapter.h" #include "input_common/drivers/gc_adapter.h"
#endif #endif
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
@ -76,7 +79,7 @@ struct InputSubsystem::Impl {
RegisterEngine("keyboard", keyboard); RegisterEngine("keyboard", keyboard);
RegisterEngine("mouse", mouse); RegisterEngine("mouse", mouse);
RegisterEngine("touch", touch_screen); RegisterEngine("touch", touch_screen);
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
RegisterEngine("gcpad", gcadapter); RegisterEngine("gcpad", gcadapter);
#endif #endif
RegisterEngine("cemuhookudp", udp_client); RegisterEngine("cemuhookudp", udp_client);
@ -110,7 +113,7 @@ struct InputSubsystem::Impl {
UnregisterEngine(keyboard); UnregisterEngine(keyboard);
UnregisterEngine(mouse); UnregisterEngine(mouse);
UnregisterEngine(touch_screen); UnregisterEngine(touch_screen);
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
UnregisterEngine(gcadapter); UnregisterEngine(gcadapter);
#endif #endif
UnregisterEngine(udp_client); UnregisterEngine(udp_client);
@ -145,7 +148,7 @@ struct InputSubsystem::Impl {
auto android_devices = android->GetInputDevices(); auto android_devices = android->GetInputDevices();
devices.insert(devices.end(), android_devices.begin(), android_devices.end()); devices.insert(devices.end(), android_devices.begin(), android_devices.end());
#endif #endif
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
auto gcadapter_devices = gcadapter->GetInputDevices(); auto gcadapter_devices = gcadapter->GetInputDevices();
devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end()); devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
#endif #endif
@ -178,7 +181,7 @@ struct InputSubsystem::Impl {
return android; return android;
} }
#endif #endif
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
if (engine == gcadapter->GetEngineName()) { if (engine == gcadapter->GetEngineName()) {
return gcadapter; return gcadapter;
} }
@ -263,7 +266,7 @@ struct InputSubsystem::Impl {
return true; return true;
} }
#endif #endif
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
if (engine == gcadapter->GetEngineName()) { if (engine == gcadapter->GetEngineName()) {
return true; return true;
} }
@ -294,7 +297,7 @@ struct InputSubsystem::Impl {
#ifdef ANDROID #ifdef ANDROID
android->BeginConfiguration(); android->BeginConfiguration();
#endif #endif
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
gcadapter->BeginConfiguration(); gcadapter->BeginConfiguration();
#endif #endif
udp_client->BeginConfiguration(); udp_client->BeginConfiguration();
@ -310,7 +313,7 @@ struct InputSubsystem::Impl {
#ifdef ANDROID #ifdef ANDROID
android->EndConfiguration(); android->EndConfiguration();
#endif #endif
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
gcadapter->EndConfiguration(); gcadapter->EndConfiguration();
#endif #endif
udp_client->EndConfiguration(); udp_client->EndConfiguration();
@ -343,7 +346,7 @@ struct InputSubsystem::Impl {
std::shared_ptr<VirtualAmiibo> virtual_amiibo; std::shared_ptr<VirtualAmiibo> virtual_amiibo;
std::shared_ptr<VirtualGamepad> virtual_gamepad; std::shared_ptr<VirtualGamepad> virtual_gamepad;
#ifdef HAVE_LIBUSB #ifdef ENABLE_LIBUSB
std::shared_ptr<GCAdapter> gcadapter; std::shared_ptr<GCAdapter> gcadapter;
#endif #endif

View file

@ -78,11 +78,11 @@ IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) {
case Type::_1D: case Type::_1D:
case Type::_1D_BUFFER: case Type::_1D_BUFFER:
return v.X(reg); return v.X(reg);
case Type::ARRAY_1D: case Type::_1D_ARRAY:
return v.ir.CompositeConstruct(v.X(reg), array(1)); return v.ir.CompositeConstruct(v.X(reg), array(1));
case Type::_2D: case Type::_2D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1)); return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1));
case Type::ARRAY_2D: case Type::_2D_ARRAY:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), array(2)); return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), array(2));
case Type::_3D: case Type::_3D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), v.X(reg + 2)); return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), v.X(reg + 2));

View file

@ -243,7 +243,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
} }
if (shader_backend == Settings::ShaderBackend::Glsl && is_nvidia) { if (shader_backend == Settings::ShaderBackend::Glsl && is_nvidia) {
const std::string_view driver_version = version.substr(13); const std::string driver_version = version.substr(13);
const int version_major = const int version_major =
std::atoi(driver_version.substr(0, driver_version.find(".")).data()); std::atoi(driver_version.substr(0, driver_version.find(".")).data());
if (version_major >= 495) { if (version_major >= 495) {