diff options
45 files changed, 496 insertions, 181 deletions
diff --git a/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp b/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp index 7f1ed0450..05cf3975d 100644 --- a/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp +++ b/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp @@ -12,7 +12,7 @@ bool IsValidChannelCount(u32 channel_count) { } bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { - return total_stream_count > 0 && stereo_stream_count > 0 && + return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 && stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count); } } // namespace diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp index c6fd45f47..b7fed5304 100644 --- a/src/audio_core/opus/decoder.cpp +++ b/src/audio_core/opus/decoder.cpp @@ -148,7 +148,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; OpusPacketHeader header{ReverseHeader(*header_p)}; - LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", + LOG_TRACE(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", header.size, input_data.size_bytes(), in_data.size_bytes()); R_UNLESS(in_data.size_bytes() >= header.size && diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3aa2e4340..597890655 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -523,6 +523,8 @@ add_library(core STATIC hle/service/hid/hid.h hle/service/hid/hid_debug_server.cpp hle/service/hid/hid_debug_server.h + hle/service/hid/hid_firmware_settings.cpp + hle/service/hid/hid_firmware_settings.h hle/service/hid/hid_server.cpp hle/service/hid/hid_server.h hle/service/hid/hid_system_server.cpp @@ -723,6 +725,7 @@ add_library(core STATIC hle/service/nvnflinger/producer_listener.h hle/service/nvnflinger/status.h hle/service/nvnflinger/ui/fence.h + hle/service/nvnflinger/ui/graphic_buffer.cpp hle/service/nvnflinger/ui/graphic_buffer.h hle/service/nvnflinger/window.h hle/service/olsc/olsc.cpp diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index c58d67d7d..0bcd87062 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -8,12 +8,17 @@ namespace Service::HID { ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} ControllerBase::~ControllerBase() = default; -void ControllerBase::ActivateController() { +Result ControllerBase::Activate() { if (is_activated) { - return; + return ResultSuccess; } is_activated = true; OnInit(); + return ResultSuccess; +} + +Result ControllerBase::Activate(u64 aruid) { + return Activate(); } void ControllerBase::DeactivateController() { diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index d6f7a5073..9a44ee41e 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -4,6 +4,7 @@ #pragma once #include "common/common_types.h" +#include "core/hle/result.h" namespace Core::Timing { class CoreTiming; @@ -31,7 +32,8 @@ public: // When the controller is requesting a motion update for the shared memory virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} - void ActivateController(); + Result Activate(); + Result Activate(u64 aruid); void DeactivateController(); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 949e58a4c..e23b4986c 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -86,6 +86,13 @@ public: Default = 3, }; + enum class NpadRevision : u32 { + Revision0 = 0, + Revision1 = 1, + Revision2 = 2, + Revision3 = 3, + }; + void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); Core::HID::NpadStyleTag GetSupportedStyleSet() const; diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp index 73a2a2b91..51a18335f 100644 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -44,7 +44,7 @@ Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) { if (handle.npad_id != active_handle.npad_id) { return InvalidPalmaHandle; } - ActivateController(); + Activate(); return ResultSuccess; } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 801a4d08f..1b7381d8d 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -3,6 +3,7 @@ #include "core/hle/service/hid/hid.h" #include "core/hle/service/hid/hid_debug_server.h" +#include "core/hle/service/hid/hid_firmware_settings.h" #include "core/hle/service/hid/hid_server.h" #include "core/hle/service/hid/hid_system_server.h" #include "core/hle/service/hid/hidbus.h" @@ -16,9 +17,11 @@ namespace Service::HID { void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system); + std::shared_ptr<HidFirmwareSettings> firmware_settings = + std::make_shared<HidFirmwareSettings>(); - server_manager->RegisterNamedService("hid", - std::make_shared<IHidServer>(system, resouce_manager)); + server_manager->RegisterNamedService( + "hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings)); server_manager->RegisterNamedService( "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager)); server_manager->RegisterNamedService( diff --git a/src/core/hle/service/hid/hid_firmware_settings.cpp b/src/core/hle/service/hid/hid_firmware_settings.cpp new file mode 100644 index 000000000..59bd6825c --- /dev/null +++ b/src/core/hle/service/hid/hid_firmware_settings.cpp @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/hid_firmware_settings.h" + +namespace Service::HID { + +HidFirmwareSettings::HidFirmwareSettings() { + LoadSettings(true); +} + +void HidFirmwareSettings::Reload() { + LoadSettings(true); +} + +void HidFirmwareSettings::LoadSettings(bool reload_config) { + if (is_initalized && !reload_config) { + return; + } + + // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values + + is_debug_pad_enabled = true; + is_device_managed = true; + is_touch_i2c_managed = is_device_managed; + is_future_devices_emulated = false; + is_mcu_hardware_error_emulated = false; + is_rail_enabled = true; + is_firmware_update_failure_emulated = false; + is_firmware_update_failure = {}; + is_ble_disabled = false; + is_dscale_disabled = false; + is_handheld_forced = true; + features_per_id_disabled = {}; + is_touch_firmware_auto_update_disabled = false; + is_initalized = true; +} + +bool HidFirmwareSettings::IsDebugPadEnabled() { + LoadSettings(false); + return is_debug_pad_enabled; +} + +bool HidFirmwareSettings::IsDeviceManaged() { + LoadSettings(false); + return is_device_managed; +} + +bool HidFirmwareSettings::IsEmulateFutureDevice() { + LoadSettings(false); + return is_future_devices_emulated; +} + +bool HidFirmwareSettings::IsTouchI2cManaged() { + LoadSettings(false); + return is_touch_i2c_managed; +} + +bool HidFirmwareSettings::IsHandheldForced() { + LoadSettings(false); + return is_handheld_forced; +} + +bool HidFirmwareSettings::IsRailEnabled() { + LoadSettings(false); + return is_rail_enabled; +} + +bool HidFirmwareSettings::IsHardwareErrorEmulated() { + LoadSettings(false); + return is_mcu_hardware_error_emulated; +} + +bool HidFirmwareSettings::IsBleDisabled() { + LoadSettings(false); + return is_ble_disabled; +} + +bool HidFirmwareSettings::IsDscaleDisabled() { + LoadSettings(false); + return is_dscale_disabled; +} + +bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() { + LoadSettings(false); + return is_touch_firmware_auto_update_disabled; +} + +HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() { + LoadSettings(false); + return is_firmware_update_failure; +} + +HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() { + LoadSettings(false); + return features_per_id_disabled; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/hid_firmware_settings.h b/src/core/hle/service/hid/hid_firmware_settings.h new file mode 100644 index 000000000..6c10c440b --- /dev/null +++ b/src/core/hle/service/hid/hid_firmware_settings.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Service::HID { + +/// Loads firmware config from nn::settings::fwdbg +class HidFirmwareSettings { +public: + using FirmwareSetting = std::array<u8, 4>; + using FeaturesPerId = std::array<bool, 0xA8>; + + HidFirmwareSettings(); + + void Reload(); + void LoadSettings(bool reload_config); + + bool IsDebugPadEnabled(); + bool IsDeviceManaged(); + bool IsEmulateFutureDevice(); + bool IsTouchI2cManaged(); + bool IsHandheldForced(); + bool IsRailEnabled(); + bool IsHardwareErrorEmulated(); + bool IsBleDisabled(); + bool IsDscaleDisabled(); + bool IsTouchAutoUpdateDisabled(); + + FirmwareSetting GetFirmwareUpdateFailure(); + FeaturesPerId FeaturesDisabledPerId(); + +private: + bool is_initalized{}; + + // Debug settings + bool is_debug_pad_enabled{}; + bool is_device_managed{}; + bool is_touch_i2c_managed{}; + bool is_future_devices_emulated{}; + bool is_mcu_hardware_error_emulated{}; + bool is_rail_enabled{}; + bool is_firmware_update_failure_emulated{}; + bool is_ble_disabled{}; + bool is_dscale_disabled{}; + bool is_handheld_forced{}; + bool is_touch_firmware_auto_update_disabled{}; + FirmwareSetting is_firmware_update_failure{}; + FeaturesPerId features_per_id_disabled{}; +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 2fb31cf47..0be6a7186 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -10,6 +10,7 @@ #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/kernel.h" #include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_firmware_settings.h" #include "core/hle/service/hid/hid_server.h" #include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/ipc_helpers.h" @@ -64,8 +65,9 @@ private: std::shared_ptr<ResourceManager> resource_manager; }; -IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource) - : ServiceFramework{system_, "hid"}, resource_manager{resource} { +IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, + std::shared_ptr<HidFirmwareSettings> settings) + : ServiceFramework{system_, "hid"}, resource_manager{resource}, firmware_settings{settings} { // clang-format off static const FunctionInfo functions[] = { {0, &IHidServer::CreateAppletResource, "CreateAppletResource"}, @@ -230,48 +232,87 @@ void IHidServer::ActivateDebugPad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::DebugPad); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto& debug_pad = + GetResourceManager()->GetController<Controller_DebugPad>(HidController::DebugPad); + + if (!firmware_settings->IsDeviceManaged()) { + result = debug_pad.Activate(); + } + + if (result.IsSuccess()) { + result = debug_pad.Activate(applet_resource_user_id); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::Touchscreen); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto& touch_screen = + GetResourceManager()->GetController<Controller_Touchscreen>(HidController::Touchscreen); + + if (!firmware_settings->IsDeviceManaged()) { + result = touch_screen.Activate(); + } + + if (result.IsSuccess()) { + result = touch_screen.Activate(applet_resource_user_id); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::ActivateMouse(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::Mouse); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto& mouse = GetResourceManager()->GetController<Controller_Mouse>(HidController::Mouse); + + if (!firmware_settings->IsDeviceManaged()) { + result = mouse.Activate(); + } + + if (result.IsSuccess()) { + result = mouse.Activate(applet_resource_user_id); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::ActivateKeyboard(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::Keyboard); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto& keyboard = + GetResourceManager()->GetController<Controller_Keyboard>(HidController::Keyboard); + + if (!firmware_settings->IsDeviceManaged()) { + result = keyboard.Activate(); + } + + if (result.IsSuccess()) { + result = keyboard.Activate(applet_resource_user_id); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::SendKeyboardLockKeyEvent(HLERequestContext& ctx) { @@ -898,7 +939,7 @@ void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) void IHidServer::ActivateGesture(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 unknown; + u32 basic_gesture_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; @@ -906,13 +947,23 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - GetResourceManager()->ActivateController(HidController::Gesture); + LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}", + parameters.basic_gesture_id, parameters.applet_resource_user_id); - LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}", - parameters.unknown, parameters.applet_resource_user_id); + Result result = ResultSuccess; + auto& gesture = GetResourceManager()->GetController<Controller_Gesture>(HidController::Gesture); + + if (!firmware_settings->IsDeviceManaged()) { + result = gesture.Activate(); + } + + if (result.IsSuccess()) { + // TODO: Use gesture id here + result = gesture.Activate(parameters.applet_resource_user_id); + } IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) { @@ -969,22 +1020,25 @@ void IHidServer::ActivateNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::NPad); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); + + // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0); + const Result result = npad.Activate(applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::DeactivateNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->DeactivateController(HidController::NPad); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + // This function does nothing since 10.0.0+ + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1053,10 +1107,9 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { } void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { - // Should have no effect with how our npad sets up the data IPC::RequestParser rp{ctx}; struct Parameters { - s32 revision; + Controller_NPad::NpadRevision revision; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; @@ -1064,13 +1117,16 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - GetResourceManager()->ActivateController(HidController::NPad); - LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision, parameters.applet_resource_user_id); + auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); + + // TODO: npad->SetRevision(applet_resource_user_id, revision); + const auto result = npad.Activate(parameters.applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { @@ -1718,12 +1774,22 @@ void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::ConsoleSixAxisSensor); + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( + HidController::ConsoleSixAxisSensor); + + if (!firmware_settings->IsDeviceManaged()) { + result = console_sixaxis.Activate(); + } + + if (result.IsSuccess()) { + result = console_sixaxis.Activate(applet_resource_user_id); + } IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::StartConsoleSixAxisSensor(HLERequestContext& ctx) { @@ -1770,9 +1836,19 @@ void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->ActivateController(HidController::ConsoleSixAxisSensor); + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( + HidController::ConsoleSixAxisSensor); + + if (!firmware_settings->IsDeviceManaged()) { + result = console_sixaxis.Activate(); + } + + if (result.IsSuccess()) { + console_sixaxis.Activate(applet_resource_user_id); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1837,7 +1913,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) { // Activate console six axis controller GetResourceManager() ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) - .ActivateController(); + .Activate(); GetResourceManager() ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index 98353b0db..eb2e8e7f4 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h @@ -11,10 +11,12 @@ class System; namespace Service::HID { class ResourceManager; +class HidFirmwareSettings; class IHidServer final : public ServiceFramework<IHidServer> { public: - explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource); + explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, + std::shared_ptr<HidFirmwareSettings> settings); ~IHidServer() override; std::shared_ptr<ResourceManager> GetResourceManager(); @@ -141,6 +143,7 @@ private: void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx); std::shared_ptr<ResourceManager> resource_manager; + std::shared_ptr<HidFirmwareSettings> firmware_settings; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp index 4e462f3b3..d6f42c646 100644 --- a/src/core/hle/service/hid/resource_manager.cpp +++ b/src/core/hle/service/hid/resource_manager.cpp @@ -59,8 +59,8 @@ void ResourceManager::Initialize() { MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory); // Homebrew doesn't try to activate some controllers, so we activate them by default - GetController<Controller_NPad>(HidController::NPad).ActivateController(); - GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController(); + GetController<Controller_NPad>(HidController::NPad).Activate(); + GetController<Controller_Touchscreen>(HidController::Touchscreen).Activate(); GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00); GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00); @@ -73,14 +73,6 @@ void ResourceManager::Initialize() { is_initialized = true; } -void ResourceManager::ActivateController(HidController controller) { - controllers[static_cast<size_t>(controller)]->ActivateController(); -} - -void ResourceManager::DeactivateController(HidController controller) { - controllers[static_cast<size_t>(controller)]->DeactivateController(); -} - void ResourceManager::UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h index 81b17f9a9..34dbf36bc 100644 --- a/src/core/hle/service/hid/resource_manager.h +++ b/src/core/hle/service/hid/resource_manager.h @@ -55,8 +55,6 @@ public: } void Initialize(); - void ActivateController(HidController controller); - void DeactivateController(HidController controller); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); diff --git a/src/core/hle/service/nvnflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h index 3da8cc3aa..7fd808f54 100644 --- a/src/core/hle/service/nvnflinger/buffer_item.h +++ b/src/core/hle/service/nvnflinger/buffer_item.h @@ -15,7 +15,7 @@ namespace Service::android { -struct GraphicBuffer; +class GraphicBuffer; class BufferItem final { public: diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index 51291539d..d91886bed 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -5,7 +5,6 @@ // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp #include "common/logging/log.h" -#include "core/hle/service/nvdrv/core/nvmap.h" #include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" @@ -14,9 +13,8 @@ namespace Service::android { -BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, - Service::Nvidia::NvCore::NvMap& nvmap_) - : core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {} +BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_) + : core{std::move(core_)}, slots{core->slots} {} BufferQueueConsumer::~BufferQueueConsumer() = default; @@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc slots[slot].buffer_state = BufferState::Free; - nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true); - listener = core->connected_producer_listener; LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); @@ -175,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_ return Status::NoError; } +Status BufferQueueConsumer::Disconnect() { + LOG_DEBUG(Service_Nvnflinger, "called"); + + std::scoped_lock lock{core->mutex}; + + if (core->consumer_listener == nullptr) { + LOG_ERROR(Service_Nvnflinger, "no consumer is connected"); + return Status::BadValue; + } + + core->is_abandoned = true; + core->consumer_listener = nullptr; + core->queue.clear(); + core->FreeAllBuffersLocked(); + core->SignalDequeueCondition(); + + return Status::NoError; +} + Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { if (out_slot_mask == nullptr) { LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr"); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 50ed0bb5f..0a61e8dbd 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h @@ -13,10 +13,6 @@ #include "core/hle/service/nvnflinger/buffer_queue_defs.h" #include "core/hle/service/nvnflinger/status.h" -namespace Service::Nvidia::NvCore { -class NvMap; -} // namespace Service::Nvidia::NvCore - namespace Service::android { class BufferItem; @@ -25,19 +21,18 @@ class IConsumerListener; class BufferQueueConsumer final { public: - explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, - Service::Nvidia::NvCore::NvMap& nvmap_); + explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); ~BufferQueueConsumer(); Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); + Status Disconnect(); Status GetReleasedBuffers(u64* out_slot_mask); private: std::shared_ptr<BufferQueueCore> core; BufferQueueDefs::SlotsType& slots; - Service::Nvidia::NvCore::NvMap& nvmap; }; } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp index ed66f6f5b..4ed5e5978 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp @@ -14,24 +14,12 @@ BufferQueueCore::BufferQueueCore() = default; BufferQueueCore::~BufferQueueCore() = default; -void BufferQueueCore::NotifyShutdown() { - std::scoped_lock lock{mutex}; - - is_shutting_down = true; - - SignalDequeueCondition(); -} - void BufferQueueCore::SignalDequeueCondition() { dequeue_possible.store(true); dequeue_condition.notify_all(); } bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { - if (is_shutting_down) { - return false; - } - dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); dequeue_possible.store(false); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index 9164f08a0..e513d183b 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -34,8 +34,6 @@ public: BufferQueueCore(); ~BufferQueueCore(); - void NotifyShutdown(); - private: void SignalDequeueCondition(); bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); @@ -74,7 +72,6 @@ private: u32 transform_hint{}; bool is_allocating{}; mutable std::condition_variable_any is_allocating_condition; - bool is_shutting_down{}; }; } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 6e7a49658..5d8762d25 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -13,7 +13,6 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/service/hle_ipc.h" #include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvdrv/core/nvmap.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h" #include "core/hle/service/nvnflinger/consumer_listener.h" @@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, item.is_droppable = core->dequeue_buffer_cannot_block || async; item.swap_interval = swap_interval; - nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true); - sticky_transform = sticky_transform_; if (core->queue.empty()) { @@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { return Status::NoError; } - // HACK: We are not Android. Remove handle for items in queue, and clear queue. - // Allows synchronous destruction of nvmap handles. - for (auto& item : core->queue) { - nvmap.FreeHandle(item.graphic_buffer->BufferId(), true); - } - core->queue.clear(); - switch (api) { case NativeWindowApi::Egl: case NativeWindowApi::Cpu: case NativeWindowApi::Media: case NativeWindowApi::Camera: if (core->connected_api == api) { + core->queue.clear(); core->FreeAllBuffersLocked(); core->connected_producer_listener = nullptr; core->connected_api = NativeWindowApi::NoConnectedApi; @@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { } Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, - const std::shared_ptr<GraphicBuffer>& buffer) { + const std::shared_ptr<NvGraphicBuffer>& buffer) { LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { @@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, slots[slot] = {}; slots[slot].fence = Fence::NoFence(); - slots[slot].graphic_buffer = buffer; + slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer); slots[slot].frame_number = 0; // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for @@ -839,7 +830,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u } case TransactionId::SetPreallocatedBuffer: { const auto slot = parcel_in.Read<s32>(); - const auto buffer = parcel_in.ReadObject<GraphicBuffer>(); + const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>(); status = SetPreallocatedBuffer(slot, buffer); break; @@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u status = RequestBuffer(slot, &buf); - parcel_out.WriteFlattenedObject(buf); + parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get()); break; } case TransactionId::QueueBuffer: { diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index d4201c104..64c17d56c 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -38,6 +38,7 @@ namespace Service::android { class BufferQueueCore; class IProducerListener; +struct NvGraphicBuffer; class BufferQueueProducer final : public IBinder { public: @@ -65,7 +66,7 @@ public: bool producer_controlled_by_app, QueueBufferOutput* output); Status Disconnect(NativeWindowApi api); - Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer); + Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer); private: BufferQueueProducer(const BufferQueueProducer&) = delete; diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index d8c9dec3b..d25bca049 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h @@ -13,7 +13,7 @@ namespace Service::android { -struct GraphicBuffer; +class GraphicBuffer; enum class BufferState : u32 { Free = 0, diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 4dcda8dac..1059e72bf 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.cpp +++ b/src/core/hle/service/nvnflinger/consumer_base.cpp @@ -27,6 +27,26 @@ void ConsumerBase::Connect(bool controlled_by_app) { consumer->Connect(shared_from_this(), controlled_by_app); } +void ConsumerBase::Abandon() { + LOG_DEBUG(Service_Nvnflinger, "called"); + + std::scoped_lock lock{mutex}; + + if (!is_abandoned) { + this->AbandonLocked(); + is_abandoned = true; + } +} + +void ConsumerBase::AbandonLocked() { + for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) { + this->FreeBufferLocked(i); + } + // disconnect from the BufferQueue + consumer->Disconnect(); + consumer = nullptr; +} + void ConsumerBase::FreeBufferLocked(s32 slot_index) { LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h index 264829414..ea3e9e97a 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.h +++ b/src/core/hle/service/nvnflinger/consumer_base.h @@ -24,6 +24,7 @@ class BufferQueueConsumer; class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> { public: void Connect(bool controlled_by_app); + void Abandon(); protected: explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); @@ -34,6 +35,7 @@ protected: void OnBuffersReleased() override; void OnSidebandStreamChanged() override; + void AbandonLocked(); void FreeBufferLocked(s32 slot_index); Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp index 6dc327b8b..d7db24f42 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp @@ -166,7 +166,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { }(); void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { - auto buffer = std::make_shared<android::GraphicBuffer>(); + auto buffer = std::make_shared<android::NvGraphicBuffer>(); buffer->width = SharedBufferWidth; buffer->height = SharedBufferHeight; buffer->stride = SharedBufferBlockLinearStride; diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index bebb45eae..0745434c5 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -47,7 +47,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) { vsync_signal.Wait(); const auto lock_guard = Lock(); - Compose(); + + if (!is_abandoned) { + Compose(); + } } } @@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() { } ShutdownLayers(); - vsync_thread = {}; if (nvdrv) { nvdrv->Close(disp_fd); @@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() { } void Nvnflinger::ShutdownLayers() { - const auto lock_guard = Lock(); - for (auto& display : displays) { - for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { - display.GetLayer(layer).Core().NotifyShutdown(); + // Abandon consumers. + { + const auto lock_guard = Lock(); + for (auto& display : displays) { + for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { + display.GetLayer(layer).GetConsumer().Abandon(); + } } + + is_abandoned = true; } + + // Join the vsync thread, if it exists. + vsync_thread = {}; } void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 959d8b46b..f5d73acdb 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -140,6 +140,8 @@ private: s32 swap_interval = 1; + bool is_abandoned = false; + /// Event that handles screen composition. std::shared_ptr<Core::Timing::EventType> multi_composition_event; std::shared_ptr<Core::Timing::EventType> single_composition_event; diff --git a/src/core/hle/service/nvnflinger/status.h b/src/core/hle/service/nvnflinger/status.h index 7af166c40..3fa0fe15b 100644 --- a/src/core/hle/service/nvnflinger/status.h +++ b/src/core/hle/service/nvnflinger/status.h @@ -19,7 +19,7 @@ enum class Status : s32 { Busy = -16, NoInit = -19, BadValue = -22, - InvalidOperation = -37, + InvalidOperation = -38, BufferNeedsReallocation = 1, ReleaseAllBuffers = 2, }; diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp new file mode 100644 index 000000000..ce70946ec --- /dev/null +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/nvdrv/core/nvmap.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" + +namespace Service::android { + +static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) { + if (buffer) { + return *buffer; + } else { + return {}; + } +} + +GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) + : NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {} + +GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap, + std::shared_ptr<NvGraphicBuffer> buffer) + : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) { + if (this->BufferId() > 0) { + m_nvmap->DuplicateHandle(this->BufferId(), true); + } +} + +GraphicBuffer::~GraphicBuffer() { + if (m_nvmap != nullptr && this->BufferId() > 0) { + m_nvmap->FreeHandle(this->BufferId(), true); + } +} + +} // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h index 3eac5cedd..da430aa75 100644 --- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h @@ -6,16 +6,22 @@ #pragma once +#include <memory> + #include "common/common_funcs.h" #include "common/common_types.h" #include "core/hle/service/nvnflinger/pixel_format.h" +namespace Service::Nvidia::NvCore { +class NvMap; +} // namespace Service::Nvidia::NvCore + namespace Service::android { -struct GraphicBuffer final { - constexpr GraphicBuffer() = default; +struct NvGraphicBuffer { + constexpr NvGraphicBuffer() = default; - constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) + constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, usage{static_cast<s32>(usage_)} {} @@ -93,6 +99,17 @@ struct GraphicBuffer final { u32 offset{}; INSERT_PADDING_WORDS(60); }; -static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); +static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size"); + +class GraphicBuffer final : public NvGraphicBuffer { +public: + explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage); + explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap, + std::shared_ptr<NvGraphicBuffer> buffer); + ~GraphicBuffer(); + +private: + Service::Nvidia::NvCore::NvMap* m_nvmap{}; +}; } // namespace Service::android diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index f0b5eff8a..d30f49877 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -35,7 +35,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont return { buffer_queue_core, std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), - std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)}; + std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; } Display::Display(u64 id, std::string name_, diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index d0e308124..64e7bad75 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -559,12 +559,12 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& offset, const IR::Value& lod_clamp) { const auto info{inst.Flags<IR::TextureInstInfo>()}; ScopedRegister dpdx, dpdy, coords; - const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; + const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp}; if (multi_component) { // Allocate this early to avoid aliasing other registers dpdx = ScopedRegister{ctx.reg_alloc}; dpdy = ScopedRegister{ctx.reg_alloc}; - if (info.num_derivates >= 3) { + if (info.num_derivatives >= 3) { coords = ScopedRegister{ctx.reg_alloc}; } } @@ -584,7 +584,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec, dpdy.reg, derivatives_vec); Register final_coord; - if (info.num_derivates >= 3) { + if (info.num_derivatives >= 3) { ctx.Add("MOV.F {}.z,{}.x;" "MOV.F {}.z,{}.y;", dpdx.reg, coord_vec, dpdy.reg, coord_vec); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index d9872ecc2..6e940bd5a 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp @@ -548,15 +548,15 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, if (sparse_inst) { throw NotImplementedException("EmitImageGradient Sparse"); } - if (!offset.IsEmpty() && info.num_derivates <= 2) { + if (!offset.IsEmpty() && info.num_derivatives <= 2) { throw NotImplementedException("EmitImageGradient offset"); } const auto texture{Texture(ctx, info, index)}; const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; - const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; + const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp}; const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)}; if (multi_component) { - if (info.num_derivates >= 3) { + if (info.num_derivatives >= 3) { const auto offset_vec{ctx.var_alloc.Consume(offset)}; ctx.Add("{}=textureGrad({},{},vec3({}.xz, {}.x),vec3({}.yw, {}.y));", texel, texture, coords, derivatives_vec, offset_vec, derivatives_vec, offset_vec); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 8decdf399..22ceca19c 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -67,22 +67,22 @@ public: } } - explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates, u32 num_derivates, - Id offset, Id lod_clamp) { - if (!Sirit::ValidId(derivates)) { - throw LogicError("Derivates must be present"); + explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, + u32 num_derivatives, Id offset, Id lod_clamp) { + if (!Sirit::ValidId(derivatives)) { + throw LogicError("Derivatives must be present"); } boost::container::static_vector<Id, 3> deriv_x_accum; boost::container::static_vector<Id, 3> deriv_y_accum; - for (u32 i = 0; i < num_derivates; ++i) { - deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2)); - deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2 + 1)); + for (u32 i = 0; i < num_derivatives; ++i) { + deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2)); + deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2 + 1)); } - const Id derivates_X{ctx.OpCompositeConstruct( - ctx.F32[num_derivates], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; - const Id derivates_Y{ctx.OpCompositeConstruct( - ctx.F32[num_derivates], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; - Add(spv::ImageOperandsMask::Grad, derivates_X, derivates_Y); + const Id derivatives_X{ctx.OpCompositeConstruct( + ctx.F32[num_derivatives], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; + const Id derivatives_Y{ctx.OpCompositeConstruct( + ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; + Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); if (Sirit::ValidId(offset)) { Add(spv::ImageOperandsMask::Offset, offset); } @@ -91,26 +91,26 @@ public: } } - explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates_1, Id derivates_2, + explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, Id offset, Id lod_clamp) { - if (!Sirit::ValidId(derivates_1) || !Sirit::ValidId(derivates_2)) { - throw LogicError("Derivates must be present"); + if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { + throw LogicError("Derivatives must be present"); } boost::container::static_vector<Id, 3> deriv_1_accum{ - ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 0), - ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 2), - ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 0), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 0), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 2), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 0), }; boost::container::static_vector<Id, 3> deriv_2_accum{ - ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 1), - ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 3), - ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 1), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 1), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 3), + ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 1), }; - const Id derivates_id1{ctx.OpCompositeConstruct( + const Id derivatives_id1{ctx.OpCompositeConstruct( ctx.F32[3], std::span{deriv_1_accum.data(), deriv_1_accum.size()})}; - const Id derivates_id2{ctx.OpCompositeConstruct( + const Id derivatives_id2{ctx.OpCompositeConstruct( ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; - Add(spv::ImageOperandsMask::Grad, derivates_id1, derivates_id2); + Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); if (Sirit::ValidId(offset)) { Add(spv::ImageOperandsMask::Offset, offset); } @@ -548,12 +548,12 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I } Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivates, Id offset, Id lod_clamp) { + Id derivatives, Id offset, Id lod_clamp) { const auto info{inst->Flags<IR::TextureInstInfo>()}; const auto operands = - info.num_derivates == 3 - ? ImageOperands(ctx, info.has_lod_clamp != 0, derivates, offset, {}, lod_clamp) - : ImageOperands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, offset, + info.num_derivatives == 3 + ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp) + : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, lod_clamp); return Emit(&EmitContext::OpImageSparseSampleExplicitLod, &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index a440b557d..7d34575c8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i const IR::Value& skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivates, Id offset, Id lod_clamp); + Id derivatives, Id offset, Id lod_clamp); Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index b7caa4246..49171c470 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -1864,11 +1864,11 @@ Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, Texture return Inst(op, Flags{info}, handle, coords); } -Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivates, +Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivatives, const Value& offset, const F32& lod_clamp, TextureInstInfo info) { const Opcode op{handle.IsImmediate() ? Opcode::BoundImageGradient : Opcode::BindlessImageGradient}; - return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp); + return Inst(op, Flags{info}, handle, coords, derivatives, offset, lod_clamp); } Value IREmitter::ImageRead(const Value& handle, const Value& coords, TextureInstInfo info) { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index f3c81dbe1..6c30897f4 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -335,7 +335,7 @@ public: [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, const U32& lod, const U32& multisampling, TextureInstInfo info); [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, - const Value& derivates, const Value& offset, + const Value& derivatives, const Value& offset, const F32& lod_clamp, TextureInstInfo info); [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); void ImageWrite(const Value& handle, const Value& coords, const Value& color, diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h index 1e9e8c8f5..c20c2401f 100644 --- a/src/shader_recompiler/frontend/ir/modifiers.h +++ b/src/shader_recompiler/frontend/ir/modifiers.h @@ -40,7 +40,7 @@ union TextureInstInfo { BitField<21, 1, u32> has_lod_clamp; BitField<22, 1, u32> relaxed_precision; BitField<23, 2, u32> gather_component; - BitField<25, 2, u32> num_derivates; + BitField<25, 2, u32> num_derivatives; BitField<27, 3, ImageFormat> image_format; BitField<30, 1, u32> ndv_is_active; }; diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp index dd34507bc..4ce3dd0cd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp @@ -59,7 +59,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { BitField<51, 3, IR::Pred> sparse_pred; BitField<0, 8, IR::Reg> dest_reg; BitField<8, 8, IR::Reg> coord_reg; - BitField<20, 8, IR::Reg> derivate_reg; + BitField<20, 8, IR::Reg> derivative_reg; BitField<28, 3, TextureType> type; BitField<31, 4, u64> mask; BitField<36, 13, u64> cbuf_offset; @@ -71,7 +71,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { } IR::Value coords; - u32 num_derivates{}; + u32 num_derivatives{}; IR::Reg base_reg{txd.coord_reg}; IR::Reg last_reg; IR::Value handle; @@ -90,42 +90,42 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { switch (txd.type) { case TextureType::_1D: { coords = v.F(base_reg); - num_derivates = 1; + num_derivatives = 1; last_reg = base_reg + 1; break; } case TextureType::ARRAY_1D: { last_reg = base_reg + 1; coords = v.ir.CompositeConstruct(v.F(base_reg), read_array()); - num_derivates = 1; + num_derivatives = 1; break; } case TextureType::_2D: { last_reg = base_reg + 2; coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1)); - num_derivates = 2; + num_derivatives = 2; break; } case TextureType::ARRAY_2D: { last_reg = base_reg + 2; coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1), read_array()); - num_derivates = 2; + num_derivatives = 2; break; } default: throw NotImplementedException("Invalid texture type"); } - const IR::Reg derivate_reg{txd.derivate_reg}; - IR::Value derivates; - switch (num_derivates) { + const IR::Reg derivative_reg{txd.derivative_reg}; + IR::Value derivatives; + switch (num_derivatives) { case 1: { - derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1)); + derivatives = v.ir.CompositeConstruct(v.F(derivative_reg), v.F(derivative_reg + 1)); break; } case 2: { - derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1), - v.F(derivate_reg + 2), v.F(derivate_reg + 3)); + derivatives = v.ir.CompositeConstruct(v.F(derivative_reg), v.F(derivative_reg + 1), + v.F(derivative_reg + 2), v.F(derivative_reg + 3)); break; } default: @@ -150,9 +150,10 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { IR::TextureInstInfo info{}; info.type.Assign(GetType(txd.type)); - info.num_derivates.Assign(num_derivates); + info.num_derivatives.Assign(num_derivatives); info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); - const IR::Value sample{v.ir.ImageGradient(handle, coords, derivates, offset, lod_clamp, info)}; + const IR::Value sample{ + v.ir.ImageGradient(handle, coords, derivatives, offset, lod_clamp, info)}; IR::Reg dest_reg{txd.dest_reg}; for (size_t element = 0; element < 4; ++element) { diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index f46e55122..ec12c843a 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -428,7 +428,7 @@ void FoldFPAdd32(IR::Inst& inst) { } } -bool FoldDerivateYFromCorrection(IR::Inst& inst) { +bool FoldDerivativeYFromCorrection(IR::Inst& inst) { const IR::Value lhs_value{inst.Arg(0)}; const IR::Value rhs_value{inst.Arg(1)}; IR::Inst* const lhs_op{lhs_value.InstRecursive()}; @@ -464,7 +464,7 @@ void FoldFPMul32(IR::Inst& inst) { if (lhs_value.IsImmediate() || rhs_value.IsImmediate()) { return; } - if (FoldDerivateYFromCorrection(inst)) { + if (FoldDerivativeYFromCorrection(inst)) { return; } IR::Inst* const lhs_op{lhs_value.InstRecursive()}; @@ -699,7 +699,7 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) { } } -bool FindGradient3DDerivates(std::array<IR::Value, 3>& results, IR::Value coord) { +bool FindGradient3DDerivatives(std::array<IR::Value, 3>& results, IR::Value coord) { if (coord.IsImmediate()) { return false; } @@ -834,7 +834,7 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { IR::Inst* const inst2 = coords.InstRecursive(); std::array<std::array<IR::Value, 3>, 3> results_matrix; for (size_t i = 0; i < 3; i++) { - if (!FindGradient3DDerivates(results_matrix[i], inst2->Arg(i).Resolve())) { + if (!FindGradient3DDerivatives(results_matrix[i], inst2->Arg(i).Resolve())) { return; } } @@ -852,7 +852,7 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2], results_matrix[1][1], results_matrix[1][2]); IR::Value derivatives_2 = ir.CompositeConstruct(results_matrix[2][1], results_matrix[2][2]); - info.num_derivates.Assign(3); + info.num_derivatives.Assign(3); IR::Value new_gradient_instruction = ir.ImageGradient(handle, new_coords, derivatives_1, derivatives_2, lod_clamp, info); IR::Inst* const new_inst = new_gradient_instruction.InstRecursive(); diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 081a574e8..f5b10411b 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1192,11 +1192,6 @@ void BufferCache<P>::UpdateDrawIndirect() { .size = static_cast<u32>(size), .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), }; - VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64); - VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64); - IntervalType interval{cpu_addr_start, cpu_addr_end}; - ClearDownload(interval); - common_ranges.subtract(interval); }; if (current_draw_indirect->include_count) { update(current_draw_indirect->count_start_address, sizeof(u32), diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 02e161270..91f10aec2 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -72,7 +72,7 @@ void Fermi2D::Blit() { UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); const auto& args = regs.pixels_from_memory; - constexpr s64 null_derivate = 1ULL << 32; + constexpr s64 null_derivative = 1ULL << 32; Surface src = regs.src; const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format)); const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 && @@ -89,7 +89,7 @@ void Fermi2D::Blit() { .operation = regs.operation, .filter = args.sample_mode.filter, .must_accelerate = - args.du_dx != null_derivate || args.dv_dy != null_derivate || delegate_to_gpu, + args.du_dx != null_derivative || args.dv_dy != null_derivative || delegate_to_gpu, .dst_x0 = args.dst_x0, .dst_y0 = args.dst_y0, .dst_x1 = args.dst_x0 + args.dst_width, diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 32d767d85..592c28ba3 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -268,7 +268,7 @@ size_t Maxwell3D::EstimateIndexBufferSize() { std::numeric_limits<u32>::max()}; const size_t byte_size = regs.index_buffer.FormatSizeInBytes(); const size_t log2_byte_size = Common::Log2Ceil64(byte_size); - const size_t cap{GetMaxCurrentVertices() * 3 * byte_size}; + const size_t cap{GetMaxCurrentVertices() * 4 * byte_size}; const size_t lower_cap = std::min<size_t>(static_cast<size_t>(end_address - start_address), cap); return std::min<size_t>( diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 44a771d65..af0a453ee 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -559,7 +559,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { - glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), GL_SEPARATE_ATTRIBS); + const GLenum buffer_mode = + num_xfb_buffers_active == 1 ? GL_INTERLEAVED_ATTRIBS : GL_SEPARATE_ATTRIBS; + glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), buffer_mode); } void GraphicsPipeline::GenerateTransformFeedbackState() { @@ -567,12 +569,14 @@ void GraphicsPipeline::GenerateTransformFeedbackState() { // when this is required. GLint* cursor{xfb_attribs.data()}; + num_xfb_buffers_active = 0; for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { const auto& layout = key.xfb_state.layouts[feedback]; UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); if (layout.varying_count == 0) { continue; } + num_xfb_buffers_active++; const auto& locations = key.xfb_state.varyings[feedback]; std::optional<u32> current_index; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 74fc9cc3d..2f70c1ae9 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h @@ -154,6 +154,7 @@ private: static constexpr std::size_t XFB_ENTRY_STRIDE = 3; GLsizei num_xfb_attribs{}; + u32 num_xfb_buffers_active{}; std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{}; std::mutex built_mutex; |