diff options
Diffstat (limited to 'src')
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) { | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { | 14 | bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { |
| 15 | return total_stream_count > 0 && stereo_stream_count > 0 && | 15 | return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 && |
| 16 | stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count); | 16 | stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count); |
| 17 | } | 17 | } |
| 18 | } // namespace | 18 | } // 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 | |||
| 148 | auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; | 148 | auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; |
| 149 | OpusPacketHeader header{ReverseHeader(*header_p)}; | 149 | OpusPacketHeader header{ReverseHeader(*header_p)}; |
| 150 | 150 | ||
| 151 | LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", | 151 | LOG_TRACE(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", |
| 152 | header.size, input_data.size_bytes(), in_data.size_bytes()); | 152 | header.size, input_data.size_bytes(), in_data.size_bytes()); |
| 153 | 153 | ||
| 154 | R_UNLESS(in_data.size_bytes() >= header.size && | 154 | 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 | |||
| 523 | hle/service/hid/hid.h | 523 | hle/service/hid/hid.h |
| 524 | hle/service/hid/hid_debug_server.cpp | 524 | hle/service/hid/hid_debug_server.cpp |
| 525 | hle/service/hid/hid_debug_server.h | 525 | hle/service/hid/hid_debug_server.h |
| 526 | hle/service/hid/hid_firmware_settings.cpp | ||
| 527 | hle/service/hid/hid_firmware_settings.h | ||
| 526 | hle/service/hid/hid_server.cpp | 528 | hle/service/hid/hid_server.cpp |
| 527 | hle/service/hid/hid_server.h | 529 | hle/service/hid/hid_server.h |
| 528 | hle/service/hid/hid_system_server.cpp | 530 | hle/service/hid/hid_system_server.cpp |
| @@ -723,6 +725,7 @@ add_library(core STATIC | |||
| 723 | hle/service/nvnflinger/producer_listener.h | 725 | hle/service/nvnflinger/producer_listener.h |
| 724 | hle/service/nvnflinger/status.h | 726 | hle/service/nvnflinger/status.h |
| 725 | hle/service/nvnflinger/ui/fence.h | 727 | hle/service/nvnflinger/ui/fence.h |
| 728 | hle/service/nvnflinger/ui/graphic_buffer.cpp | ||
| 726 | hle/service/nvnflinger/ui/graphic_buffer.h | 729 | hle/service/nvnflinger/ui/graphic_buffer.h |
| 727 | hle/service/nvnflinger/window.h | 730 | hle/service/nvnflinger/window.h |
| 728 | hle/service/olsc/olsc.cpp | 731 | 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 { | |||
| 8 | ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} | 8 | ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} |
| 9 | ControllerBase::~ControllerBase() = default; | 9 | ControllerBase::~ControllerBase() = default; |
| 10 | 10 | ||
| 11 | void ControllerBase::ActivateController() { | 11 | Result ControllerBase::Activate() { |
| 12 | if (is_activated) { | 12 | if (is_activated) { |
| 13 | return; | 13 | return ResultSuccess; |
| 14 | } | 14 | } |
| 15 | is_activated = true; | 15 | is_activated = true; |
| 16 | OnInit(); | 16 | OnInit(); |
| 17 | return ResultSuccess; | ||
| 18 | } | ||
| 19 | |||
| 20 | Result ControllerBase::Activate(u64 aruid) { | ||
| 21 | return Activate(); | ||
| 17 | } | 22 | } |
| 18 | 23 | ||
| 19 | void ControllerBase::DeactivateController() { | 24 | 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 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "core/hle/result.h" | ||
| 7 | 8 | ||
| 8 | namespace Core::Timing { | 9 | namespace Core::Timing { |
| 9 | class CoreTiming; | 10 | class CoreTiming; |
| @@ -31,7 +32,8 @@ public: | |||
| 31 | // When the controller is requesting a motion update for the shared memory | 32 | // When the controller is requesting a motion update for the shared memory |
| 32 | virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} | 33 | virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} |
| 33 | 34 | ||
| 34 | void ActivateController(); | 35 | Result Activate(); |
| 36 | Result Activate(u64 aruid); | ||
| 35 | 37 | ||
| 36 | void DeactivateController(); | 38 | void DeactivateController(); |
| 37 | 39 | ||
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: | |||
| 86 | Default = 3, | 86 | Default = 3, |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | enum class NpadRevision : u32 { | ||
| 90 | Revision0 = 0, | ||
| 91 | Revision1 = 1, | ||
| 92 | Revision2 = 2, | ||
| 93 | Revision3 = 3, | ||
| 94 | }; | ||
| 95 | |||
| 89 | void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); | 96 | void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); |
| 90 | Core::HID::NpadStyleTag GetSupportedStyleSet() const; | 97 | Core::HID::NpadStyleTag GetSupportedStyleSet() const; |
| 91 | 98 | ||
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) { | |||
| 44 | if (handle.npad_id != active_handle.npad_id) { | 44 | if (handle.npad_id != active_handle.npad_id) { |
| 45 | return InvalidPalmaHandle; | 45 | return InvalidPalmaHandle; |
| 46 | } | 46 | } |
| 47 | ActivateController(); | 47 | Activate(); |
| 48 | return ResultSuccess; | 48 | return ResultSuccess; |
| 49 | } | 49 | } |
| 50 | 50 | ||
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 @@ | |||
| 3 | 3 | ||
| 4 | #include "core/hle/service/hid/hid.h" | 4 | #include "core/hle/service/hid/hid.h" |
| 5 | #include "core/hle/service/hid/hid_debug_server.h" | 5 | #include "core/hle/service/hid/hid_debug_server.h" |
| 6 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 6 | #include "core/hle/service/hid/hid_server.h" | 7 | #include "core/hle/service/hid/hid_server.h" |
| 7 | #include "core/hle/service/hid/hid_system_server.h" | 8 | #include "core/hle/service/hid/hid_system_server.h" |
| 8 | #include "core/hle/service/hid/hidbus.h" | 9 | #include "core/hle/service/hid/hidbus.h" |
| @@ -16,9 +17,11 @@ namespace Service::HID { | |||
| 16 | void LoopProcess(Core::System& system) { | 17 | void LoopProcess(Core::System& system) { |
| 17 | auto server_manager = std::make_unique<ServerManager>(system); | 18 | auto server_manager = std::make_unique<ServerManager>(system); |
| 18 | std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system); | 19 | std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system); |
| 20 | std::shared_ptr<HidFirmwareSettings> firmware_settings = | ||
| 21 | std::make_shared<HidFirmwareSettings>(); | ||
| 19 | 22 | ||
| 20 | server_manager->RegisterNamedService("hid", | 23 | server_manager->RegisterNamedService( |
| 21 | std::make_shared<IHidServer>(system, resouce_manager)); | 24 | "hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings)); |
| 22 | server_manager->RegisterNamedService( | 25 | server_manager->RegisterNamedService( |
| 23 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager)); | 26 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager)); |
| 24 | server_manager->RegisterNamedService( | 27 | 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | HidFirmwareSettings::HidFirmwareSettings() { | ||
| 9 | LoadSettings(true); | ||
| 10 | } | ||
| 11 | |||
| 12 | void HidFirmwareSettings::Reload() { | ||
| 13 | LoadSettings(true); | ||
| 14 | } | ||
| 15 | |||
| 16 | void HidFirmwareSettings::LoadSettings(bool reload_config) { | ||
| 17 | if (is_initalized && !reload_config) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | |||
| 21 | // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values | ||
| 22 | |||
| 23 | is_debug_pad_enabled = true; | ||
| 24 | is_device_managed = true; | ||
| 25 | is_touch_i2c_managed = is_device_managed; | ||
| 26 | is_future_devices_emulated = false; | ||
| 27 | is_mcu_hardware_error_emulated = false; | ||
| 28 | is_rail_enabled = true; | ||
| 29 | is_firmware_update_failure_emulated = false; | ||
| 30 | is_firmware_update_failure = {}; | ||
| 31 | is_ble_disabled = false; | ||
| 32 | is_dscale_disabled = false; | ||
| 33 | is_handheld_forced = true; | ||
| 34 | features_per_id_disabled = {}; | ||
| 35 | is_touch_firmware_auto_update_disabled = false; | ||
| 36 | is_initalized = true; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool HidFirmwareSettings::IsDebugPadEnabled() { | ||
| 40 | LoadSettings(false); | ||
| 41 | return is_debug_pad_enabled; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool HidFirmwareSettings::IsDeviceManaged() { | ||
| 45 | LoadSettings(false); | ||
| 46 | return is_device_managed; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool HidFirmwareSettings::IsEmulateFutureDevice() { | ||
| 50 | LoadSettings(false); | ||
| 51 | return is_future_devices_emulated; | ||
| 52 | } | ||
| 53 | |||
| 54 | bool HidFirmwareSettings::IsTouchI2cManaged() { | ||
| 55 | LoadSettings(false); | ||
| 56 | return is_touch_i2c_managed; | ||
| 57 | } | ||
| 58 | |||
| 59 | bool HidFirmwareSettings::IsHandheldForced() { | ||
| 60 | LoadSettings(false); | ||
| 61 | return is_handheld_forced; | ||
| 62 | } | ||
| 63 | |||
| 64 | bool HidFirmwareSettings::IsRailEnabled() { | ||
| 65 | LoadSettings(false); | ||
| 66 | return is_rail_enabled; | ||
| 67 | } | ||
| 68 | |||
| 69 | bool HidFirmwareSettings::IsHardwareErrorEmulated() { | ||
| 70 | LoadSettings(false); | ||
| 71 | return is_mcu_hardware_error_emulated; | ||
| 72 | } | ||
| 73 | |||
| 74 | bool HidFirmwareSettings::IsBleDisabled() { | ||
| 75 | LoadSettings(false); | ||
| 76 | return is_ble_disabled; | ||
| 77 | } | ||
| 78 | |||
| 79 | bool HidFirmwareSettings::IsDscaleDisabled() { | ||
| 80 | LoadSettings(false); | ||
| 81 | return is_dscale_disabled; | ||
| 82 | } | ||
| 83 | |||
| 84 | bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() { | ||
| 85 | LoadSettings(false); | ||
| 86 | return is_touch_firmware_auto_update_disabled; | ||
| 87 | } | ||
| 88 | |||
| 89 | HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() { | ||
| 90 | LoadSettings(false); | ||
| 91 | return is_firmware_update_failure; | ||
| 92 | } | ||
| 93 | |||
| 94 | HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() { | ||
| 95 | LoadSettings(false); | ||
| 96 | return features_per_id_disabled; | ||
| 97 | } | ||
| 98 | |||
| 99 | } // 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | /// Loads firmware config from nn::settings::fwdbg | ||
| 11 | class HidFirmwareSettings { | ||
| 12 | public: | ||
| 13 | using FirmwareSetting = std::array<u8, 4>; | ||
| 14 | using FeaturesPerId = std::array<bool, 0xA8>; | ||
| 15 | |||
| 16 | HidFirmwareSettings(); | ||
| 17 | |||
| 18 | void Reload(); | ||
| 19 | void LoadSettings(bool reload_config); | ||
| 20 | |||
| 21 | bool IsDebugPadEnabled(); | ||
| 22 | bool IsDeviceManaged(); | ||
| 23 | bool IsEmulateFutureDevice(); | ||
| 24 | bool IsTouchI2cManaged(); | ||
| 25 | bool IsHandheldForced(); | ||
| 26 | bool IsRailEnabled(); | ||
| 27 | bool IsHardwareErrorEmulated(); | ||
| 28 | bool IsBleDisabled(); | ||
| 29 | bool IsDscaleDisabled(); | ||
| 30 | bool IsTouchAutoUpdateDisabled(); | ||
| 31 | |||
| 32 | FirmwareSetting GetFirmwareUpdateFailure(); | ||
| 33 | FeaturesPerId FeaturesDisabledPerId(); | ||
| 34 | |||
| 35 | private: | ||
| 36 | bool is_initalized{}; | ||
| 37 | |||
| 38 | // Debug settings | ||
| 39 | bool is_debug_pad_enabled{}; | ||
| 40 | bool is_device_managed{}; | ||
| 41 | bool is_touch_i2c_managed{}; | ||
| 42 | bool is_future_devices_emulated{}; | ||
| 43 | bool is_mcu_hardware_error_emulated{}; | ||
| 44 | bool is_rail_enabled{}; | ||
| 45 | bool is_firmware_update_failure_emulated{}; | ||
| 46 | bool is_ble_disabled{}; | ||
| 47 | bool is_dscale_disabled{}; | ||
| 48 | bool is_handheld_forced{}; | ||
| 49 | bool is_touch_firmware_auto_update_disabled{}; | ||
| 50 | FirmwareSetting is_firmware_update_failure{}; | ||
| 51 | FeaturesPerId features_per_id_disabled{}; | ||
| 52 | }; | ||
| 53 | |||
| 54 | } // 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 @@ | |||
| 10 | #include "core/hle/kernel/k_transfer_memory.h" | 10 | #include "core/hle/kernel/k_transfer_memory.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/service/hid/errors.h" | 12 | #include "core/hle/service/hid/errors.h" |
| 13 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 13 | #include "core/hle/service/hid/hid_server.h" | 14 | #include "core/hle/service/hid/hid_server.h" |
| 14 | #include "core/hle/service/hid/resource_manager.h" | 15 | #include "core/hle/service/hid/resource_manager.h" |
| 15 | #include "core/hle/service/ipc_helpers.h" | 16 | #include "core/hle/service/ipc_helpers.h" |
| @@ -64,8 +65,9 @@ private: | |||
| 64 | std::shared_ptr<ResourceManager> resource_manager; | 65 | std::shared_ptr<ResourceManager> resource_manager; |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource) | 68 | IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, |
| 68 | : ServiceFramework{system_, "hid"}, resource_manager{resource} { | 69 | std::shared_ptr<HidFirmwareSettings> settings) |
| 70 | : ServiceFramework{system_, "hid"}, resource_manager{resource}, firmware_settings{settings} { | ||
| 69 | // clang-format off | 71 | // clang-format off |
| 70 | static const FunctionInfo functions[] = { | 72 | static const FunctionInfo functions[] = { |
| 71 | {0, &IHidServer::CreateAppletResource, "CreateAppletResource"}, | 73 | {0, &IHidServer::CreateAppletResource, "CreateAppletResource"}, |
| @@ -230,48 +232,87 @@ void IHidServer::ActivateDebugPad(HLERequestContext& ctx) { | |||
| 230 | IPC::RequestParser rp{ctx}; | 232 | IPC::RequestParser rp{ctx}; |
| 231 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 233 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 232 | 234 | ||
| 233 | GetResourceManager()->ActivateController(HidController::DebugPad); | ||
| 234 | |||
| 235 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 235 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 236 | 236 | ||
| 237 | Result result = ResultSuccess; | ||
| 238 | auto& debug_pad = | ||
| 239 | GetResourceManager()->GetController<Controller_DebugPad>(HidController::DebugPad); | ||
| 240 | |||
| 241 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 242 | result = debug_pad.Activate(); | ||
| 243 | } | ||
| 244 | |||
| 245 | if (result.IsSuccess()) { | ||
| 246 | result = debug_pad.Activate(applet_resource_user_id); | ||
| 247 | } | ||
| 248 | |||
| 237 | IPC::ResponseBuilder rb{ctx, 2}; | 249 | IPC::ResponseBuilder rb{ctx, 2}; |
| 238 | rb.Push(ResultSuccess); | 250 | rb.Push(result); |
| 239 | } | 251 | } |
| 240 | 252 | ||
| 241 | void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) { | 253 | void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) { |
| 242 | IPC::RequestParser rp{ctx}; | 254 | IPC::RequestParser rp{ctx}; |
| 243 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 255 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 244 | 256 | ||
| 245 | GetResourceManager()->ActivateController(HidController::Touchscreen); | ||
| 246 | |||
| 247 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 257 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 248 | 258 | ||
| 259 | Result result = ResultSuccess; | ||
| 260 | auto& touch_screen = | ||
| 261 | GetResourceManager()->GetController<Controller_Touchscreen>(HidController::Touchscreen); | ||
| 262 | |||
| 263 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 264 | result = touch_screen.Activate(); | ||
| 265 | } | ||
| 266 | |||
| 267 | if (result.IsSuccess()) { | ||
| 268 | result = touch_screen.Activate(applet_resource_user_id); | ||
| 269 | } | ||
| 270 | |||
| 249 | IPC::ResponseBuilder rb{ctx, 2}; | 271 | IPC::ResponseBuilder rb{ctx, 2}; |
| 250 | rb.Push(ResultSuccess); | 272 | rb.Push(result); |
| 251 | } | 273 | } |
| 252 | 274 | ||
| 253 | void IHidServer::ActivateMouse(HLERequestContext& ctx) { | 275 | void IHidServer::ActivateMouse(HLERequestContext& ctx) { |
| 254 | IPC::RequestParser rp{ctx}; | 276 | IPC::RequestParser rp{ctx}; |
| 255 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 277 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 256 | 278 | ||
| 257 | GetResourceManager()->ActivateController(HidController::Mouse); | ||
| 258 | |||
| 259 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 279 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 260 | 280 | ||
| 281 | Result result = ResultSuccess; | ||
| 282 | auto& mouse = GetResourceManager()->GetController<Controller_Mouse>(HidController::Mouse); | ||
| 283 | |||
| 284 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 285 | result = mouse.Activate(); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (result.IsSuccess()) { | ||
| 289 | result = mouse.Activate(applet_resource_user_id); | ||
| 290 | } | ||
| 291 | |||
| 261 | IPC::ResponseBuilder rb{ctx, 2}; | 292 | IPC::ResponseBuilder rb{ctx, 2}; |
| 262 | rb.Push(ResultSuccess); | 293 | rb.Push(result); |
| 263 | } | 294 | } |
| 264 | 295 | ||
| 265 | void IHidServer::ActivateKeyboard(HLERequestContext& ctx) { | 296 | void IHidServer::ActivateKeyboard(HLERequestContext& ctx) { |
| 266 | IPC::RequestParser rp{ctx}; | 297 | IPC::RequestParser rp{ctx}; |
| 267 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 298 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 268 | 299 | ||
| 269 | GetResourceManager()->ActivateController(HidController::Keyboard); | ||
| 270 | |||
| 271 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 300 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 272 | 301 | ||
| 302 | Result result = ResultSuccess; | ||
| 303 | auto& keyboard = | ||
| 304 | GetResourceManager()->GetController<Controller_Keyboard>(HidController::Keyboard); | ||
| 305 | |||
| 306 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 307 | result = keyboard.Activate(); | ||
| 308 | } | ||
| 309 | |||
| 310 | if (result.IsSuccess()) { | ||
| 311 | result = keyboard.Activate(applet_resource_user_id); | ||
| 312 | } | ||
| 313 | |||
| 273 | IPC::ResponseBuilder rb{ctx, 2}; | 314 | IPC::ResponseBuilder rb{ctx, 2}; |
| 274 | rb.Push(ResultSuccess); | 315 | rb.Push(result); |
| 275 | } | 316 | } |
| 276 | 317 | ||
| 277 | void IHidServer::SendKeyboardLockKeyEvent(HLERequestContext& ctx) { | 318 | void IHidServer::SendKeyboardLockKeyEvent(HLERequestContext& ctx) { |
| @@ -898,7 +939,7 @@ void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) | |||
| 898 | void IHidServer::ActivateGesture(HLERequestContext& ctx) { | 939 | void IHidServer::ActivateGesture(HLERequestContext& ctx) { |
| 899 | IPC::RequestParser rp{ctx}; | 940 | IPC::RequestParser rp{ctx}; |
| 900 | struct Parameters { | 941 | struct Parameters { |
| 901 | u32 unknown; | 942 | u32 basic_gesture_id; |
| 902 | INSERT_PADDING_WORDS_NOINIT(1); | 943 | INSERT_PADDING_WORDS_NOINIT(1); |
| 903 | u64 applet_resource_user_id; | 944 | u64 applet_resource_user_id; |
| 904 | }; | 945 | }; |
| @@ -906,13 +947,23 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) { | |||
| 906 | 947 | ||
| 907 | const auto parameters{rp.PopRaw<Parameters>()}; | 948 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 908 | 949 | ||
| 909 | GetResourceManager()->ActivateController(HidController::Gesture); | 950 | LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}", |
| 951 | parameters.basic_gesture_id, parameters.applet_resource_user_id); | ||
| 910 | 952 | ||
| 911 | LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}", | 953 | Result result = ResultSuccess; |
| 912 | parameters.unknown, parameters.applet_resource_user_id); | 954 | auto& gesture = GetResourceManager()->GetController<Controller_Gesture>(HidController::Gesture); |
| 955 | |||
| 956 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 957 | result = gesture.Activate(); | ||
| 958 | } | ||
| 959 | |||
| 960 | if (result.IsSuccess()) { | ||
| 961 | // TODO: Use gesture id here | ||
| 962 | result = gesture.Activate(parameters.applet_resource_user_id); | ||
| 963 | } | ||
| 913 | 964 | ||
| 914 | IPC::ResponseBuilder rb{ctx, 2}; | 965 | IPC::ResponseBuilder rb{ctx, 2}; |
| 915 | rb.Push(ResultSuccess); | 966 | rb.Push(result); |
| 916 | } | 967 | } |
| 917 | 968 | ||
| 918 | void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) { | 969 | void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) { |
| @@ -969,22 +1020,25 @@ void IHidServer::ActivateNpad(HLERequestContext& ctx) { | |||
| 969 | IPC::RequestParser rp{ctx}; | 1020 | IPC::RequestParser rp{ctx}; |
| 970 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1021 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 971 | 1022 | ||
| 972 | GetResourceManager()->ActivateController(HidController::NPad); | ||
| 973 | |||
| 974 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1023 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 975 | 1024 | ||
| 1025 | auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); | ||
| 1026 | |||
| 1027 | // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0); | ||
| 1028 | const Result result = npad.Activate(applet_resource_user_id); | ||
| 1029 | |||
| 976 | IPC::ResponseBuilder rb{ctx, 2}; | 1030 | IPC::ResponseBuilder rb{ctx, 2}; |
| 977 | rb.Push(ResultSuccess); | 1031 | rb.Push(result); |
| 978 | } | 1032 | } |
| 979 | 1033 | ||
| 980 | void IHidServer::DeactivateNpad(HLERequestContext& ctx) { | 1034 | void IHidServer::DeactivateNpad(HLERequestContext& ctx) { |
| 981 | IPC::RequestParser rp{ctx}; | 1035 | IPC::RequestParser rp{ctx}; |
| 982 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1036 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 983 | 1037 | ||
| 984 | GetResourceManager()->DeactivateController(HidController::NPad); | ||
| 985 | |||
| 986 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1038 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 987 | 1039 | ||
| 1040 | // This function does nothing since 10.0.0+ | ||
| 1041 | |||
| 988 | IPC::ResponseBuilder rb{ctx, 2}; | 1042 | IPC::ResponseBuilder rb{ctx, 2}; |
| 989 | rb.Push(ResultSuccess); | 1043 | rb.Push(ResultSuccess); |
| 990 | } | 1044 | } |
| @@ -1053,10 +1107,9 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { | |||
| 1053 | } | 1107 | } |
| 1054 | 1108 | ||
| 1055 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { | 1109 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { |
| 1056 | // Should have no effect with how our npad sets up the data | ||
| 1057 | IPC::RequestParser rp{ctx}; | 1110 | IPC::RequestParser rp{ctx}; |
| 1058 | struct Parameters { | 1111 | struct Parameters { |
| 1059 | s32 revision; | 1112 | Controller_NPad::NpadRevision revision; |
| 1060 | INSERT_PADDING_WORDS_NOINIT(1); | 1113 | INSERT_PADDING_WORDS_NOINIT(1); |
| 1061 | u64 applet_resource_user_id; | 1114 | u64 applet_resource_user_id; |
| 1062 | }; | 1115 | }; |
| @@ -1064,13 +1117,16 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { | |||
| 1064 | 1117 | ||
| 1065 | const auto parameters{rp.PopRaw<Parameters>()}; | 1118 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1066 | 1119 | ||
| 1067 | GetResourceManager()->ActivateController(HidController::NPad); | ||
| 1068 | |||
| 1069 | LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision, | 1120 | LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision, |
| 1070 | parameters.applet_resource_user_id); | 1121 | parameters.applet_resource_user_id); |
| 1071 | 1122 | ||
| 1123 | auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); | ||
| 1124 | |||
| 1125 | // TODO: npad->SetRevision(applet_resource_user_id, revision); | ||
| 1126 | const auto result = npad.Activate(parameters.applet_resource_user_id); | ||
| 1127 | |||
| 1072 | IPC::ResponseBuilder rb{ctx, 2}; | 1128 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1073 | rb.Push(ResultSuccess); | 1129 | rb.Push(result); |
| 1074 | } | 1130 | } |
| 1075 | 1131 | ||
| 1076 | void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { | 1132 | void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { |
| @@ -1718,12 +1774,22 @@ void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { | |||
| 1718 | IPC::RequestParser rp{ctx}; | 1774 | IPC::RequestParser rp{ctx}; |
| 1719 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1775 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1720 | 1776 | ||
| 1721 | GetResourceManager()->ActivateController(HidController::ConsoleSixAxisSensor); | 1777 | LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1722 | 1778 | ||
| 1723 | LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1779 | Result result = ResultSuccess; |
| 1780 | auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( | ||
| 1781 | HidController::ConsoleSixAxisSensor); | ||
| 1782 | |||
| 1783 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 1784 | result = console_sixaxis.Activate(); | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | if (result.IsSuccess()) { | ||
| 1788 | result = console_sixaxis.Activate(applet_resource_user_id); | ||
| 1789 | } | ||
| 1724 | 1790 | ||
| 1725 | IPC::ResponseBuilder rb{ctx, 2}; | 1791 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1726 | rb.Push(ResultSuccess); | 1792 | rb.Push(result); |
| 1727 | } | 1793 | } |
| 1728 | 1794 | ||
| 1729 | void IHidServer::StartConsoleSixAxisSensor(HLERequestContext& ctx) { | 1795 | void IHidServer::StartConsoleSixAxisSensor(HLERequestContext& ctx) { |
| @@ -1770,9 +1836,19 @@ void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) { | |||
| 1770 | IPC::RequestParser rp{ctx}; | 1836 | IPC::RequestParser rp{ctx}; |
| 1771 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1837 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1772 | 1838 | ||
| 1773 | GetResourceManager()->ActivateController(HidController::ConsoleSixAxisSensor); | 1839 | LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1774 | 1840 | ||
| 1775 | LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1841 | Result result = ResultSuccess; |
| 1842 | auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( | ||
| 1843 | HidController::ConsoleSixAxisSensor); | ||
| 1844 | |||
| 1845 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 1846 | result = console_sixaxis.Activate(); | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | if (result.IsSuccess()) { | ||
| 1850 | console_sixaxis.Activate(applet_resource_user_id); | ||
| 1851 | } | ||
| 1776 | 1852 | ||
| 1777 | IPC::ResponseBuilder rb{ctx, 2}; | 1853 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1778 | rb.Push(ResultSuccess); | 1854 | rb.Push(ResultSuccess); |
| @@ -1837,7 +1913,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) { | |||
| 1837 | // Activate console six axis controller | 1913 | // Activate console six axis controller |
| 1838 | GetResourceManager() | 1914 | GetResourceManager() |
| 1839 | ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) | 1915 | ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) |
| 1840 | .ActivateController(); | 1916 | .Activate(); |
| 1841 | 1917 | ||
| 1842 | GetResourceManager() | 1918 | GetResourceManager() |
| 1843 | ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) | 1919 | ->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; | |||
| 11 | 11 | ||
| 12 | namespace Service::HID { | 12 | namespace Service::HID { |
| 13 | class ResourceManager; | 13 | class ResourceManager; |
| 14 | class HidFirmwareSettings; | ||
| 14 | 15 | ||
| 15 | class IHidServer final : public ServiceFramework<IHidServer> { | 16 | class IHidServer final : public ServiceFramework<IHidServer> { |
| 16 | public: | 17 | public: |
| 17 | explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource); | 18 | explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, |
| 19 | std::shared_ptr<HidFirmwareSettings> settings); | ||
| 18 | ~IHidServer() override; | 20 | ~IHidServer() override; |
| 19 | 21 | ||
| 20 | std::shared_ptr<ResourceManager> GetResourceManager(); | 22 | std::shared_ptr<ResourceManager> GetResourceManager(); |
| @@ -141,6 +143,7 @@ private: | |||
| 141 | void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx); | 143 | void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx); |
| 142 | 144 | ||
| 143 | std::shared_ptr<ResourceManager> resource_manager; | 145 | std::shared_ptr<ResourceManager> resource_manager; |
| 146 | std::shared_ptr<HidFirmwareSettings> firmware_settings; | ||
| 144 | }; | 147 | }; |
| 145 | 148 | ||
| 146 | } // namespace Service::HID | 149 | } // 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() { | |||
| 59 | MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory); | 59 | MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory); |
| 60 | 60 | ||
| 61 | // Homebrew doesn't try to activate some controllers, so we activate them by default | 61 | // Homebrew doesn't try to activate some controllers, so we activate them by default |
| 62 | GetController<Controller_NPad>(HidController::NPad).ActivateController(); | 62 | GetController<Controller_NPad>(HidController::NPad).Activate(); |
| 63 | GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController(); | 63 | GetController<Controller_Touchscreen>(HidController::Touchscreen).Activate(); |
| 64 | 64 | ||
| 65 | GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00); | 65 | GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00); |
| 66 | GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00); | 66 | GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00); |
| @@ -73,14 +73,6 @@ void ResourceManager::Initialize() { | |||
| 73 | is_initialized = true; | 73 | is_initialized = true; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | void ResourceManager::ActivateController(HidController controller) { | ||
| 77 | controllers[static_cast<size_t>(controller)]->ActivateController(); | ||
| 78 | } | ||
| 79 | |||
| 80 | void ResourceManager::DeactivateController(HidController controller) { | ||
| 81 | controllers[static_cast<size_t>(controller)]->DeactivateController(); | ||
| 82 | } | ||
| 83 | |||
| 84 | void ResourceManager::UpdateControllers(std::uintptr_t user_data, | 76 | void ResourceManager::UpdateControllers(std::uintptr_t user_data, |
| 85 | std::chrono::nanoseconds ns_late) { | 77 | std::chrono::nanoseconds ns_late) { |
| 86 | auto& core_timing = system.CoreTiming(); | 78 | 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: | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void Initialize(); | 57 | void Initialize(); |
| 58 | void ActivateController(HidController controller); | ||
| 59 | void DeactivateController(HidController controller); | ||
| 60 | 58 | ||
| 61 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 59 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 62 | void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 60 | 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 @@ | |||
| 15 | 15 | ||
| 16 | namespace Service::android { | 16 | namespace Service::android { |
| 17 | 17 | ||
| 18 | struct GraphicBuffer; | 18 | class GraphicBuffer; |
| 19 | 19 | ||
| 20 | class BufferItem final { | 20 | class BufferItem final { |
| 21 | public: | 21 | 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 @@ | |||
| 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp | 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp |
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/hle/service/nvdrv/core/nvmap.h" | ||
| 9 | #include "core/hle/service/nvnflinger/buffer_item.h" | 8 | #include "core/hle/service/nvnflinger/buffer_item.h" |
| 10 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" | 9 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" |
| 11 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 10 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| @@ -14,9 +13,8 @@ | |||
| 14 | 13 | ||
| 15 | namespace Service::android { | 14 | namespace Service::android { |
| 16 | 15 | ||
| 17 | BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, | 16 | BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_) |
| 18 | Service::Nvidia::NvCore::NvMap& nvmap_) | 17 | : core{std::move(core_)}, slots{core->slots} {} |
| 19 | : core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {} | ||
| 20 | 18 | ||
| 21 | BufferQueueConsumer::~BufferQueueConsumer() = default; | 19 | BufferQueueConsumer::~BufferQueueConsumer() = default; |
| 22 | 20 | ||
| @@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc | |||
| 136 | 134 | ||
| 137 | slots[slot].buffer_state = BufferState::Free; | 135 | slots[slot].buffer_state = BufferState::Free; |
| 138 | 136 | ||
| 139 | nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true); | ||
| 140 | |||
| 141 | listener = core->connected_producer_listener; | 137 | listener = core->connected_producer_listener; |
| 142 | 138 | ||
| 143 | LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); | 139 | LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); |
| @@ -175,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_ | |||
| 175 | return Status::NoError; | 171 | return Status::NoError; |
| 176 | } | 172 | } |
| 177 | 173 | ||
| 174 | Status BufferQueueConsumer::Disconnect() { | ||
| 175 | LOG_DEBUG(Service_Nvnflinger, "called"); | ||
| 176 | |||
| 177 | std::scoped_lock lock{core->mutex}; | ||
| 178 | |||
| 179 | if (core->consumer_listener == nullptr) { | ||
| 180 | LOG_ERROR(Service_Nvnflinger, "no consumer is connected"); | ||
| 181 | return Status::BadValue; | ||
| 182 | } | ||
| 183 | |||
| 184 | core->is_abandoned = true; | ||
| 185 | core->consumer_listener = nullptr; | ||
| 186 | core->queue.clear(); | ||
| 187 | core->FreeAllBuffersLocked(); | ||
| 188 | core->SignalDequeueCondition(); | ||
| 189 | |||
| 190 | return Status::NoError; | ||
| 191 | } | ||
| 192 | |||
| 178 | Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { | 193 | Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { |
| 179 | if (out_slot_mask == nullptr) { | 194 | if (out_slot_mask == nullptr) { |
| 180 | LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr"); | 195 | 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 @@ | |||
| 13 | #include "core/hle/service/nvnflinger/buffer_queue_defs.h" | 13 | #include "core/hle/service/nvnflinger/buffer_queue_defs.h" |
| 14 | #include "core/hle/service/nvnflinger/status.h" | 14 | #include "core/hle/service/nvnflinger/status.h" |
| 15 | 15 | ||
| 16 | namespace Service::Nvidia::NvCore { | ||
| 17 | class NvMap; | ||
| 18 | } // namespace Service::Nvidia::NvCore | ||
| 19 | |||
| 20 | namespace Service::android { | 16 | namespace Service::android { |
| 21 | 17 | ||
| 22 | class BufferItem; | 18 | class BufferItem; |
| @@ -25,19 +21,18 @@ class IConsumerListener; | |||
| 25 | 21 | ||
| 26 | class BufferQueueConsumer final { | 22 | class BufferQueueConsumer final { |
| 27 | public: | 23 | public: |
| 28 | explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, | 24 | explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); |
| 29 | Service::Nvidia::NvCore::NvMap& nvmap_); | ||
| 30 | ~BufferQueueConsumer(); | 25 | ~BufferQueueConsumer(); |
| 31 | 26 | ||
| 32 | Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); | 27 | Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); |
| 33 | Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); | 28 | Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); |
| 34 | Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); | 29 | Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); |
| 30 | Status Disconnect(); | ||
| 35 | Status GetReleasedBuffers(u64* out_slot_mask); | 31 | Status GetReleasedBuffers(u64* out_slot_mask); |
| 36 | 32 | ||
| 37 | private: | 33 | private: |
| 38 | std::shared_ptr<BufferQueueCore> core; | 34 | std::shared_ptr<BufferQueueCore> core; |
| 39 | BufferQueueDefs::SlotsType& slots; | 35 | BufferQueueDefs::SlotsType& slots; |
| 40 | Service::Nvidia::NvCore::NvMap& nvmap; | ||
| 41 | }; | 36 | }; |
| 42 | 37 | ||
| 43 | } // namespace Service::android | 38 | } // 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; | |||
| 14 | 14 | ||
| 15 | BufferQueueCore::~BufferQueueCore() = default; | 15 | BufferQueueCore::~BufferQueueCore() = default; |
| 16 | 16 | ||
| 17 | void BufferQueueCore::NotifyShutdown() { | ||
| 18 | std::scoped_lock lock{mutex}; | ||
| 19 | |||
| 20 | is_shutting_down = true; | ||
| 21 | |||
| 22 | SignalDequeueCondition(); | ||
| 23 | } | ||
| 24 | |||
| 25 | void BufferQueueCore::SignalDequeueCondition() { | 17 | void BufferQueueCore::SignalDequeueCondition() { |
| 26 | dequeue_possible.store(true); | 18 | dequeue_possible.store(true); |
| 27 | dequeue_condition.notify_all(); | 19 | dequeue_condition.notify_all(); |
| 28 | } | 20 | } |
| 29 | 21 | ||
| 30 | bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { | 22 | bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { |
| 31 | if (is_shutting_down) { | ||
| 32 | return false; | ||
| 33 | } | ||
| 34 | |||
| 35 | dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); | 23 | dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); |
| 36 | dequeue_possible.store(false); | 24 | dequeue_possible.store(false); |
| 37 | 25 | ||
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: | |||
| 34 | BufferQueueCore(); | 34 | BufferQueueCore(); |
| 35 | ~BufferQueueCore(); | 35 | ~BufferQueueCore(); |
| 36 | 36 | ||
| 37 | void NotifyShutdown(); | ||
| 38 | |||
| 39 | private: | 37 | private: |
| 40 | void SignalDequeueCondition(); | 38 | void SignalDequeueCondition(); |
| 41 | bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); | 39 | bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); |
| @@ -74,7 +72,6 @@ private: | |||
| 74 | u32 transform_hint{}; | 72 | u32 transform_hint{}; |
| 75 | bool is_allocating{}; | 73 | bool is_allocating{}; |
| 76 | mutable std::condition_variable_any is_allocating_condition; | 74 | mutable std::condition_variable_any is_allocating_condition; |
| 77 | bool is_shutting_down{}; | ||
| 78 | }; | 75 | }; |
| 79 | 76 | ||
| 80 | } // namespace Service::android | 77 | } // 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 @@ | |||
| 13 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/service/hle_ipc.h" | 14 | #include "core/hle/service/hle_ipc.h" |
| 15 | #include "core/hle/service/kernel_helpers.h" | 15 | #include "core/hle/service/kernel_helpers.h" |
| 16 | #include "core/hle/service/nvdrv/core/nvmap.h" | ||
| 17 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 16 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| 18 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | 17 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" |
| 19 | #include "core/hle/service/nvnflinger/consumer_listener.h" | 18 | #include "core/hle/service/nvnflinger/consumer_listener.h" |
| @@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, | |||
| 533 | item.is_droppable = core->dequeue_buffer_cannot_block || async; | 532 | item.is_droppable = core->dequeue_buffer_cannot_block || async; |
| 534 | item.swap_interval = swap_interval; | 533 | item.swap_interval = swap_interval; |
| 535 | 534 | ||
| 536 | nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true); | ||
| 537 | |||
| 538 | sticky_transform = sticky_transform_; | 535 | sticky_transform = sticky_transform_; |
| 539 | 536 | ||
| 540 | if (core->queue.empty()) { | 537 | if (core->queue.empty()) { |
| @@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { | |||
| 744 | return Status::NoError; | 741 | return Status::NoError; |
| 745 | } | 742 | } |
| 746 | 743 | ||
| 747 | // HACK: We are not Android. Remove handle for items in queue, and clear queue. | ||
| 748 | // Allows synchronous destruction of nvmap handles. | ||
| 749 | for (auto& item : core->queue) { | ||
| 750 | nvmap.FreeHandle(item.graphic_buffer->BufferId(), true); | ||
| 751 | } | ||
| 752 | core->queue.clear(); | ||
| 753 | |||
| 754 | switch (api) { | 744 | switch (api) { |
| 755 | case NativeWindowApi::Egl: | 745 | case NativeWindowApi::Egl: |
| 756 | case NativeWindowApi::Cpu: | 746 | case NativeWindowApi::Cpu: |
| 757 | case NativeWindowApi::Media: | 747 | case NativeWindowApi::Media: |
| 758 | case NativeWindowApi::Camera: | 748 | case NativeWindowApi::Camera: |
| 759 | if (core->connected_api == api) { | 749 | if (core->connected_api == api) { |
| 750 | core->queue.clear(); | ||
| 760 | core->FreeAllBuffersLocked(); | 751 | core->FreeAllBuffersLocked(); |
| 761 | core->connected_producer_listener = nullptr; | 752 | core->connected_producer_listener = nullptr; |
| 762 | core->connected_api = NativeWindowApi::NoConnectedApi; | 753 | core->connected_api = NativeWindowApi::NoConnectedApi; |
| @@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { | |||
| 785 | } | 776 | } |
| 786 | 777 | ||
| 787 | Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | 778 | Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, |
| 788 | const std::shared_ptr<GraphicBuffer>& buffer) { | 779 | const std::shared_ptr<NvGraphicBuffer>& buffer) { |
| 789 | LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); | 780 | LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); |
| 790 | 781 | ||
| 791 | if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { | 782 | if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { |
| @@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | |||
| 796 | 787 | ||
| 797 | slots[slot] = {}; | 788 | slots[slot] = {}; |
| 798 | slots[slot].fence = Fence::NoFence(); | 789 | slots[slot].fence = Fence::NoFence(); |
| 799 | slots[slot].graphic_buffer = buffer; | 790 | slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer); |
| 800 | slots[slot].frame_number = 0; | 791 | slots[slot].frame_number = 0; |
| 801 | 792 | ||
| 802 | // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for | 793 | // 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 | |||
| 839 | } | 830 | } |
| 840 | case TransactionId::SetPreallocatedBuffer: { | 831 | case TransactionId::SetPreallocatedBuffer: { |
| 841 | const auto slot = parcel_in.Read<s32>(); | 832 | const auto slot = parcel_in.Read<s32>(); |
| 842 | const auto buffer = parcel_in.ReadObject<GraphicBuffer>(); | 833 | const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>(); |
| 843 | 834 | ||
| 844 | status = SetPreallocatedBuffer(slot, buffer); | 835 | status = SetPreallocatedBuffer(slot, buffer); |
| 845 | break; | 836 | break; |
| @@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u | |||
| 867 | 858 | ||
| 868 | status = RequestBuffer(slot, &buf); | 859 | status = RequestBuffer(slot, &buf); |
| 869 | 860 | ||
| 870 | parcel_out.WriteFlattenedObject(buf); | 861 | parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get()); |
| 871 | break; | 862 | break; |
| 872 | } | 863 | } |
| 873 | case TransactionId::QueueBuffer: { | 864 | 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 { | |||
| 38 | 38 | ||
| 39 | class BufferQueueCore; | 39 | class BufferQueueCore; |
| 40 | class IProducerListener; | 40 | class IProducerListener; |
| 41 | struct NvGraphicBuffer; | ||
| 41 | 42 | ||
| 42 | class BufferQueueProducer final : public IBinder { | 43 | class BufferQueueProducer final : public IBinder { |
| 43 | public: | 44 | public: |
| @@ -65,7 +66,7 @@ public: | |||
| 65 | bool producer_controlled_by_app, QueueBufferOutput* output); | 66 | bool producer_controlled_by_app, QueueBufferOutput* output); |
| 66 | 67 | ||
| 67 | Status Disconnect(NativeWindowApi api); | 68 | Status Disconnect(NativeWindowApi api); |
| 68 | Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer); | 69 | Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer); |
| 69 | 70 | ||
| 70 | private: | 71 | private: |
| 71 | BufferQueueProducer(const BufferQueueProducer&) = delete; | 72 | 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 @@ | |||
| 13 | 13 | ||
| 14 | namespace Service::android { | 14 | namespace Service::android { |
| 15 | 15 | ||
| 16 | struct GraphicBuffer; | 16 | class GraphicBuffer; |
| 17 | 17 | ||
| 18 | enum class BufferState : u32 { | 18 | enum class BufferState : u32 { |
| 19 | Free = 0, | 19 | 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) { | |||
| 27 | consumer->Connect(shared_from_this(), controlled_by_app); | 27 | consumer->Connect(shared_from_this(), controlled_by_app); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | void ConsumerBase::Abandon() { | ||
| 31 | LOG_DEBUG(Service_Nvnflinger, "called"); | ||
| 32 | |||
| 33 | std::scoped_lock lock{mutex}; | ||
| 34 | |||
| 35 | if (!is_abandoned) { | ||
| 36 | this->AbandonLocked(); | ||
| 37 | is_abandoned = true; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | void ConsumerBase::AbandonLocked() { | ||
| 42 | for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) { | ||
| 43 | this->FreeBufferLocked(i); | ||
| 44 | } | ||
| 45 | // disconnect from the BufferQueue | ||
| 46 | consumer->Disconnect(); | ||
| 47 | consumer = nullptr; | ||
| 48 | } | ||
| 49 | |||
| 30 | void ConsumerBase::FreeBufferLocked(s32 slot_index) { | 50 | void ConsumerBase::FreeBufferLocked(s32 slot_index) { |
| 31 | LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); | 51 | LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); |
| 32 | 52 | ||
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; | |||
| 24 | class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> { | 24 | class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> { |
| 25 | public: | 25 | public: |
| 26 | void Connect(bool controlled_by_app); | 26 | void Connect(bool controlled_by_app); |
| 27 | void Abandon(); | ||
| 27 | 28 | ||
| 28 | protected: | 29 | protected: |
| 29 | explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); | 30 | explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); |
| @@ -34,6 +35,7 @@ protected: | |||
| 34 | void OnBuffersReleased() override; | 35 | void OnBuffersReleased() override; |
| 35 | void OnSidebandStreamChanged() override; | 36 | void OnSidebandStreamChanged() override; |
| 36 | 37 | ||
| 38 | void AbandonLocked(); | ||
| 37 | void FreeBufferLocked(s32 slot_index); | 39 | void FreeBufferLocked(s32 slot_index); |
| 38 | Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); | 40 | Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); |
| 39 | Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); | 41 | 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 = [] { | |||
| 166 | }(); | 166 | }(); |
| 167 | 167 | ||
| 168 | void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { | 168 | void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { |
| 169 | auto buffer = std::make_shared<android::GraphicBuffer>(); | 169 | auto buffer = std::make_shared<android::NvGraphicBuffer>(); |
| 170 | buffer->width = SharedBufferWidth; | 170 | buffer->width = SharedBufferWidth; |
| 171 | buffer->height = SharedBufferHeight; | 171 | buffer->height = SharedBufferHeight; |
| 172 | buffer->stride = SharedBufferBlockLinearStride; | 172 | 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) { | |||
| 47 | vsync_signal.Wait(); | 47 | vsync_signal.Wait(); |
| 48 | 48 | ||
| 49 | const auto lock_guard = Lock(); | 49 | const auto lock_guard = Lock(); |
| 50 | Compose(); | 50 | |
| 51 | if (!is_abandoned) { | ||
| 52 | Compose(); | ||
| 53 | } | ||
| 51 | } | 54 | } |
| 52 | } | 55 | } |
| 53 | 56 | ||
| @@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() { | |||
| 98 | } | 101 | } |
| 99 | 102 | ||
| 100 | ShutdownLayers(); | 103 | ShutdownLayers(); |
| 101 | vsync_thread = {}; | ||
| 102 | 104 | ||
| 103 | if (nvdrv) { | 105 | if (nvdrv) { |
| 104 | nvdrv->Close(disp_fd); | 106 | nvdrv->Close(disp_fd); |
| @@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() { | |||
| 106 | } | 108 | } |
| 107 | 109 | ||
| 108 | void Nvnflinger::ShutdownLayers() { | 110 | void Nvnflinger::ShutdownLayers() { |
| 109 | const auto lock_guard = Lock(); | 111 | // Abandon consumers. |
| 110 | for (auto& display : displays) { | 112 | { |
| 111 | for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { | 113 | const auto lock_guard = Lock(); |
| 112 | display.GetLayer(layer).Core().NotifyShutdown(); | 114 | for (auto& display : displays) { |
| 115 | for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { | ||
| 116 | display.GetLayer(layer).GetConsumer().Abandon(); | ||
| 117 | } | ||
| 113 | } | 118 | } |
| 119 | |||
| 120 | is_abandoned = true; | ||
| 114 | } | 121 | } |
| 122 | |||
| 123 | // Join the vsync thread, if it exists. | ||
| 124 | vsync_thread = {}; | ||
| 115 | } | 125 | } |
| 116 | 126 | ||
| 117 | void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { | 127 | 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: | |||
| 140 | 140 | ||
| 141 | s32 swap_interval = 1; | 141 | s32 swap_interval = 1; |
| 142 | 142 | ||
| 143 | bool is_abandoned = false; | ||
| 144 | |||
| 143 | /// Event that handles screen composition. | 145 | /// Event that handles screen composition. |
| 144 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; | 146 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; |
| 145 | std::shared_ptr<Core::Timing::EventType> single_composition_event; | 147 | 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 { | |||
| 19 | Busy = -16, | 19 | Busy = -16, |
| 20 | NoInit = -19, | 20 | NoInit = -19, |
| 21 | BadValue = -22, | 21 | BadValue = -22, |
| 22 | InvalidOperation = -37, | 22 | InvalidOperation = -38, |
| 23 | BufferNeedsReallocation = 1, | 23 | BufferNeedsReallocation = 1, |
| 24 | ReleaseAllBuffers = 2, | 24 | ReleaseAllBuffers = 2, |
| 25 | }; | 25 | }; |
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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/nvdrv/core/nvmap.h" | ||
| 5 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | ||
| 6 | |||
| 7 | namespace Service::android { | ||
| 8 | |||
| 9 | static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) { | ||
| 10 | if (buffer) { | ||
| 11 | return *buffer; | ||
| 12 | } else { | ||
| 13 | return {}; | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) | ||
| 18 | : NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {} | ||
| 19 | |||
| 20 | GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap, | ||
| 21 | std::shared_ptr<NvGraphicBuffer> buffer) | ||
| 22 | : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) { | ||
| 23 | if (this->BufferId() > 0) { | ||
| 24 | m_nvmap->DuplicateHandle(this->BufferId(), true); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | GraphicBuffer::~GraphicBuffer() { | ||
| 29 | if (m_nvmap != nullptr && this->BufferId() > 0) { | ||
| 30 | m_nvmap->FreeHandle(this->BufferId(), true); | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | } // 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 @@ | |||
| 6 | 6 | ||
| 7 | #pragma once | 7 | #pragma once |
| 8 | 8 | ||
| 9 | #include <memory> | ||
| 10 | |||
| 9 | #include "common/common_funcs.h" | 11 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 11 | #include "core/hle/service/nvnflinger/pixel_format.h" | 13 | #include "core/hle/service/nvnflinger/pixel_format.h" |
| 12 | 14 | ||
| 15 | namespace Service::Nvidia::NvCore { | ||
| 16 | class NvMap; | ||
| 17 | } // namespace Service::Nvidia::NvCore | ||
| 18 | |||
| 13 | namespace Service::android { | 19 | namespace Service::android { |
| 14 | 20 | ||
| 15 | struct GraphicBuffer final { | 21 | struct NvGraphicBuffer { |
| 16 | constexpr GraphicBuffer() = default; | 22 | constexpr NvGraphicBuffer() = default; |
| 17 | 23 | ||
| 18 | constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) | 24 | constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) |
| 19 | : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, | 25 | : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, |
| 20 | usage{static_cast<s32>(usage_)} {} | 26 | usage{static_cast<s32>(usage_)} {} |
| 21 | 27 | ||
| @@ -93,6 +99,17 @@ struct GraphicBuffer final { | |||
| 93 | u32 offset{}; | 99 | u32 offset{}; |
| 94 | INSERT_PADDING_WORDS(60); | 100 | INSERT_PADDING_WORDS(60); |
| 95 | }; | 101 | }; |
| 96 | static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); | 102 | static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size"); |
| 103 | |||
| 104 | class GraphicBuffer final : public NvGraphicBuffer { | ||
| 105 | public: | ||
| 106 | explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage); | ||
| 107 | explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap, | ||
| 108 | std::shared_ptr<NvGraphicBuffer> buffer); | ||
| 109 | ~GraphicBuffer(); | ||
| 110 | |||
| 111 | private: | ||
| 112 | Service::Nvidia::NvCore::NvMap* m_nvmap{}; | ||
| 113 | }; | ||
| 97 | 114 | ||
| 98 | } // namespace Service::android | 115 | } // 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 | |||
| 35 | return { | 35 | return { |
| 36 | buffer_queue_core, | 36 | buffer_queue_core, |
| 37 | std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), | 37 | std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), |
| 38 | std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)}; | 38 | std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | Display::Display(u64 id, std::string name_, | 41 | 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, | |||
| 559 | const IR::Value& offset, const IR::Value& lod_clamp) { | 559 | const IR::Value& offset, const IR::Value& lod_clamp) { |
| 560 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | 560 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 561 | ScopedRegister dpdx, dpdy, coords; | 561 | ScopedRegister dpdx, dpdy, coords; |
| 562 | const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; | 562 | const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp}; |
| 563 | if (multi_component) { | 563 | if (multi_component) { |
| 564 | // Allocate this early to avoid aliasing other registers | 564 | // Allocate this early to avoid aliasing other registers |
| 565 | dpdx = ScopedRegister{ctx.reg_alloc}; | 565 | dpdx = ScopedRegister{ctx.reg_alloc}; |
| 566 | dpdy = ScopedRegister{ctx.reg_alloc}; | 566 | dpdy = ScopedRegister{ctx.reg_alloc}; |
| 567 | if (info.num_derivates >= 3) { | 567 | if (info.num_derivatives >= 3) { |
| 568 | coords = ScopedRegister{ctx.reg_alloc}; | 568 | coords = ScopedRegister{ctx.reg_alloc}; |
| 569 | } | 569 | } |
| 570 | } | 570 | } |
| @@ -584,7 +584,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | |||
| 584 | dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec, | 584 | dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec, |
| 585 | dpdy.reg, derivatives_vec); | 585 | dpdy.reg, derivatives_vec); |
| 586 | Register final_coord; | 586 | Register final_coord; |
| 587 | if (info.num_derivates >= 3) { | 587 | if (info.num_derivatives >= 3) { |
| 588 | ctx.Add("MOV.F {}.z,{}.x;" | 588 | ctx.Add("MOV.F {}.z,{}.x;" |
| 589 | "MOV.F {}.z,{}.y;", | 589 | "MOV.F {}.z,{}.y;", |
| 590 | dpdx.reg, coord_vec, dpdy.reg, coord_vec); | 590 | 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, | |||
| 548 | if (sparse_inst) { | 548 | if (sparse_inst) { |
| 549 | throw NotImplementedException("EmitImageGradient Sparse"); | 549 | throw NotImplementedException("EmitImageGradient Sparse"); |
| 550 | } | 550 | } |
| 551 | if (!offset.IsEmpty() && info.num_derivates <= 2) { | 551 | if (!offset.IsEmpty() && info.num_derivatives <= 2) { |
| 552 | throw NotImplementedException("EmitImageGradient offset"); | 552 | throw NotImplementedException("EmitImageGradient offset"); |
| 553 | } | 553 | } |
| 554 | const auto texture{Texture(ctx, info, index)}; | 554 | const auto texture{Texture(ctx, info, index)}; |
| 555 | const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 555 | const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; |
| 556 | const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; | 556 | const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp}; |
| 557 | const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)}; | 557 | const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)}; |
| 558 | if (multi_component) { | 558 | if (multi_component) { |
| 559 | if (info.num_derivates >= 3) { | 559 | if (info.num_derivatives >= 3) { |
| 560 | const auto offset_vec{ctx.var_alloc.Consume(offset)}; | 560 | const auto offset_vec{ctx.var_alloc.Consume(offset)}; |
| 561 | ctx.Add("{}=textureGrad({},{},vec3({}.xz, {}.x),vec3({}.yw, {}.y));", texel, texture, | 561 | ctx.Add("{}=textureGrad({},{},vec3({}.xz, {}.x),vec3({}.yw, {}.y));", texel, texture, |
| 562 | coords, derivatives_vec, offset_vec, derivatives_vec, offset_vec); | 562 | 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: | |||
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates, u32 num_derivates, | 70 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, |
| 71 | Id offset, Id lod_clamp) { | 71 | u32 num_derivatives, Id offset, Id lod_clamp) { |
| 72 | if (!Sirit::ValidId(derivates)) { | 72 | if (!Sirit::ValidId(derivatives)) { |
| 73 | throw LogicError("Derivates must be present"); | 73 | throw LogicError("Derivatives must be present"); |
| 74 | } | 74 | } |
| 75 | boost::container::static_vector<Id, 3> deriv_x_accum; | 75 | boost::container::static_vector<Id, 3> deriv_x_accum; |
| 76 | boost::container::static_vector<Id, 3> deriv_y_accum; | 76 | boost::container::static_vector<Id, 3> deriv_y_accum; |
| 77 | for (u32 i = 0; i < num_derivates; ++i) { | 77 | for (u32 i = 0; i < num_derivatives; ++i) { |
| 78 | deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2)); | 78 | deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2)); |
| 79 | deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2 + 1)); | 79 | deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2 + 1)); |
| 80 | } | 80 | } |
| 81 | const Id derivates_X{ctx.OpCompositeConstruct( | 81 | const Id derivatives_X{ctx.OpCompositeConstruct( |
| 82 | ctx.F32[num_derivates], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; | 82 | ctx.F32[num_derivatives], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; |
| 83 | const Id derivates_Y{ctx.OpCompositeConstruct( | 83 | const Id derivatives_Y{ctx.OpCompositeConstruct( |
| 84 | ctx.F32[num_derivates], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; | 84 | ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; |
| 85 | Add(spv::ImageOperandsMask::Grad, derivates_X, derivates_Y); | 85 | Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); |
| 86 | if (Sirit::ValidId(offset)) { | 86 | if (Sirit::ValidId(offset)) { |
| 87 | Add(spv::ImageOperandsMask::Offset, offset); | 87 | Add(spv::ImageOperandsMask::Offset, offset); |
| 88 | } | 88 | } |
| @@ -91,26 +91,26 @@ public: | |||
| 91 | } | 91 | } |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates_1, Id derivates_2, | 94 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, |
| 95 | Id offset, Id lod_clamp) { | 95 | Id offset, Id lod_clamp) { |
| 96 | if (!Sirit::ValidId(derivates_1) || !Sirit::ValidId(derivates_2)) { | 96 | if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { |
| 97 | throw LogicError("Derivates must be present"); | 97 | throw LogicError("Derivatives must be present"); |
| 98 | } | 98 | } |
| 99 | boost::container::static_vector<Id, 3> deriv_1_accum{ | 99 | boost::container::static_vector<Id, 3> deriv_1_accum{ |
| 100 | ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 0), | 100 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 0), |
| 101 | ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 2), | 101 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 2), |
| 102 | ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 0), | 102 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 0), |
| 103 | }; | 103 | }; |
| 104 | boost::container::static_vector<Id, 3> deriv_2_accum{ | 104 | boost::container::static_vector<Id, 3> deriv_2_accum{ |
| 105 | ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 1), | 105 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 1), |
| 106 | ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 3), | 106 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 3), |
| 107 | ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 1), | 107 | ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 1), |
| 108 | }; | 108 | }; |
| 109 | const Id derivates_id1{ctx.OpCompositeConstruct( | 109 | const Id derivatives_id1{ctx.OpCompositeConstruct( |
| 110 | ctx.F32[3], std::span{deriv_1_accum.data(), deriv_1_accum.size()})}; | 110 | ctx.F32[3], std::span{deriv_1_accum.data(), deriv_1_accum.size()})}; |
| 111 | const Id derivates_id2{ctx.OpCompositeConstruct( | 111 | const Id derivatives_id2{ctx.OpCompositeConstruct( |
| 112 | ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; | 112 | ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; |
| 113 | Add(spv::ImageOperandsMask::Grad, derivates_id1, derivates_id2); | 113 | Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); |
| 114 | if (Sirit::ValidId(offset)) { | 114 | if (Sirit::ValidId(offset)) { |
| 115 | Add(spv::ImageOperandsMask::Offset, offset); | 115 | Add(spv::ImageOperandsMask::Offset, offset); |
| 116 | } | 116 | } |
| @@ -548,12 +548,12 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | |||
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 550 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 551 | Id derivates, Id offset, Id lod_clamp) { | 551 | Id derivatives, Id offset, Id lod_clamp) { |
| 552 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 552 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 553 | const auto operands = | 553 | const auto operands = |
| 554 | info.num_derivates == 3 | 554 | info.num_derivatives == 3 |
| 555 | ? ImageOperands(ctx, info.has_lod_clamp != 0, derivates, offset, {}, lod_clamp) | 555 | ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp) |
| 556 | : ImageOperands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, offset, | 556 | : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, |
| 557 | lod_clamp); | 557 | lod_clamp); |
| 558 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 558 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| 559 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], | 559 | &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 | |||
| 543 | const IR::Value& skip_mips); | 543 | const IR::Value& skip_mips); |
| 544 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 544 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 545 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 545 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 546 | Id derivates, Id offset, Id lod_clamp); | 546 | Id derivatives, Id offset, Id lod_clamp); |
| 547 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 547 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 548 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); | 548 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); |
| 549 | Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); | 549 | 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 | |||
| 1864 | return Inst(op, Flags{info}, handle, coords); | 1864 | return Inst(op, Flags{info}, handle, coords); |
| 1865 | } | 1865 | } |
| 1866 | 1866 | ||
| 1867 | Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivates, | 1867 | Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivatives, |
| 1868 | const Value& offset, const F32& lod_clamp, TextureInstInfo info) { | 1868 | const Value& offset, const F32& lod_clamp, TextureInstInfo info) { |
| 1869 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageGradient | 1869 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageGradient |
| 1870 | : Opcode::BindlessImageGradient}; | 1870 | : Opcode::BindlessImageGradient}; |
| 1871 | return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp); | 1871 | return Inst(op, Flags{info}, handle, coords, derivatives, offset, lod_clamp); |
| 1872 | } | 1872 | } |
| 1873 | 1873 | ||
| 1874 | Value IREmitter::ImageRead(const Value& handle, const Value& coords, TextureInstInfo info) { | 1874 | 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: | |||
| 335 | [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, | 335 | [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, |
| 336 | const U32& lod, const U32& multisampling, TextureInstInfo info); | 336 | const U32& lod, const U32& multisampling, TextureInstInfo info); |
| 337 | [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, | 337 | [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, |
| 338 | const Value& derivates, const Value& offset, | 338 | const Value& derivatives, const Value& offset, |
| 339 | const F32& lod_clamp, TextureInstInfo info); | 339 | const F32& lod_clamp, TextureInstInfo info); |
| 340 | [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); | 340 | [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); |
| 341 | void ImageWrite(const Value& handle, const Value& coords, const Value& color, | 341 | 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 { | |||
| 40 | BitField<21, 1, u32> has_lod_clamp; | 40 | BitField<21, 1, u32> has_lod_clamp; |
| 41 | BitField<22, 1, u32> relaxed_precision; | 41 | BitField<22, 1, u32> relaxed_precision; |
| 42 | BitField<23, 2, u32> gather_component; | 42 | BitField<23, 2, u32> gather_component; |
| 43 | BitField<25, 2, u32> num_derivates; | 43 | BitField<25, 2, u32> num_derivatives; |
| 44 | BitField<27, 3, ImageFormat> image_format; | 44 | BitField<27, 3, ImageFormat> image_format; |
| 45 | BitField<30, 1, u32> ndv_is_active; | 45 | BitField<30, 1, u32> ndv_is_active; |
| 46 | }; | 46 | }; |
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) { | |||
| 59 | BitField<51, 3, IR::Pred> sparse_pred; | 59 | BitField<51, 3, IR::Pred> sparse_pred; |
| 60 | BitField<0, 8, IR::Reg> dest_reg; | 60 | BitField<0, 8, IR::Reg> dest_reg; |
| 61 | BitField<8, 8, IR::Reg> coord_reg; | 61 | BitField<8, 8, IR::Reg> coord_reg; |
| 62 | BitField<20, 8, IR::Reg> derivate_reg; | 62 | BitField<20, 8, IR::Reg> derivative_reg; |
| 63 | BitField<28, 3, TextureType> type; | 63 | BitField<28, 3, TextureType> type; |
| 64 | BitField<31, 4, u64> mask; | 64 | BitField<31, 4, u64> mask; |
| 65 | BitField<36, 13, u64> cbuf_offset; | 65 | BitField<36, 13, u64> cbuf_offset; |
| @@ -71,7 +71,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | IR::Value coords; | 73 | IR::Value coords; |
| 74 | u32 num_derivates{}; | 74 | u32 num_derivatives{}; |
| 75 | IR::Reg base_reg{txd.coord_reg}; | 75 | IR::Reg base_reg{txd.coord_reg}; |
| 76 | IR::Reg last_reg; | 76 | IR::Reg last_reg; |
| 77 | IR::Value handle; | 77 | IR::Value handle; |
| @@ -90,42 +90,42 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 90 | switch (txd.type) { | 90 | switch (txd.type) { |
| 91 | case TextureType::_1D: { | 91 | case TextureType::_1D: { |
| 92 | coords = v.F(base_reg); | 92 | coords = v.F(base_reg); |
| 93 | num_derivates = 1; | 93 | num_derivatives = 1; |
| 94 | last_reg = base_reg + 1; | 94 | last_reg = base_reg + 1; |
| 95 | break; | 95 | break; |
| 96 | } | 96 | } |
| 97 | case TextureType::ARRAY_1D: { | 97 | case TextureType::ARRAY_1D: { |
| 98 | last_reg = base_reg + 1; | 98 | last_reg = base_reg + 1; |
| 99 | coords = v.ir.CompositeConstruct(v.F(base_reg), read_array()); | 99 | coords = v.ir.CompositeConstruct(v.F(base_reg), read_array()); |
| 100 | num_derivates = 1; | 100 | num_derivatives = 1; |
| 101 | break; | 101 | break; |
| 102 | } | 102 | } |
| 103 | case TextureType::_2D: { | 103 | case TextureType::_2D: { |
| 104 | last_reg = base_reg + 2; | 104 | last_reg = base_reg + 2; |
| 105 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1)); | 105 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1)); |
| 106 | num_derivates = 2; | 106 | num_derivatives = 2; |
| 107 | break; | 107 | break; |
| 108 | } | 108 | } |
| 109 | case TextureType::ARRAY_2D: { | 109 | case TextureType::ARRAY_2D: { |
| 110 | last_reg = base_reg + 2; | 110 | last_reg = base_reg + 2; |
| 111 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1), read_array()); | 111 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1), read_array()); |
| 112 | num_derivates = 2; | 112 | num_derivatives = 2; |
| 113 | break; | 113 | break; |
| 114 | } | 114 | } |
| 115 | default: | 115 | default: |
| 116 | throw NotImplementedException("Invalid texture type"); | 116 | throw NotImplementedException("Invalid texture type"); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | const IR::Reg derivate_reg{txd.derivate_reg}; | 119 | const IR::Reg derivative_reg{txd.derivative_reg}; |
| 120 | IR::Value derivates; | 120 | IR::Value derivatives; |
| 121 | switch (num_derivates) { | 121 | switch (num_derivatives) { |
| 122 | case 1: { | 122 | case 1: { |
| 123 | derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1)); | 123 | derivatives = v.ir.CompositeConstruct(v.F(derivative_reg), v.F(derivative_reg + 1)); |
| 124 | break; | 124 | break; |
| 125 | } | 125 | } |
| 126 | case 2: { | 126 | case 2: { |
| 127 | derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1), | 127 | derivatives = v.ir.CompositeConstruct(v.F(derivative_reg), v.F(derivative_reg + 1), |
| 128 | v.F(derivate_reg + 2), v.F(derivate_reg + 3)); | 128 | v.F(derivative_reg + 2), v.F(derivative_reg + 3)); |
| 129 | break; | 129 | break; |
| 130 | } | 130 | } |
| 131 | default: | 131 | default: |
| @@ -150,9 +150,10 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 150 | 150 | ||
| 151 | IR::TextureInstInfo info{}; | 151 | IR::TextureInstInfo info{}; |
| 152 | info.type.Assign(GetType(txd.type)); | 152 | info.type.Assign(GetType(txd.type)); |
| 153 | info.num_derivates.Assign(num_derivates); | 153 | info.num_derivatives.Assign(num_derivatives); |
| 154 | info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); | 154 | info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); |
| 155 | const IR::Value sample{v.ir.ImageGradient(handle, coords, derivates, offset, lod_clamp, info)}; | 155 | const IR::Value sample{ |
| 156 | v.ir.ImageGradient(handle, coords, derivatives, offset, lod_clamp, info)}; | ||
| 156 | 157 | ||
| 157 | IR::Reg dest_reg{txd.dest_reg}; | 158 | IR::Reg dest_reg{txd.dest_reg}; |
| 158 | for (size_t element = 0; element < 4; ++element) { | 159 | 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) { | |||
| 428 | } | 428 | } |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | bool FoldDerivateYFromCorrection(IR::Inst& inst) { | 431 | bool FoldDerivativeYFromCorrection(IR::Inst& inst) { |
| 432 | const IR::Value lhs_value{inst.Arg(0)}; | 432 | const IR::Value lhs_value{inst.Arg(0)}; |
| 433 | const IR::Value rhs_value{inst.Arg(1)}; | 433 | const IR::Value rhs_value{inst.Arg(1)}; |
| 434 | IR::Inst* const lhs_op{lhs_value.InstRecursive()}; | 434 | IR::Inst* const lhs_op{lhs_value.InstRecursive()}; |
| @@ -464,7 +464,7 @@ void FoldFPMul32(IR::Inst& inst) { | |||
| 464 | if (lhs_value.IsImmediate() || rhs_value.IsImmediate()) { | 464 | if (lhs_value.IsImmediate() || rhs_value.IsImmediate()) { |
| 465 | return; | 465 | return; |
| 466 | } | 466 | } |
| 467 | if (FoldDerivateYFromCorrection(inst)) { | 467 | if (FoldDerivativeYFromCorrection(inst)) { |
| 468 | return; | 468 | return; |
| 469 | } | 469 | } |
| 470 | IR::Inst* const lhs_op{lhs_value.InstRecursive()}; | 470 | IR::Inst* const lhs_op{lhs_value.InstRecursive()}; |
| @@ -699,7 +699,7 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) { | |||
| 699 | } | 699 | } |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | bool FindGradient3DDerivates(std::array<IR::Value, 3>& results, IR::Value coord) { | 702 | bool FindGradient3DDerivatives(std::array<IR::Value, 3>& results, IR::Value coord) { |
| 703 | if (coord.IsImmediate()) { | 703 | if (coord.IsImmediate()) { |
| 704 | return false; | 704 | return false; |
| 705 | } | 705 | } |
| @@ -834,7 +834,7 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { | |||
| 834 | IR::Inst* const inst2 = coords.InstRecursive(); | 834 | IR::Inst* const inst2 = coords.InstRecursive(); |
| 835 | std::array<std::array<IR::Value, 3>, 3> results_matrix; | 835 | std::array<std::array<IR::Value, 3>, 3> results_matrix; |
| 836 | for (size_t i = 0; i < 3; i++) { | 836 | for (size_t i = 0; i < 3; i++) { |
| 837 | if (!FindGradient3DDerivates(results_matrix[i], inst2->Arg(i).Resolve())) { | 837 | if (!FindGradient3DDerivatives(results_matrix[i], inst2->Arg(i).Resolve())) { |
| 838 | return; | 838 | return; |
| 839 | } | 839 | } |
| 840 | } | 840 | } |
| @@ -852,7 +852,7 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { | |||
| 852 | IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2], | 852 | IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2], |
| 853 | results_matrix[1][1], results_matrix[1][2]); | 853 | results_matrix[1][1], results_matrix[1][2]); |
| 854 | IR::Value derivatives_2 = ir.CompositeConstruct(results_matrix[2][1], results_matrix[2][2]); | 854 | IR::Value derivatives_2 = ir.CompositeConstruct(results_matrix[2][1], results_matrix[2][2]); |
| 855 | info.num_derivates.Assign(3); | 855 | info.num_derivatives.Assign(3); |
| 856 | IR::Value new_gradient_instruction = | 856 | IR::Value new_gradient_instruction = |
| 857 | ir.ImageGradient(handle, new_coords, derivatives_1, derivatives_2, lod_clamp, info); | 857 | ir.ImageGradient(handle, new_coords, derivatives_1, derivatives_2, lod_clamp, info); |
| 858 | IR::Inst* const new_inst = new_gradient_instruction.InstRecursive(); | 858 | 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() { | |||
| 1192 | .size = static_cast<u32>(size), | 1192 | .size = static_cast<u32>(size), |
| 1193 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), | 1193 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), |
| 1194 | }; | 1194 | }; |
| 1195 | VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64); | ||
| 1196 | VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64); | ||
| 1197 | IntervalType interval{cpu_addr_start, cpu_addr_end}; | ||
| 1198 | ClearDownload(interval); | ||
| 1199 | common_ranges.subtract(interval); | ||
| 1200 | }; | 1195 | }; |
| 1201 | if (current_draw_indirect->include_count) { | 1196 | if (current_draw_indirect->include_count) { |
| 1202 | update(current_draw_indirect->count_start_address, sizeof(u32), | 1197 | 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() { | |||
| 72 | UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); | 72 | UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); |
| 73 | 73 | ||
| 74 | const auto& args = regs.pixels_from_memory; | 74 | const auto& args = regs.pixels_from_memory; |
| 75 | constexpr s64 null_derivate = 1ULL << 32; | 75 | constexpr s64 null_derivative = 1ULL << 32; |
| 76 | Surface src = regs.src; | 76 | Surface src = regs.src; |
| 77 | const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format)); | 77 | const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format)); |
| 78 | const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 && | 78 | const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 && |
| @@ -89,7 +89,7 @@ void Fermi2D::Blit() { | |||
| 89 | .operation = regs.operation, | 89 | .operation = regs.operation, |
| 90 | .filter = args.sample_mode.filter, | 90 | .filter = args.sample_mode.filter, |
| 91 | .must_accelerate = | 91 | .must_accelerate = |
| 92 | args.du_dx != null_derivate || args.dv_dy != null_derivate || delegate_to_gpu, | 92 | args.du_dx != null_derivative || args.dv_dy != null_derivative || delegate_to_gpu, |
| 93 | .dst_x0 = args.dst_x0, | 93 | .dst_x0 = args.dst_x0, |
| 94 | .dst_y0 = args.dst_y0, | 94 | .dst_y0 = args.dst_y0, |
| 95 | .dst_x1 = args.dst_x0 + args.dst_width, | 95 | .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() { | |||
| 268 | std::numeric_limits<u32>::max()}; | 268 | std::numeric_limits<u32>::max()}; |
| 269 | const size_t byte_size = regs.index_buffer.FormatSizeInBytes(); | 269 | const size_t byte_size = regs.index_buffer.FormatSizeInBytes(); |
| 270 | const size_t log2_byte_size = Common::Log2Ceil64(byte_size); | 270 | const size_t log2_byte_size = Common::Log2Ceil64(byte_size); |
| 271 | const size_t cap{GetMaxCurrentVertices() * 3 * byte_size}; | 271 | const size_t cap{GetMaxCurrentVertices() * 4 * byte_size}; |
| 272 | const size_t lower_cap = | 272 | const size_t lower_cap = |
| 273 | std::min<size_t>(static_cast<size_t>(end_address - start_address), cap); | 273 | std::min<size_t>(static_cast<size_t>(end_address - start_address), cap); |
| 274 | return std::min<size_t>( | 274 | 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) { | |||
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { | 561 | void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { |
| 562 | glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), GL_SEPARATE_ATTRIBS); | 562 | const GLenum buffer_mode = |
| 563 | num_xfb_buffers_active == 1 ? GL_INTERLEAVED_ATTRIBS : GL_SEPARATE_ATTRIBS; | ||
| 564 | glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), buffer_mode); | ||
| 563 | } | 565 | } |
| 564 | 566 | ||
| 565 | void GraphicsPipeline::GenerateTransformFeedbackState() { | 567 | void GraphicsPipeline::GenerateTransformFeedbackState() { |
| @@ -567,12 +569,14 @@ void GraphicsPipeline::GenerateTransformFeedbackState() { | |||
| 567 | // when this is required. | 569 | // when this is required. |
| 568 | GLint* cursor{xfb_attribs.data()}; | 570 | GLint* cursor{xfb_attribs.data()}; |
| 569 | 571 | ||
| 572 | num_xfb_buffers_active = 0; | ||
| 570 | for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { | 573 | for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { |
| 571 | const auto& layout = key.xfb_state.layouts[feedback]; | 574 | const auto& layout = key.xfb_state.layouts[feedback]; |
| 572 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); | 575 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); |
| 573 | if (layout.varying_count == 0) { | 576 | if (layout.varying_count == 0) { |
| 574 | continue; | 577 | continue; |
| 575 | } | 578 | } |
| 579 | num_xfb_buffers_active++; | ||
| 576 | 580 | ||
| 577 | const auto& locations = key.xfb_state.varyings[feedback]; | 581 | const auto& locations = key.xfb_state.varyings[feedback]; |
| 578 | std::optional<u32> current_index; | 582 | 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: | |||
| 154 | 154 | ||
| 155 | static constexpr std::size_t XFB_ENTRY_STRIDE = 3; | 155 | static constexpr std::size_t XFB_ENTRY_STRIDE = 3; |
| 156 | GLsizei num_xfb_attribs{}; | 156 | GLsizei num_xfb_attribs{}; |
| 157 | u32 num_xfb_buffers_active{}; | ||
| 157 | std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{}; | 158 | std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{}; |
| 158 | 159 | ||
| 159 | std::mutex built_mutex; | 160 | std::mutex built_mutex; |