Compare commits

...

38 Commits

Author SHA1 Message Date
Liam
adec4d0da7 cmake: update inclusion of system FFmpeg 2022-11-30 18:25:07 -05:00
Fernando S
4e89979c87 Merge pull request #9320 from yuzu-emu/fix-audio-suspend
AudioCore: Take suspend lock when stalling the running process.
2022-11-30 16:41:32 +01:00
bunnei
8fd4e44014 audio_core: sink_stream: Hold the suspend lock when process is stalled.
- Prevents us from clashing with other callers trying to un/stall.
2022-11-29 20:32:06 -08:00
Morph
49219b8a86 Merge pull request #9349 from lat9nq/cmake-322
CMakeLists: Bump minimum required CMake version to 3.22
2022-11-29 19:41:47 -05:00
liamwhite
d6b63239ae Merge pull request #9308 from lat9nq/from-scratch
startup_checks: Use Windows flow for *nix
2022-11-29 18:45:39 -05:00
liamwhite
cafca891ea Merge pull request #9322 from german77/pump_events
input_common: Pump SDL events from main thread
2022-11-29 18:45:25 -05:00
liamwhite
c845d8a9e8 Merge pull request #9352 from lioncash/vidcast
engines: Remove unnecessary casts
2022-11-29 18:45:16 -05:00
liamwhite
1a6785d296 Merge pull request #9354 from lioncash/const-param
host1x/syncpoint_manager: Pass DeregisterAction() handle as const-ref
2022-11-29 18:45:05 -05:00
Lioncash
b6d93b2c77 host1x/syncpoint_manager: Eliminate unnecessary std::function construction
We can just pass the function object through, and if it's a valid
function, then it will automatically be converted.
2022-11-29 08:58:50 -05:00
Lioncash
c4af7b3f5c host1x/syncpoint_manager: Pass DeregisterAction() handle as const-ref
The handle is only compared against and not modified in any way, so we
can pass it by const reference.

This also allows us to mark the respective parameters for
DeregisterGuestAction() and DeregisterHostAction() as const references
as well.
2022-11-29 08:55:33 -05:00
Lioncash
96ffc174aa maxwell_3d: Mark shifted value as unsigned
Otherwise this is technically creating a signed int result that gets
converted. Just a consistency change.

While we're in the area, we can mark Samples() as const.
2022-11-29 08:39:33 -05:00
Lioncash
d7ec031419 engines: Remove unnecessary casts
In a few cases we have some casts that can be trivially removed.
2022-11-29 08:38:46 -05:00
liamwhite
55a3cbfa0d Merge pull request #9340 from lioncash/nvdrv
nvdrv: Simplify builder declarations
2022-11-29 08:27:13 -05:00
liamwhite
55b546a110 Merge pull request #9347 from lioncash/vcast
video_core/surface: Eliminate casts in GetFormatType()
2022-11-29 08:26:39 -05:00
liamwhite
6b8ab9ed8f Merge pull request #9346 from lioncash/vtable
producer_listener: Add virtual destructor to IProducerListener
2022-11-29 08:26:32 -05:00
liamwhite
a7f1fa7bfc Merge pull request #9345 from lioncash/fence
consumer_base: Pass std::shared_ptr by const reference
2022-11-29 08:26:25 -05:00
liamwhite
b6373c5ea5 Merge pull request #9343 from lioncash/bounds
syncpoint_manager: Reduce redundant bounds checks
2022-11-29 08:26:16 -05:00
lat9nq
0941ae0b61 CMake: Directly link to SDL2-static when appropriate
Trying to be lazy and alias SDL2 to SDL2-static causes issues in later
versions of CMake. Just use the same condition to tell which one to use.
2022-11-28 23:21:14 -05:00
lat9nq
47b133c0b8 CMakeLists: Bump minimum required CMake version to 3.22 2022-11-28 22:48:49 -05:00
Lioncash
a9efea8ae9 video_core/surface: Eliminate casts in GetFormatType()
We can just compare directly and get rid of verbose casting.
2022-11-28 20:25:44 -05:00
Lioncash
25dda06f49 producer_listener: Add virtual destructor to IProducerListener
Several member variables are shared_ptr's to this base class. Even
though producer listeners are still unimplemented, this ensures we
always have consistent deletion behavior once this ends up being used
polymorphically.
2022-11-28 19:39:13 -05:00
Lioncash
7a329ae56c syncpoint_manager: Mark IsSyncpointAllocated() as const
This doesn't modify class state at all.
2022-11-28 16:08:21 -05:00
Lioncash
d0883027d6 syncpoint_manager: Reduce number of bounds checks
The only time we need to check bounds is on the first access.
2022-11-28 16:06:01 -05:00
Morph
bbb963a31a Merge pull request #9339 from lioncash/cacheheader
common/cache_management: Amend header includes
2022-11-28 13:12:20 -05:00
Morph
51abe35e05 Merge pull request #9338 from lioncash/properties
input_common/helpers: Mark analog property structs members as static constexpr
2022-11-28 13:12:14 -05:00
Morph
64ff79f919 Merge pull request #9337 from lioncash/pbr
common/input: Add helper functions for constructing input and output devices
2022-11-28 13:12:08 -05:00
Morph
e507c01a22 Merge pull request #9336 from lioncash/themepath
yuzu/main: Merge variable declaration into ifdef
2022-11-28 13:11:17 -05:00
Lioncash
ad787b20ca nvdrv: Simplify builder declarations
We can just use auto here. If one of these ever happens to not be
derived from nvdevice, then this will cause a compilation error.

We can also move the devices into the collection to get rid of an
unnecessary atomic reference count increment and decrement.
2022-11-28 10:43:48 -05:00
Lioncash
c2c9b44749 common/cache_management: Amend header includes
Narrows the include in the header to <cstddef>, since that's what houses
size_t's definition, meanwhile the <cstdint> include can be moved into
the cpp file.
2022-11-28 10:19:53 -05:00
Lioncash
8265c167d3 input_common/helpers: Mark analog property structs members as static constexpr
These are const with no dependency on any other data members, so we can
make these static constexpr to reduce the overall object size.
2022-11-28 10:10:37 -05:00
Lioncash
780ae92265 core/hid/emulated_controller: Use ranges version of transform
Makes the transform calls much nicer to read.
2022-11-28 10:00:42 -05:00
Lioncash
2ec7d0b5fd common/input: Add helpers functions for creating input and output devices
Avoids the redundancy of needing to explictly specify the common
namespace and the type.
2022-11-28 10:00:37 -05:00
Lioncash
7f42432f42 common/input: Pass ParamPackage by const reference in CreateDevice
This was previously being passed by value, which was unnecessary and
created more allocations than necessary.
2022-11-28 09:11:58 -05:00
Lioncash
e96f55b6e2 yuzu/main: Merge variable declaration into ifdef
This is only used in the non-Windows path.
2022-11-28 08:40:41 -05:00
german77
7d8095d944 input_common: Pump sdl events from main thread 2022-11-27 11:09:40 -06:00
bunnei
8f6245be9a core: Use atomic instead of a lock to protect is_paused.
- This allows us to call IsPaused() elsewhere if we are holding the suspend lock.
2022-11-26 13:46:38 -08:00
lat9nq
35319ca3a5 startup_checks: Use fmt::print, fix exec error handling
Uses fmt::print opposed to std::fprintf for error printing.

Call exit instead of returning to caller to prevent a like issue the
previous commit was trying to solve.

Removes unneeded comment.

Co-authored-by: liamwhite <liamwhite@users.noreply.github.com>
Co-authored-by: Lioncash <mathew1800@gmail.com>
2022-11-23 21:59:24 -05:00
lat9nq
3e6c835a64 startup_checks: Use Windows flow for *nix
Spawns a child using fork and exec as opposed to fork alone. Workaround
for the macos file manager complaining about not supporting fork without
exec.

Control flow for *nix is now roughly the same as for Windows.
2022-11-23 21:35:47 -05:00
42 changed files with 387 additions and 316 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.22)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")

View File

@@ -69,7 +69,6 @@ if (YUZU_USE_EXTERNAL_SDL2)
set(SDL_SHARED OFF)
add_subdirectory(SDL EXCLUDE_FROM_ALL)
add_library(SDL2 ALIAS SDL2-static)
endif()
# ENet

View File

@@ -226,6 +226,10 @@ if(ENABLE_CUBEB)
target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
endif()
if(ENABLE_SDL2)
target_link_libraries(audio_core PRIVATE SDL2)
if (YUZU_USE_EXTERNAL_SDL2)
target_link_libraries(audio_core PRIVATE SDL2-static)
else()
target_link_libraries(audio_core PRIVATE SDL2)
endif()
target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
endif()

View File

@@ -266,19 +266,20 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
}
void SinkStream::Stall() {
if (stalled) {
std::scoped_lock lk{stall_guard};
if (stalled_lock) {
return;
}
stalled = true;
system.StallProcesses();
stalled_lock = system.StallProcesses();
}
void SinkStream::Unstall() {
if (!stalled) {
std::scoped_lock lk{stall_guard};
if (!stalled_lock) {
return;
}
system.UnstallProcesses();
stalled = false;
stalled_lock.unlock();
}
} // namespace AudioCore::Sink

View File

@@ -6,6 +6,7 @@
#include <array>
#include <atomic>
#include <memory>
#include <mutex>
#include <span>
#include <vector>
@@ -240,8 +241,8 @@ private:
f32 system_volume{1.0f};
/// Set via IAudioDevice service calls
f32 device_volume{1.0f};
/// True if coretiming has been stalled
bool stalled{false};
std::mutex stall_guard;
std::unique_lock<std::mutex> stalled_lock;
};
using SinkStreamPtr = std::unique_ptr<SinkStream>;

View File

@@ -1,11 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdint>
#include <cstring>
#include "alignment.h"
#include "cache_management.h"
#include "common_types.h"
#include "common/cache_management.h"
namespace Common {

View File

@@ -3,7 +3,7 @@
#pragma once
#include "stdlib.h"
#include <cstddef>
namespace Common {

View File

@@ -383,6 +383,16 @@ void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDevic
}
}
inline void RegisterInputFactory(const std::string& name,
std::shared_ptr<Factory<InputDevice>> factory) {
RegisterFactory<InputDevice>(name, std::move(factory));
}
inline void RegisterOutputFactory(const std::string& name,
std::shared_ptr<Factory<OutputDevice>> factory) {
RegisterFactory<OutputDevice>(name, std::move(factory));
}
/**
* Unregisters an input device factory.
* @tparam InputDeviceType the type of input devices the factory can create
@@ -395,6 +405,14 @@ void UnregisterFactory(const std::string& name) {
}
}
inline void UnregisterInputFactory(const std::string& name) {
UnregisterFactory<InputDevice>(name);
}
inline void UnregisterOutputFactory(const std::string& name) {
UnregisterFactory<OutputDevice>(name);
}
/**
* Create an input device from given paramters.
* @tparam InputDeviceType the type of input devices to create
@@ -416,13 +434,21 @@ std::unique_ptr<InputDeviceType> CreateDeviceFromString(const std::string& param
return pair->second->Create(package);
}
inline std::unique_ptr<InputDevice> CreateInputDeviceFromString(const std::string& params) {
return CreateDeviceFromString<InputDevice>(params);
}
inline std::unique_ptr<OutputDevice> CreateOutputDeviceFromString(const std::string& params) {
return CreateDeviceFromString<OutputDevice>(params);
}
/**
* Create an input device from given paramters.
* Create an input device from given parameters.
* @tparam InputDeviceType the type of input devices to create
* @param A ParamPackage that contains all parameters for creating the device
* @param package A ParamPackage that contains all parameters for creating the device
*/
template <typename InputDeviceType>
std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package) {
std::unique_ptr<InputDeviceType> CreateDevice(const ParamPackage& package) {
const std::string engine = package.Get("engine", "null");
const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
const auto pair = factory_list.find(engine);
@@ -435,4 +461,12 @@ std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package
return pair->second->Create(package);
}
inline std::unique_ptr<InputDevice> CreateInputDevice(const ParamPackage& package) {
return CreateDevice<InputDevice>(package);
}
inline std::unique_ptr<OutputDevice> CreateOutputDevice(const ParamPackage& package) {
return CreateDevice<OutputDevice>(package);
}
} // namespace Common::Input

View File

@@ -189,7 +189,7 @@ struct System::Impl {
kernel.Suspend(false);
core_timing.SyncPause(false);
is_paused = false;
is_paused.store(false, std::memory_order_relaxed);
return status;
}
@@ -200,14 +200,13 @@ struct System::Impl {
core_timing.SyncPause(true);
kernel.Suspend(true);
is_paused = true;
is_paused.store(true, std::memory_order_relaxed);
return status;
}
bool IsPaused() const {
std::unique_lock lk(suspend_guard);
return is_paused;
return is_paused.load(std::memory_order_relaxed);
}
std::unique_lock<std::mutex> StallProcesses() {
@@ -218,7 +217,7 @@ struct System::Impl {
}
void UnstallProcesses() {
if (!is_paused) {
if (!IsPaused()) {
core_timing.SyncPause(false);
kernel.Suspend(false);
}
@@ -465,7 +464,7 @@ struct System::Impl {
}
mutable std::mutex suspend_guard;
bool is_paused{};
std::atomic_bool is_paused{};
std::atomic<bool> is_shutting_down{};
Timing::CoreTiming core_timing;

View File

@@ -68,7 +68,7 @@ void EmulatedConsole::ReloadInput() {
// If you load any device here add the equivalent to the UnloadInput() function
SetTouchParams();
motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params);
motion_devices = Common::Input::CreateInputDevice(motion_params);
if (motion_devices) {
motion_devices->SetCallback({
.on_change =
@@ -79,7 +79,7 @@ void EmulatedConsole::ReloadInput() {
// Unique index for identifying touch device source
std::size_t index = 0;
for (auto& touch_device : touch_devices) {
touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]);
touch_device = Common::Input::CreateInputDevice(touch_params[index]);
if (!touch_device) {
continue;
}

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include "common/thread.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/input_converter.h"
@@ -144,29 +146,23 @@ void EmulatedController::LoadDevices() {
LoadTASParams();
std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
stick_params.begin() + Settings::NativeAnalog::STICK_HID_END,
stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
motion_params.begin() + Settings::NativeMotion::MOTION_HID_END,
motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
camera_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(camera_params);
nfc_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(nfc_params);
std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
Common::Input::CreateDevice<Common::Input::OutputDevice>);
std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice);
std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice);
std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice);
std::ranges::transform(trigger_params, trigger_devices.begin(),
Common::Input::CreateInputDevice);
std::ranges::transform(battery_params, battery_devices.begin(),
Common::Input::CreateInputDevice);
camera_devices = Common::Input::CreateInputDevice(camera_params);
nfc_devices = Common::Input::CreateInputDevice(nfc_params);
std::ranges::transform(output_params, output_devices.begin(),
Common::Input::CreateOutputDevice);
// Initialize TAS devices
std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
std::ranges::transform(tas_button_params, tas_button_devices.begin(),
Common::Input::CreateInputDevice);
std::ranges::transform(tas_stick_params, tas_stick_devices.begin(),
Common::Input::CreateInputDevice);
}
void EmulatedController::LoadTASParams() {

View File

@@ -25,12 +25,12 @@ void EmulatedDevices::ReloadInput() {
Common::ParamPackage mouse_params;
mouse_params.Set("engine", "mouse");
mouse_params.Set("button", static_cast<int>(key_index));
mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params);
mouse_device = Common::Input::CreateInputDevice(mouse_params);
key_index++;
}
mouse_stick_device = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
"engine:mouse,axis_x:0,axis_y:1");
mouse_stick_device =
Common::Input::CreateInputDeviceFromString("engine:mouse,axis_x:0,axis_y:1");
// First two axis are reserved for mouse position
key_index = 2;
@@ -38,7 +38,7 @@ void EmulatedDevices::ReloadInput() {
Common::ParamPackage mouse_params;
mouse_params.Set("engine", "mouse");
mouse_params.Set("axis", static_cast<int>(key_index));
mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params);
mouse_device = Common::Input::CreateInputDevice(mouse_params);
key_index++;
}
@@ -50,7 +50,7 @@ void EmulatedDevices::ReloadInput() {
keyboard_params.Set("button", static_cast<int>(key_index));
keyboard_params.Set("port", 1);
keyboard_params.Set("pad", 0);
keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params);
keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
key_index++;
}
@@ -62,11 +62,11 @@ void EmulatedDevices::ReloadInput() {
keyboard_params.Set("button", static_cast<int>(key_index));
keyboard_params.Set("port", 1);
keyboard_params.Set("pad", 1);
keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params);
keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
key_index++;
}
ring_analog_device = Common::Input::CreateDevice<Common::Input::InputDevice>(ring_params);
ring_analog_device = Common::Input::CreateInputDevice(ring_params);
for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
if (!mouse_button_devices[index]) {

View File

@@ -28,13 +28,15 @@ SyncpointManager::SyncpointManager(Tegra::Host1x::Host1x& host1x_) : host1x{host
SyncpointManager::~SyncpointManager() = default;
u32 SyncpointManager::ReserveSyncpoint(u32 id, bool client_managed) {
if (syncpoints.at(id).reserved) {
auto& syncpoint = syncpoints.at(id);
if (syncpoint.reserved) {
ASSERT_MSG(false, "Requested syncpoint is in use");
return 0;
}
syncpoints.at(id).reserved = true;
syncpoints.at(id).interface_managed = client_managed;
syncpoint.reserved = true;
syncpoint.interface_managed = client_managed;
return id;
}
@@ -56,11 +58,12 @@ u32 SyncpointManager::AllocateSyncpoint(bool client_managed) {
void SyncpointManager::FreeSyncpoint(u32 id) {
std::lock_guard lock(reservation_lock);
ASSERT(syncpoints.at(id).reserved);
syncpoints.at(id).reserved = false;
auto& syncpoint = syncpoints.at(id);
ASSERT(syncpoint.reserved);
syncpoint.reserved = false;
}
bool SyncpointManager::IsSyncpointAllocated(u32 id) {
bool SyncpointManager::IsSyncpointAllocated(u32 id) const {
return (id <= SyncpointCount) && syncpoints[id].reserved;
}
@@ -69,7 +72,7 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const {
if (!syncpoint.reserved) {
ASSERT(false);
return 0;
return false;
}
// If the interface manages counters then we don't keep track of the maximum value as it handles
@@ -82,40 +85,51 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const {
}
u32 SyncpointManager::IncrementSyncpointMaxExt(u32 id, u32 amount) {
if (!syncpoints.at(id).reserved) {
auto& syncpoint = syncpoints.at(id);
if (!syncpoint.reserved) {
ASSERT(false);
return 0;
}
return syncpoints.at(id).counter_max += amount;
return syncpoint.counter_max += amount;
}
u32 SyncpointManager::ReadSyncpointMinValue(u32 id) {
if (!syncpoints.at(id).reserved) {
auto& syncpoint = syncpoints.at(id);
if (!syncpoint.reserved) {
ASSERT(false);
return 0;
}
return syncpoints.at(id).counter_min;
return syncpoint.counter_min;
}
u32 SyncpointManager::UpdateMin(u32 id) {
if (!syncpoints.at(id).reserved) {
auto& syncpoint = syncpoints.at(id);
if (!syncpoint.reserved) {
ASSERT(false);
return 0;
}
syncpoints.at(id).counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id);
return syncpoints.at(id).counter_min;
syncpoint.counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id);
return syncpoint.counter_min;
}
NvFence SyncpointManager::GetSyncpointFence(u32 id) {
if (!syncpoints.at(id).reserved) {
auto& syncpoint = syncpoints.at(id);
if (!syncpoint.reserved) {
ASSERT(false);
return NvFence{};
}
return {.id = static_cast<s32>(id), .value = syncpoints.at(id).counter_max};
return {
.id = static_cast<s32>(id),
.value = syncpoint.counter_max,
};
}
} // namespace Service::Nvidia::NvCore

View File

@@ -44,7 +44,7 @@ public:
/**
* @brief Checks if the given syncpoint is both allocated and below the number of HW syncpoints
*/
bool IsSyncpointAllocated(u32 id);
bool IsSyncpointAllocated(u32 id) const;
/**
* @brief Finds a free syncpoint and reserves it

View File

@@ -55,48 +55,40 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
Module::Module(Core::System& system)
: container{system.Host1x()}, service_context{system, "nvdrv"}, events_interface{*this} {
builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-gpu"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_gpu>(system, events_interface, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_gpu>(system, events_interface, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-ctrl-gpu"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvmap"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvmap>(system, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvmap>(system, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvdisp_disp0"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvdisp_disp0>(system, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvdisp_disp0>(system, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-ctrl"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-nvdec"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_nvdec>(system, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_nvdec>(system, container);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-nvjpg"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device = std::make_shared<Devices::nvhost_nvjpg>(system);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_nvjpg>(system);
return open_files.emplace(fd, std::move(device)).first;
};
builders["/dev/nvhost-vic"] = [this, &system](DeviceFD fd) {
std::shared_ptr<Devices::nvdevice> device =
std::make_shared<Devices::nvhost_vic>(system, container);
return open_files.emplace(fd, device).first;
auto device = std::make_shared<Devices::nvhost_vic>(system, container);
return open_files.emplace(fd, std::move(device)).first;
};
}

View File

@@ -10,6 +10,7 @@ namespace Service::android {
class IProducerListener {
public:
virtual ~IProducerListener() = default;
virtual void OnBufferReleased() = 0;
};

View File

@@ -55,7 +55,11 @@ if (ENABLE_SDL2)
drivers/sdl_driver.cpp
drivers/sdl_driver.h
)
target_link_libraries(input_common PRIVATE SDL2)
if (YUZU_USE_EXTERNAL_SDL2)
target_link_libraries(input_common PRIVATE SDL2-static)
else()
target_link_libraries(input_common PRIVATE SDL2)
endif()
target_compile_definitions(input_common PRIVATE HAVE_SDL2)
endif()

View File

@@ -361,6 +361,12 @@ void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {
}
}
void SDLDriver::PumpEvents() const {
if (initialized) {
SDL_PumpEvents();
}
}
void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
switch (event.type) {
case SDL_JOYBUTTONUP: {
@@ -451,14 +457,6 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
initialized = true;
if (start_thread) {
poll_thread = std::thread([this] {
Common::SetCurrentThreadName("SDL_MainLoop");
using namespace std::chrono_literals;
while (initialized) {
SDL_PumpEvents();
std::this_thread::sleep_for(1ms);
}
});
vibration_thread = std::thread([this] {
Common::SetCurrentThreadName("SDL_Vibration");
using namespace std::chrono_literals;
@@ -481,7 +479,6 @@ SDLDriver::~SDLDriver() {
initialized = false;
if (start_thread) {
poll_thread.join();
vibration_thread.join();
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
}

View File

@@ -36,6 +36,8 @@ public:
/// Unregisters SDL device factories and shut them down.
~SDLDriver() override;
void PumpEvents() const;
/// Handle SDL_Events for joysticks from SDL_PollEvent
void HandleGameControllerEvent(const SDL_Event& event);
@@ -128,7 +130,6 @@ private:
bool start_thread = false;
std::atomic<bool> initialized = false;
std::thread poll_thread;
std::thread vibration_thread;
};
} // namespace InputCommon

View File

@@ -294,6 +294,15 @@ public:
}
private:
static constexpr Common::Input::AnalogProperties properties{
.deadzone = 0.0f,
.range = 1.0f,
.threshold = 0.5f,
.offset = 0.0f,
.inverted = false,
.toggle = false,
};
Button up;
Button down;
Button left;
@@ -311,23 +320,17 @@ private:
float last_x_axis_value{};
float last_y_axis_value{};
Common::Input::ButtonStatus modifier_status{};
const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
std::chrono::time_point<std::chrono::steady_clock> last_update;
};
std::unique_ptr<Common::Input::InputDevice> StickFromButton::Create(
const Common::ParamPackage& params) {
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
auto up = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("up", null_engine));
auto down = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("down", null_engine));
auto left = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("left", null_engine));
auto right = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("right", null_engine));
auto modifier = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("modifier", null_engine));
auto up = Common::Input::CreateInputDeviceFromString(params.Get("up", null_engine));
auto down = Common::Input::CreateInputDeviceFromString(params.Get("down", null_engine));
auto left = Common::Input::CreateInputDeviceFromString(params.Get("left", null_engine));
auto right = Common::Input::CreateInputDeviceFromString(params.Get("right", null_engine));
auto modifier = Common::Input::CreateInputDeviceFromString(params.Get("modifier", null_engine));
auto modifier_scale = params.Get("modifier_scale", 0.5f);
auto modifier_angle = params.Get("modifier_angle", 5.5f);
return std::make_unique<Stick>(std::move(up), std::move(down), std::move(left),

View File

@@ -59,18 +59,25 @@ public:
}
private:
static constexpr Common::Input::AnalogProperties properties{
.deadzone = 0.0f,
.range = 1.0f,
.threshold = 0.5f,
.offset = 0.0f,
.inverted = false,
.toggle = false,
};
Button button;
bool last_button_value;
const float x;
const float y;
const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
};
std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create(
const Common::ParamPackage& params) {
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
params.Get("button", null_engine));
auto button = Common::Input::CreateInputDeviceFromString(params.Get("button", null_engine));
const float x = params.Get("x", 0.0f) / 1280.0f;
const float y = params.Get("y", 0.0f) / 720.0f;
return std::make_unique<TouchFromButtonDevice>(std::move(button), x, y);

View File

@@ -33,129 +33,113 @@ struct InputSubsystem::Impl {
keyboard->SetMappingCallback(mapping_callback);
keyboard_factory = std::make_shared<InputFactory>(keyboard);
keyboard_output_factory = std::make_shared<OutputFactory>(keyboard);
Common::Input::RegisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName(),
keyboard_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName(),
keyboard_output_factory);
Common::Input::RegisterInputFactory(keyboard->GetEngineName(), keyboard_factory);
Common::Input::RegisterOutputFactory(keyboard->GetEngineName(), keyboard_output_factory);
mouse = std::make_shared<Mouse>("mouse");
mouse->SetMappingCallback(mapping_callback);
mouse_factory = std::make_shared<InputFactory>(mouse);
mouse_output_factory = std::make_shared<OutputFactory>(mouse);
Common::Input::RegisterFactory<Common::Input::InputDevice>(mouse->GetEngineName(),
mouse_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName(),
mouse_output_factory);
Common::Input::RegisterInputFactory(mouse->GetEngineName(), mouse_factory);
Common::Input::RegisterOutputFactory(mouse->GetEngineName(), mouse_output_factory);
touch_screen = std::make_shared<TouchScreen>("touch");
touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
Common::Input::RegisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName(),
touch_screen_factory);
Common::Input::RegisterInputFactory(touch_screen->GetEngineName(), touch_screen_factory);
gcadapter = std::make_shared<GCAdapter>("gcpad");
gcadapter->SetMappingCallback(mapping_callback);
gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
Common::Input::RegisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName(),
gcadapter_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName(),
gcadapter_output_factory);
Common::Input::RegisterInputFactory(gcadapter->GetEngineName(), gcadapter_input_factory);
Common::Input::RegisterOutputFactory(gcadapter->GetEngineName(), gcadapter_output_factory);
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
udp_client->SetMappingCallback(mapping_callback);
udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
udp_client_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName(),
udp_client_output_factory);
Common::Input::RegisterInputFactory(udp_client->GetEngineName(), udp_client_input_factory);
Common::Input::RegisterOutputFactory(udp_client->GetEngineName(),
udp_client_output_factory);
tas_input = std::make_shared<TasInput::Tas>("tas");
tas_input->SetMappingCallback(mapping_callback);
tas_input_factory = std::make_shared<InputFactory>(tas_input);
tas_output_factory = std::make_shared<OutputFactory>(tas_input);
Common::Input::RegisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName(),
tas_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(),
tas_output_factory);
Common::Input::RegisterInputFactory(tas_input->GetEngineName(), tas_input_factory);
Common::Input::RegisterOutputFactory(tas_input->GetEngineName(), tas_output_factory);
camera = std::make_shared<Camera>("camera");
camera->SetMappingCallback(mapping_callback);
camera_input_factory = std::make_shared<InputFactory>(camera);
camera_output_factory = std::make_shared<OutputFactory>(camera);
Common::Input::RegisterFactory<Common::Input::InputDevice>(camera->GetEngineName(),
camera_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(),
camera_output_factory);
Common::Input::RegisterInputFactory(camera->GetEngineName(), camera_input_factory);
Common::Input::RegisterOutputFactory(camera->GetEngineName(), camera_output_factory);
virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo");
virtual_amiibo->SetMappingCallback(mapping_callback);
virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo);
virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo);
Common::Input::RegisterFactory<Common::Input::InputDevice>(virtual_amiibo->GetEngineName(),
virtual_amiibo_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(virtual_amiibo->GetEngineName(),
virtual_amiibo_output_factory);
Common::Input::RegisterInputFactory(virtual_amiibo->GetEngineName(),
virtual_amiibo_input_factory);
Common::Input::RegisterOutputFactory(virtual_amiibo->GetEngineName(),
virtual_amiibo_output_factory);
#ifdef HAVE_SDL2
sdl = std::make_shared<SDLDriver>("sdl");
sdl->SetMappingCallback(mapping_callback);
sdl_input_factory = std::make_shared<InputFactory>(sdl);
sdl_output_factory = std::make_shared<OutputFactory>(sdl);
Common::Input::RegisterFactory<Common::Input::InputDevice>(sdl->GetEngineName(),
sdl_input_factory);
Common::Input::RegisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName(),
sdl_output_factory);
Common::Input::RegisterInputFactory(sdl->GetEngineName(), sdl_input_factory);
Common::Input::RegisterOutputFactory(sdl->GetEngineName(), sdl_output_factory);
#endif
Common::Input::RegisterFactory<Common::Input::InputDevice>(
"touch_from_button", std::make_shared<TouchFromButton>());
Common::Input::RegisterFactory<Common::Input::InputDevice>(
"analog_from_button", std::make_shared<StickFromButton>());
Common::Input::RegisterInputFactory("touch_from_button",
std::make_shared<TouchFromButton>());
Common::Input::RegisterInputFactory("analog_from_button",
std::make_shared<StickFromButton>());
}
void Shutdown() {
Common::Input::UnregisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName());
Common::Input::UnregisterInputFactory(keyboard->GetEngineName());
Common::Input::UnregisterOutputFactory(keyboard->GetEngineName());
keyboard.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(mouse->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName());
Common::Input::UnregisterInputFactory(mouse->GetEngineName());
Common::Input::UnregisterOutputFactory(mouse->GetEngineName());
mouse.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName());
Common::Input::UnregisterInputFactory(touch_screen->GetEngineName());
touch_screen.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName());
Common::Input::UnregisterInputFactory(gcadapter->GetEngineName());
Common::Input::UnregisterOutputFactory(gcadapter->GetEngineName());
gcadapter.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName());
Common::Input::UnregisterInputFactory(udp_client->GetEngineName());
Common::Input::UnregisterOutputFactory(udp_client->GetEngineName());
udp_client.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName());
Common::Input::UnregisterInputFactory(tas_input->GetEngineName());
Common::Input::UnregisterOutputFactory(tas_input->GetEngineName());
tas_input.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(camera->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(camera->GetEngineName());
Common::Input::UnregisterInputFactory(camera->GetEngineName());
Common::Input::UnregisterOutputFactory(camera->GetEngineName());
camera.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(
virtual_amiibo->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(
virtual_amiibo->GetEngineName());
Common::Input::UnregisterInputFactory(virtual_amiibo->GetEngineName());
Common::Input::UnregisterOutputFactory(virtual_amiibo->GetEngineName());
virtual_amiibo.reset();
#ifdef HAVE_SDL2
Common::Input::UnregisterFactory<Common::Input::InputDevice>(sdl->GetEngineName());
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName());
Common::Input::UnregisterInputFactory(sdl->GetEngineName());
Common::Input::UnregisterOutputFactory(sdl->GetEngineName());
sdl.reset();
#endif
Common::Input::UnregisterFactory<Common::Input::InputDevice>("touch_from_button");
Common::Input::UnregisterFactory<Common::Input::InputDevice>("analog_from_button");
Common::Input::UnregisterInputFactory("touch_from_button");
Common::Input::UnregisterInputFactory("analog_from_button");
}
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
@@ -334,6 +318,12 @@ struct InputSubsystem::Impl {
#endif
}
void PumpEvents() const {
#ifdef HAVE_SDL2
sdl->PumpEvents();
#endif
}
void RegisterInput(const MappingData& data) {
mapping_factory->RegisterInput(data);
}
@@ -482,6 +472,10 @@ void InputSubsystem::StopMapping() const {
impl->mapping_factory->StopMapping();
}
void InputSubsystem::PumpEvents() const {
impl->PumpEvents();
}
std::string GenerateKeyboardParam(int key_code) {
Common::ParamPackage param;
param.Set("engine", "keyboard");

View File

@@ -147,6 +147,9 @@ public:
/// Stop polling from all backends.
void StopMapping() const;
/// Signals SDL driver for new input events
void PumpEvents() const;
private:
struct Impl;
std::unique_ptr<Impl> impl;

View File

@@ -253,8 +253,8 @@ if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32)
add_dependencies(video_core ffmpeg-build)
endif()
target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR})
target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES})
target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_avcodec} ${FFmpeg_INCLUDE_avutil} ${FFmpeg_INCLUDE_swscale})
target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARY_avcodec} ${FFmpeg_LIBRARY_avutil} ${FFmpeg_LIBRARY_swscale})
target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
add_dependencies(video_core host_shaders)

View File

@@ -49,10 +49,9 @@ void State::ProcessData(std::span<const u8> read_buffer) {
if (regs.line_count == 1) {
rasterizer->AccelerateInlineToMemory(address, copy_size, read_buffer);
} else {
for (u32 line = 0; line < regs.line_count; ++line) {
const GPUVAddr dest_line = address + static_cast<size_t>(line) * regs.dest.pitch;
std::span<const u8> buffer(read_buffer.data() +
static_cast<size_t>(line) * regs.line_length_in,
for (size_t line = 0; line < regs.line_count; ++line) {
const GPUVAddr dest_line = address + line * regs.dest.pitch;
std::span<const u8> buffer(read_buffer.data() + line * regs.line_length_in,
regs.line_length_in);
rasterizer->AccelerateInlineToMemory(dest_line, regs.line_length_in, buffer);
}

View File

@@ -39,7 +39,7 @@ struct Registers {
u32 y;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
u32 BlockWidth() const {

View File

@@ -97,7 +97,7 @@ public:
u32 addr_lower;
[[nodiscard]] constexpr GPUVAddr Address() const noexcept {
return (static_cast<GPUVAddr>(addr_upper) << 32) | static_cast<GPUVAddr>(addr_lower);
return (GPUVAddr{addr_upper} << 32) | GPUVAddr{addr_lower};
}
};
static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size");

View File

@@ -50,11 +50,11 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun
u32 methods_pending) {
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(data_upload):
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
upload_state.ProcessData(base_start, amount);
return;
default:
for (std::size_t i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1);
}
break;
}

View File

@@ -68,7 +68,7 @@ public:
struct {
u32 address;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address) << 8));
return GPUVAddr{address} << 8;
}
} launch_desc_loc;
@@ -83,8 +83,7 @@ public:
u32 address_low;
u32 limit;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
} tsc;
@@ -95,8 +94,7 @@ public:
u32 address_low;
u32 limit;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
} tic;
@@ -106,8 +104,7 @@ public:
u32 address_high;
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
} code_loc;
@@ -162,8 +159,7 @@ public:
BitField<15, 17, u32> size;
};
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high.Value()) << 32) |
address_low);
return (GPUVAddr{address_high.Value()} << 32) | GPUVAddr{address_low};
}
};
std::array<ConstBufferConfig, NumConstBuffers> const_buffer_config;

View File

@@ -42,11 +42,11 @@ void KeplerMemory::CallMultiMethod(u32 method, const u32* base_start, u32 amount
u32 methods_pending) {
switch (method) {
case KEPLERMEMORY_REG_INDEX(data):
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
upload_state.ProcessData(base_start, amount);
return;
default:
for (std::size_t i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1);
}
break;
}

View File

@@ -370,11 +370,11 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
ProcessCBMultiData(base_start, amount);
break;
case MAXWELL3D_REG_INDEX(inline_data):
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
upload_state.ProcessData(base_start, amount);
return;
default:
for (std::size_t i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1);
}
break;
}
@@ -652,12 +652,12 @@ void Maxwell3D::ProcessDeferredDraw() {
return;
}
u32 method_count = static_cast<u32>(deferred_draw_method.size());
const auto method_count = deferred_draw_method.size();
u32 instance_count = 1;
u32 vertex_buffer_count = 0;
u32 index_buffer_count = 0;
for (u32 index = 0; index < method_count; ++index) {
u32 method = deferred_draw_method[index];
for (size_t index = 0; index < method_count; ++index) {
const u32 method = deferred_draw_method[index];
if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
instance_count = ++vertex_buffer_count;
} else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {

View File

@@ -96,8 +96,7 @@ public:
u32 type;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -106,8 +105,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -124,8 +122,7 @@ public:
Mode mode;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(offset_high) << 32) |
offset_low);
return (GPUVAddr{offset_high} << 32) | GPUVAddr{offset_low};
}
};
@@ -187,7 +184,7 @@ public:
default:
// Thresholds begin at 0x10 (1 << 4)
// Threshold is in the range 0x1 to 0x13
return 1 << (4 + threshold.Value() - 1);
return 1U << (4 + threshold.Value() - 1);
}
}
};
@@ -468,8 +465,7 @@ public:
INSERT_PADDING_BYTES_NOINIT(0xC);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
static_assert(sizeof(Buffer) == 0x20);
@@ -511,12 +507,11 @@ public:
u32 default_size_per_warp;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
u64 Size() const {
return (static_cast<u64>(size_high) << 32) | size_low;
return (u64{size_high} << 32) | u64{size_low};
}
};
@@ -538,13 +533,11 @@ public:
u32 storage_limit_address_low;
GPUVAddr StorageAddress() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(storage_address_high) << 32) |
storage_address_low);
return (GPUVAddr{storage_address_high} << 32) | GPUVAddr{storage_address_low};
}
GPUVAddr StorageLimitAddress() const {
return static_cast<GPUVAddr>(
(static_cast<GPUVAddr>(storage_limit_address_high) << 32) |
storage_limit_address_low);
return (GPUVAddr{storage_limit_address_high} << 32) |
GPUVAddr{storage_limit_address_low};
}
};
@@ -829,11 +822,11 @@ public:
struct CompressionThresholdSamples {
u32 samples;
u32 Samples() {
u32 Samples() const {
if (samples == 0) {
return 0;
}
return 1 << (samples - 1);
return 1U << (samples - 1);
}
};
@@ -1138,8 +1131,7 @@ public:
INSERT_PADDING_BYTES_NOINIT(0x18);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
static_assert(sizeof(RenderTargetConfig) == 0x40);
@@ -1482,8 +1474,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1533,8 +1524,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1561,8 +1551,7 @@ public:
u32 array_pitch;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1910,8 +1899,7 @@ public:
Mode mode;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1921,8 +1909,7 @@ public:
u32 limit;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1932,8 +1919,7 @@ public:
u32 limit;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -1981,8 +1967,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -2027,8 +2012,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -2224,19 +2208,16 @@ public:
}
GPUVAddr StartAddress() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_addr_high) << 32) |
start_addr_low);
return (GPUVAddr{start_addr_high} << 32) | GPUVAddr{start_addr_low};
}
GPUVAddr EndAddress() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_addr_high) << 32) |
limit_addr_low);
return (GPUVAddr{limit_addr_high} << 32) | GPUVAddr{limit_addr_low};
}
/// Adjust the index buffer offset so it points to the first desired index.
GPUVAddr IndexStart() const {
return StartAddress() +
static_cast<size_t>(first) * static_cast<size_t>(FormatSizeInBytes());
return StartAddress() + size_t{first} * size_t{FormatSizeInBytes()};
}
};
@@ -2464,8 +2445,7 @@ public:
} query;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
@@ -2479,8 +2459,7 @@ public:
u32 frequency;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
bool IsEnabled() const {
@@ -2494,8 +2473,7 @@ public:
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};
static_assert(sizeof(VertexStreamLimit) == 0x8);
@@ -2543,8 +2521,7 @@ public:
std::array<u32, NumCBData> buffer;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};
}
};

View File

@@ -41,8 +41,8 @@ void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call)
void MaxwellDMA::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
u32 methods_pending) {
for (size_t i = 0; i < amount; ++i) {
CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
for (u32 i = 0; i < amount; ++i) {
CallMethod(method, base_start[i], methods_pending - i <= 1);
}
}
@@ -94,14 +94,14 @@ void MaxwellDMA::Launch() {
reinterpret_cast<u8*>(tmp_buffer.data()),
regs.line_length_in * sizeof(u32));
} else {
auto convert_linear_2_blocklinear_addr = [](u64 address) {
const auto convert_linear_2_blocklinear_addr = [](u64 address) {
return (address & ~0x1f0ULL) | ((address & 0x40) >> 2) | ((address & 0x10) << 1) |
((address & 0x180) >> 1) | ((address & 0x20) << 3);
};
auto src_kind = memory_manager.GetPageKind(regs.offset_in);
auto dst_kind = memory_manager.GetPageKind(regs.offset_out);
const bool is_src_pitch = IsPitchKind(static_cast<PTEKind>(src_kind));
const bool is_dst_pitch = IsPitchKind(static_cast<PTEKind>(dst_kind));
const auto src_kind = memory_manager.GetPageKind(regs.offset_in);
const auto dst_kind = memory_manager.GetPageKind(regs.offset_out);
const bool is_src_pitch = IsPitchKind(src_kind);
const bool is_dst_pitch = IsPitchKind(dst_kind);
if (!is_src_pitch && is_dst_pitch) {
UNIMPLEMENTED_IF(regs.line_length_in % 16 != 0);
UNIMPLEMENTED_IF(regs.offset_in % 16 != 0);

View File

@@ -31,7 +31,7 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) {
LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,
method_call.argument);
const auto engine_id = static_cast<EngineID>(method_call.argument);
bound_engines[method_call.subchannel] = static_cast<EngineID>(engine_id);
bound_engines[method_call.subchannel] = engine_id;
switch (engine_id) {
case EngineID::FERMI_TWOD_A:
dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel);
@@ -285,12 +285,12 @@ void Puller::CallMultiMethod(u32 method, u32 subchannel, const u32* base_start,
if (ExecuteMethodOnEngine(method)) {
CallEngineMultiMethod(method, subchannel, base_start, amount, methods_pending);
} else {
for (std::size_t i = 0; i < amount; i++) {
for (u32 i = 0; i < amount; i++) {
CallPullerMethod(MethodCall{
method,
base_start[i],
subchannel,
methods_pending - static_cast<u32>(i),
methods_pending - i,
});
}
}

View File

@@ -34,7 +34,7 @@ SyncpointManager::ActionHandle SyncpointManager::RegisterAction(
}
void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_storage,
ActionHandle& handle) {
const ActionHandle& handle) {
std::unique_lock lk(guard);
// We want to ensure the iterator still exists prior to erasing it
@@ -49,11 +49,11 @@ void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_stor
}
}
void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle) {
void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, const ActionHandle& handle) {
DeregisterAction(guest_action_storage[syncpoint_id], handle);
}
void SyncpointManager::DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle) {
void SyncpointManager::DeregisterHostAction(u32 syncpoint_id, const ActionHandle& handle) {
DeregisterAction(host_action_storage[syncpoint_id], handle);
}

View File

@@ -36,21 +36,19 @@ public:
template <typename Func>
ActionHandle RegisterGuestAction(u32 syncpoint_id, u32 expected_value, Func&& action) {
std::function<void()> func(action);
return RegisterAction(syncpoints_guest[syncpoint_id], guest_action_storage[syncpoint_id],
expected_value, std::move(func));
expected_value, std::move(action));
}
template <typename Func>
ActionHandle RegisterHostAction(u32 syncpoint_id, u32 expected_value, Func&& action) {
std::function<void()> func(action);
return RegisterAction(syncpoints_host[syncpoint_id], host_action_storage[syncpoint_id],
expected_value, std::move(func));
expected_value, std::move(action));
}
void DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle);
void DeregisterGuestAction(u32 syncpoint_id, const ActionHandle& handle);
void DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle);
void DeregisterHostAction(u32 syncpoint_id, const ActionHandle& handle);
void IncrementGuest(u32 syncpoint_id);
@@ -76,7 +74,7 @@ private:
std::list<RegisteredAction>& action_storage, u32 expected_value,
std::function<void()>&& action);
void DeregisterAction(std::list<RegisteredAction>& action_storage, ActionHandle& handle);
void DeregisterAction(std::list<RegisteredAction>& action_storage, const ActionHandle& handle);
void Wait(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, u32 expected_value);

View File

@@ -214,23 +214,16 @@ PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format)
}
SurfaceType GetFormatType(PixelFormat pixel_format) {
if (static_cast<std::size_t>(pixel_format) <
static_cast<std::size_t>(PixelFormat::MaxColorFormat)) {
if (pixel_format < PixelFormat::MaxColorFormat) {
return SurfaceType::ColorTexture;
}
if (static_cast<std::size_t>(pixel_format) <
static_cast<std::size_t>(PixelFormat::MaxDepthFormat)) {
if (pixel_format < PixelFormat::MaxDepthFormat) {
return SurfaceType::Depth;
}
if (static_cast<std::size_t>(pixel_format) <
static_cast<std::size_t>(PixelFormat::MaxStencilFormat)) {
if (pixel_format < PixelFormat::MaxStencilFormat) {
return SurfaceType::Stencil;
}
if (static_cast<std::size_t>(pixel_format) <
static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) {
if (pixel_format < PixelFormat::MaxDepthStencilFormat) {
return SurfaceType::DepthStencil;
}

View File

@@ -387,7 +387,11 @@ if (YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6)
endif()
if (ENABLE_SDL2)
target_link_libraries(yuzu PRIVATE SDL2)
if (YUZU_USE_EXTERNAL_SDL2)
target_link_libraries(yuzu PRIVATE SDL2-static)
else()
target_link_libraries(yuzu PRIVATE SDL2)
endif()
target_compile_definitions(yuzu PRIVATE HAVE_SDL2)
endif()

View File

@@ -167,6 +167,7 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
constexpr int default_mouse_hide_timeout = 2500;
constexpr int default_mouse_center_timeout = 10;
constexpr int default_input_update_timeout = 1;
/**
* "Callouts" are one-time instructional messages shown to the user. In the config settings, there
@@ -405,6 +406,10 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
mouse_center_timer.setInterval(default_mouse_center_timeout);
connect(&mouse_center_timer, &QTimer::timeout, this, &GMainWindow::CenterMouseCursor);
update_input_timer.setInterval(default_input_update_timeout);
connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers);
update_input_timer.start();
MigrateConfigFiles();
if (has_broken_vulkan) {
@@ -3637,6 +3642,13 @@ void GMainWindow::UpdateUISettings() {
UISettings::values.first_start = false;
}
void GMainWindow::UpdateInputDrivers() {
if (!input_subsystem) {
return;
}
input_subsystem->PumpEvents();
}
void GMainWindow::HideMouseCursor() {
if (emu_thread == nullptr && UISettings::values.hide_mouse) {
mouse_hide_timer.stop();
@@ -4037,7 +4049,6 @@ void GMainWindow::UpdateUITheme() {
const QString default_theme =
QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
QString current_theme = UISettings::values.theme;
QStringList theme_paths(default_theme_paths);
if (current_theme.isEmpty()) {
current_theme = default_theme;
@@ -4050,7 +4061,7 @@ void GMainWindow::UpdateUITheme() {
if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {
QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
: startup_icon_theme);
QIcon::setThemeSearchPaths(theme_paths);
QIcon::setThemeSearchPaths(QStringList(default_theme_paths));
if (CheckDarkMode()) {
current_theme = QStringLiteral("default_dark");
}

View File

@@ -353,6 +353,7 @@ private:
void UpdateGPUAccuracyButton();
void UpdateStatusButtons();
void UpdateUISettings();
void UpdateInputDrivers();
void HideMouseCursor();
void ShowMouseCursor();
void CenterMouseCursor();
@@ -404,6 +405,7 @@ private:
bool auto_muted = false;
QTimer mouse_hide_timer;
QTimer mouse_center_timer;
QTimer update_input_timer;
QString startup_icon_theme;
bool os_dark_mode = false;

View File

@@ -4,16 +4,19 @@
#include "video_core/vulkan_common/vulkan_wrapper.h"
#ifdef _WIN32
#include <cstring> // for memset, strncpy
#include <cstring>
#include <processthreadsapi.h>
#include <windows.h>
#elif defined(YUZU_UNIX)
#include <cstring>
#include <errno.h>
#include <spawn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
#include <cstdio>
#include <fmt/core.h>
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_library.h"
#include "yuzu/startup_checks.h"
@@ -27,7 +30,7 @@ void CheckVulkan() {
Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_0);
} catch (const Vulkan::vk::Exception& exception) {
std::fprintf(stderr, "Failed to initialize Vulkan: %s\n", exception.what());
fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what());
}
}
@@ -49,8 +52,15 @@ bool CheckEnvVars(bool* is_child) {
*is_child = true;
return false;
} else if (!SetEnvironmentVariableA(IS_CHILD_ENV_VAR, ENV_VAR_ENABLED_TEXT)) {
std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n",
IS_CHILD_ENV_VAR, GetLastError());
fmt::print(stderr, "SetEnvironmentVariableA failed to set {} with error {}\n",
IS_CHILD_ENV_VAR, GetLastError());
return true;
}
#elif defined(YUZU_UNIX)
const char* startup_check_var = getenv(STARTUP_CHECK_ENV_VAR);
if (startup_check_var != nullptr &&
std::strncmp(startup_check_var, ENV_VAR_ENABLED_TEXT, 8) == 0) {
CheckVulkan();
return true;
}
#endif
@@ -62,8 +72,8 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka
// Set the startup variable for child processes
const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT);
if (!env_var_set) {
std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n",
STARTUP_CHECK_ENV_VAR, GetLastError());
fmt::print(stderr, "SetEnvironmentVariableA failed to set {} with error {}\n",
STARTUP_CHECK_ENV_VAR, GetLastError());
return false;
}
@@ -81,48 +91,57 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka
DWORD exit_code = STILL_ACTIVE;
const int err = GetExitCodeProcess(process_info.hProcess, &exit_code);
if (err == 0) {
std::fprintf(stderr, "GetExitCodeProcess failed with error %lu\n", GetLastError());
fmt::print(stderr, "GetExitCodeProcess failed with error {}\n", GetLastError());
}
// Vulkan is broken if the child crashed (return value is not zero)
*has_broken_vulkan = (exit_code != 0);
if (CloseHandle(process_info.hProcess) == 0) {
std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError());
fmt::print(stderr, "CloseHandle failed with error {}\n", GetLastError());
}
if (CloseHandle(process_info.hThread) == 0) {
std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError());
fmt::print(stderr, "CloseHandle failed with error {}\n", GetLastError());
}
}
if (!SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, nullptr)) {
std::fprintf(stderr, "SetEnvironmentVariableA failed to clear %s with error %lu\n",
STARTUP_CHECK_ENV_VAR, GetLastError());
fmt::print(stderr, "SetEnvironmentVariableA failed to clear {} with error {}\n",
STARTUP_CHECK_ENV_VAR, GetLastError());
}
#elif defined(YUZU_UNIX)
const int env_var_set = setenv(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT, 1);
if (env_var_set == -1) {
const int err = errno;
fmt::print(stderr, "setenv failed to set {} with error {}\n", STARTUP_CHECK_ENV_VAR, err);
return false;
}
if (perform_vulkan_check) {
const pid_t pid = fork();
if (pid == 0) {
CheckVulkan();
return true;
} else if (pid == -1) {
const int err = errno;
std::fprintf(stderr, "fork failed with error %d\n", err);
const pid_t pid = SpawnChild(arg0);
if (pid == -1) {
return false;
}
// Get exit code from child process
int status;
const int r_val = wait(&status);
const int r_val = waitpid(pid, &status, 0);
if (r_val == -1) {
const int err = errno;
std::fprintf(stderr, "wait failed with error %d\n", err);
fmt::print(stderr, "wait failed with error {}\n", err);
return false;
}
// Vulkan is broken if the child crashed (return value is not zero)
*has_broken_vulkan = (status != 0);
}
const int env_var_cleared = unsetenv(STARTUP_CHECK_ENV_VAR);
if (env_var_cleared == -1) {
const int err = errno;
fmt::print(stderr, "unsetenv failed to clear {} with error {}\n", STARTUP_CHECK_ENV_VAR,
err);
}
#endif
return false;
}
@@ -150,10 +169,29 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags) {
pi // lpProcessInformation
);
if (!process_created) {
std::fprintf(stderr, "CreateProcessA failed with error %lu\n", GetLastError());
fmt::print(stderr, "CreateProcessA failed with error {}\n", GetLastError());
return false;
}
return true;
}
#elif defined(YUZU_UNIX)
pid_t SpawnChild(const char* arg0) {
const pid_t pid = fork();
if (pid == -1) {
// error
const int err = errno;
fmt::print(stderr, "fork failed with error {}\n", err);
return pid;
} else if (pid == 0) {
// child
execl(arg0, arg0, nullptr);
const int err = errno;
fmt::print(stderr, "execl failed with error {}\n", err);
_exit(0);
}
return pid;
}
#endif

View File

@@ -5,6 +5,8 @@
#ifdef _WIN32
#include <windows.h>
#elif defined(YUZU_UNIX)
#include <sys/types.h>
#endif
constexpr char IS_CHILD_ENV_VAR[] = "YUZU_IS_CHILD";
@@ -17,4 +19,6 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka
#ifdef _WIN32
bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags);
#elif defined(YUZU_UNIX)
pid_t SpawnChild(const char* arg0);
#endif