Compare commits

...

4 commits

Author SHA1 Message Date
yuzubot cc7b11f0c7 "Merge Tagged PR 11912" 2023-11-15 13:02:53 +00:00
yuzubot a9f6bd2777 "Merge Tagged PR 11917" 2023-11-15 13:02:52 +00:00
yuzubot ce83d961f1 "Merge Tagged PR 11995" 2023-11-15 13:02:52 +00:00
yuzubot e3324fbfaa "Merge Tagged PR 12007" 2023-11-15 13:02:51 +00:00
37 changed files with 545 additions and 273 deletions

View file

@ -6,10 +6,11 @@
namespace Settings { namespace Settings {
namespace NativeButton { namespace NativeButton {
const std::array<const char*, NumButtons> mapping = {{ const std::array<const char*, NumButtons> mapping = {{
"button_a", "button_b", "button_x", "button_y", "button_lstick", "button_a", "button_b", "button_x", "button_y", "button_lstick",
"button_rstick", "button_l", "button_r", "button_zl", "button_zr", "button_rstick", "button_l", "button_r", "button_zl", "button_zr",
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright", "button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
"button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot", "button_ddown", "button_slleft", "button_srleft", "button_home", "button_screenshot",
"button_slright", "button_srright",
}}; }};
} }

View file

@ -29,12 +29,15 @@ enum Values : int {
DRight, DRight,
DDown, DDown,
SL, SLLeft,
SR, SRLeft,
Home, Home,
Screenshot, Screenshot,
SLRight,
SRRight,
NumButtons, NumButtons,
}; };

View file

@ -715,6 +715,7 @@ add_library(core STATIC
hle/service/nvnflinger/producer_listener.h hle/service/nvnflinger/producer_listener.h
hle/service/nvnflinger/status.h hle/service/nvnflinger/status.h
hle/service/nvnflinger/ui/fence.h hle/service/nvnflinger/ui/fence.h
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h hle/service/nvnflinger/window.h
hle/service/olsc/olsc.cpp hle/service/olsc/olsc.cpp

View file

@ -243,10 +243,12 @@ void EmulatedController::LoadTASParams() {
tas_button_params[Settings::NativeButton::DUp].Set("button", 13); tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
tas_button_params[Settings::NativeButton::DRight].Set("button", 14); tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
tas_button_params[Settings::NativeButton::DDown].Set("button", 15); tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
tas_button_params[Settings::NativeButton::SL].Set("button", 16); tas_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
tas_button_params[Settings::NativeButton::SR].Set("button", 17); tas_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
tas_button_params[Settings::NativeButton::Home].Set("button", 18); tas_button_params[Settings::NativeButton::Home].Set("button", 18);
tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
tas_button_params[Settings::NativeButton::SLRight].Set("button", 20);
tas_button_params[Settings::NativeButton::SRRight].Set("button", 21);
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
@ -296,10 +298,12 @@ void EmulatedController::LoadVirtualGamepadParams() {
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13); virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14); virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15); virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
virtual_button_params[Settings::NativeButton::SL].Set("button", 16); virtual_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
virtual_button_params[Settings::NativeButton::SR].Set("button", 17); virtual_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
virtual_button_params[Settings::NativeButton::Home].Set("button", 18); virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19); virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
virtual_button_params[Settings::NativeButton::SLRight].Set("button", 20);
virtual_button_params[Settings::NativeButton::SRRight].Set("button", 21);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
@ -867,12 +871,16 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
controller.npad_button_state.down.Assign(current_status.value); controller.npad_button_state.down.Assign(current_status.value);
controller.debug_pad_button_state.d_down.Assign(current_status.value); controller.debug_pad_button_state.d_down.Assign(current_status.value);
break; break;
case Settings::NativeButton::SL: case Settings::NativeButton::SLLeft:
controller.npad_button_state.left_sl.Assign(current_status.value); controller.npad_button_state.left_sl.Assign(current_status.value);
break;
case Settings::NativeButton::SLRight:
controller.npad_button_state.right_sl.Assign(current_status.value); controller.npad_button_state.right_sl.Assign(current_status.value);
break; break;
case Settings::NativeButton::SR: case Settings::NativeButton::SRLeft:
controller.npad_button_state.left_sr.Assign(current_status.value); controller.npad_button_state.left_sr.Assign(current_status.value);
break;
case Settings::NativeButton::SRRight:
controller.npad_button_state.right_sr.Assign(current_status.value); controller.npad_button_state.right_sr.Assign(current_status.value);
break; break;
case Settings::NativeButton::Home: case Settings::NativeButton::Home:
@ -1890,12 +1898,16 @@ NpadButton EmulatedController::GetTurboButtonMask() const {
case Settings::NativeButton::DDown: case Settings::NativeButton::DDown:
button_mask.down.Assign(1); button_mask.down.Assign(1);
break; break;
case Settings::NativeButton::SL: case Settings::NativeButton::SLLeft:
button_mask.left_sl.Assign(1); button_mask.left_sl.Assign(1);
break;
case Settings::NativeButton::SLRight:
button_mask.right_sl.Assign(1); button_mask.right_sl.Assign(1);
break; break;
case Settings::NativeButton::SR: case Settings::NativeButton::SRLeft:
button_mask.left_sr.Assign(1); button_mask.left_sr.Assign(1);
break;
case Settings::NativeButton::SRRight:
button_mask.right_sr.Assign(1); button_mask.right_sr.Assign(1);
break; break;
default: default:

View file

@ -457,12 +457,14 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
pad_entry.l_stick = stick_state.left; pad_entry.l_stick = stick_state.left;
} }
if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) { if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
} }
if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) { if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
} }

View file

@ -15,7 +15,7 @@
namespace Service::android { namespace Service::android {
struct GraphicBuffer; class GraphicBuffer;
class BufferItem final { class BufferItem final {
public: public:

View file

@ -5,7 +5,6 @@
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" #include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h"
@ -14,9 +13,8 @@
namespace Service::android { namespace Service::android {
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
Service::Nvidia::NvCore::NvMap& nvmap_) : core{std::move(core_)}, slots{core->slots} {}
: core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
BufferQueueConsumer::~BufferQueueConsumer() = default; BufferQueueConsumer::~BufferQueueConsumer() = default;
@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
slots[slot].buffer_state = BufferState::Free; slots[slot].buffer_state = BufferState::Free;
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
listener = core->connected_producer_listener; listener = core->connected_producer_listener;
LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
@ -175,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
return Status::NoError; return Status::NoError;
} }
Status BufferQueueConsumer::Disconnect() {
LOG_DEBUG(Service_Nvnflinger, "called");
std::scoped_lock lock{core->mutex};
if (core->consumer_listener == nullptr) {
LOG_ERROR(Service_Nvnflinger, "no consumer is connected");
return Status::BadValue;
}
core->is_abandoned = true;
core->consumer_listener = nullptr;
core->queue.clear();
core->FreeAllBuffersLocked();
core->SignalDequeueCondition();
return Status::NoError;
}
Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
if (out_slot_mask == nullptr) { if (out_slot_mask == nullptr) {
LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr"); LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr");

View file

@ -13,10 +13,6 @@
#include "core/hle/service/nvnflinger/buffer_queue_defs.h" #include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/status.h" #include "core/hle/service/nvnflinger/status.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android { namespace Service::android {
class BufferItem; class BufferItem;
@ -25,19 +21,18 @@ class IConsumerListener;
class BufferQueueConsumer final { class BufferQueueConsumer final {
public: public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
Service::Nvidia::NvCore::NvMap& nvmap_);
~BufferQueueConsumer(); ~BufferQueueConsumer();
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
Status Disconnect();
Status GetReleasedBuffers(u64* out_slot_mask); Status GetReleasedBuffers(u64* out_slot_mask);
private: private:
std::shared_ptr<BufferQueueCore> core; std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots; BufferQueueDefs::SlotsType& slots;
Service::Nvidia::NvCore::NvMap& nvmap;
}; };
} // namespace Service::android } // namespace Service::android

View file

@ -14,24 +14,12 @@ BufferQueueCore::BufferQueueCore() = default;
BufferQueueCore::~BufferQueueCore() = default; BufferQueueCore::~BufferQueueCore() = default;
void BufferQueueCore::NotifyShutdown() {
std::scoped_lock lock{mutex};
is_shutting_down = true;
SignalDequeueCondition();
}
void BufferQueueCore::SignalDequeueCondition() { void BufferQueueCore::SignalDequeueCondition() {
dequeue_possible.store(true); dequeue_possible.store(true);
dequeue_condition.notify_all(); dequeue_condition.notify_all();
} }
bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) {
if (is_shutting_down) {
return false;
}
dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); });
dequeue_possible.store(false); dequeue_possible.store(false);

View file

@ -34,8 +34,6 @@ public:
BufferQueueCore(); BufferQueueCore();
~BufferQueueCore(); ~BufferQueueCore();
void NotifyShutdown();
private: private:
void SignalDequeueCondition(); void SignalDequeueCondition();
bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
@ -74,7 +72,6 @@ private:
u32 transform_hint{}; u32 transform_hint{};
bool is_allocating{}; bool is_allocating{};
mutable std::condition_variable_any is_allocating_condition; mutable std::condition_variable_any is_allocating_condition;
bool is_shutting_down{};
}; };
} // namespace Service::android } // namespace Service::android

View file

@ -13,7 +13,6 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/service/hle_ipc.h" #include "core/hle/service/hle_ipc.h"
#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h"
#include "core/hle/service/nvnflinger/consumer_listener.h" #include "core/hle/service/nvnflinger/consumer_listener.h"
@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
item.is_droppable = core->dequeue_buffer_cannot_block || async; item.is_droppable = core->dequeue_buffer_cannot_block || async;
item.swap_interval = swap_interval; item.swap_interval = swap_interval;
nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true);
sticky_transform = sticky_transform_; sticky_transform = sticky_transform_;
if (core->queue.empty()) { if (core->queue.empty()) {
@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
return Status::NoError; return Status::NoError;
} }
// HACK: We are not Android. Remove handle for items in queue, and clear queue.
// Allows synchronous destruction of nvmap handles.
for (auto& item : core->queue) {
nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
}
core->queue.clear();
switch (api) { switch (api) {
case NativeWindowApi::Egl: case NativeWindowApi::Egl:
case NativeWindowApi::Cpu: case NativeWindowApi::Cpu:
case NativeWindowApi::Media: case NativeWindowApi::Media:
case NativeWindowApi::Camera: case NativeWindowApi::Camera:
if (core->connected_api == api) { if (core->connected_api == api) {
core->queue.clear();
core->FreeAllBuffersLocked(); core->FreeAllBuffersLocked();
core->connected_producer_listener = nullptr; core->connected_producer_listener = nullptr;
core->connected_api = NativeWindowApi::NoConnectedApi; core->connected_api = NativeWindowApi::NoConnectedApi;
@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
} }
Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
const std::shared_ptr<GraphicBuffer>& buffer) { const std::shared_ptr<NvGraphicBuffer>& buffer) {
LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); LOG_DEBUG(Service_Nvnflinger, "slot {}", slot);
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
slots[slot] = {}; slots[slot] = {};
slots[slot].fence = Fence::NoFence(); slots[slot].fence = Fence::NoFence();
slots[slot].graphic_buffer = buffer; slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer);
slots[slot].frame_number = 0; slots[slot].frame_number = 0;
// Most games preallocate a buffer and pass a valid buffer here. However, it is possible for // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for
@ -839,7 +830,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
} }
case TransactionId::SetPreallocatedBuffer: { case TransactionId::SetPreallocatedBuffer: {
const auto slot = parcel_in.Read<s32>(); const auto slot = parcel_in.Read<s32>();
const auto buffer = parcel_in.ReadObject<GraphicBuffer>(); const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>();
status = SetPreallocatedBuffer(slot, buffer); status = SetPreallocatedBuffer(slot, buffer);
break; break;
@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
status = RequestBuffer(slot, &buf); status = RequestBuffer(slot, &buf);
parcel_out.WriteFlattenedObject(buf); parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get());
break; break;
} }
case TransactionId::QueueBuffer: { case TransactionId::QueueBuffer: {

View file

@ -38,6 +38,7 @@ namespace Service::android {
class BufferQueueCore; class BufferQueueCore;
class IProducerListener; class IProducerListener;
struct NvGraphicBuffer;
class BufferQueueProducer final : public IBinder { class BufferQueueProducer final : public IBinder {
public: public:
@ -65,7 +66,7 @@ public:
bool producer_controlled_by_app, QueueBufferOutput* output); bool producer_controlled_by_app, QueueBufferOutput* output);
Status Disconnect(NativeWindowApi api); Status Disconnect(NativeWindowApi api);
Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer); Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer);
private: private:
BufferQueueProducer(const BufferQueueProducer&) = delete; BufferQueueProducer(const BufferQueueProducer&) = delete;

View file

@ -13,7 +13,7 @@
namespace Service::android { namespace Service::android {
struct GraphicBuffer; class GraphicBuffer;
enum class BufferState : u32 { enum class BufferState : u32 {
Free = 0, Free = 0,

View file

@ -27,6 +27,26 @@ void ConsumerBase::Connect(bool controlled_by_app) {
consumer->Connect(shared_from_this(), controlled_by_app); consumer->Connect(shared_from_this(), controlled_by_app);
} }
void ConsumerBase::Abandon() {
LOG_DEBUG(Service_Nvnflinger, "called");
std::scoped_lock lock{mutex};
if (!is_abandoned) {
this->AbandonLocked();
is_abandoned = true;
}
}
void ConsumerBase::AbandonLocked() {
for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
this->FreeBufferLocked(i);
}
// disconnect from the BufferQueue
consumer->Disconnect();
consumer = nullptr;
}
void ConsumerBase::FreeBufferLocked(s32 slot_index) { void ConsumerBase::FreeBufferLocked(s32 slot_index) {
LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index);

View file

@ -24,6 +24,7 @@ class BufferQueueConsumer;
class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> { class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
public: public:
void Connect(bool controlled_by_app); void Connect(bool controlled_by_app);
void Abandon();
protected: protected:
explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
@ -34,6 +35,7 @@ protected:
void OnBuffersReleased() override; void OnBuffersReleased() override;
void OnSidebandStreamChanged() override; void OnSidebandStreamChanged() override;
void AbandonLocked();
void FreeBufferLocked(s32 slot_index); void FreeBufferLocked(s32 slot_index);
Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when);
Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer);

View file

@ -166,7 +166,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
}(); }();
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
auto buffer = std::make_shared<android::GraphicBuffer>(); auto buffer = std::make_shared<android::NvGraphicBuffer>();
buffer->width = SharedBufferWidth; buffer->width = SharedBufferWidth;
buffer->height = SharedBufferHeight; buffer->height = SharedBufferHeight;
buffer->stride = SharedBufferBlockLinearStride; buffer->stride = SharedBufferBlockLinearStride;

View file

@ -47,7 +47,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {
vsync_signal.Wait(); vsync_signal.Wait();
const auto lock_guard = Lock(); const auto lock_guard = Lock();
Compose();
if (!is_abandoned) {
Compose();
}
} }
} }
@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() {
} }
ShutdownLayers(); ShutdownLayers();
vsync_thread = {};
if (nvdrv) { if (nvdrv) {
nvdrv->Close(disp_fd); nvdrv->Close(disp_fd);
@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() {
} }
void Nvnflinger::ShutdownLayers() { void Nvnflinger::ShutdownLayers() {
const auto lock_guard = Lock(); // Abandon consumers.
for (auto& display : displays) { {
for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { const auto lock_guard = Lock();
display.GetLayer(layer).Core().NotifyShutdown(); for (auto& display : displays) {
for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
display.GetLayer(layer).GetConsumer().Abandon();
}
} }
is_abandoned = true;
} }
// Join the vsync thread, if it exists.
vsync_thread = {};
} }
void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {

View file

@ -140,6 +140,8 @@ private:
s32 swap_interval = 1; s32 swap_interval = 1;
bool is_abandoned = false;
/// Event that handles screen composition. /// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> multi_composition_event; std::shared_ptr<Core::Timing::EventType> multi_composition_event;
std::shared_ptr<Core::Timing::EventType> single_composition_event; std::shared_ptr<Core::Timing::EventType> single_composition_event;

View file

@ -19,7 +19,7 @@ enum class Status : s32 {
Busy = -16, Busy = -16,
NoInit = -19, NoInit = -19,
BadValue = -22, BadValue = -22,
InvalidOperation = -37, InvalidOperation = -38,
BufferNeedsReallocation = 1, BufferNeedsReallocation = 1,
ReleaseAllBuffers = 2, ReleaseAllBuffers = 2,
}; };

View file

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
namespace Service::android {
static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) {
if (buffer) {
return *buffer;
} else {
return {};
}
}
GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {}
GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer)
: NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
if (this->BufferId() > 0) {
m_nvmap->DuplicateHandle(this->BufferId(), true);
}
}
GraphicBuffer::~GraphicBuffer() {
if (m_nvmap != nullptr && this->BufferId() > 0) {
m_nvmap->FreeHandle(this->BufferId(), true);
}
}
} // namespace Service::android

View file

@ -6,16 +6,22 @@
#pragma once #pragma once
#include <memory>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/nvnflinger/pixel_format.h" #include "core/hle/service/nvnflinger/pixel_format.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android { namespace Service::android {
struct GraphicBuffer final { struct NvGraphicBuffer {
constexpr GraphicBuffer() = default; constexpr NvGraphicBuffer() = default;
constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_},
usage{static_cast<s32>(usage_)} {} usage{static_cast<s32>(usage_)} {}
@ -93,6 +99,17 @@ struct GraphicBuffer final {
u32 offset{}; u32 offset{};
INSERT_PADDING_WORDS(60); INSERT_PADDING_WORDS(60);
}; };
static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size");
class GraphicBuffer final : public NvGraphicBuffer {
public:
explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage);
explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer);
~GraphicBuffer();
private:
Service::Nvidia::NvCore::NvMap* m_nvmap{};
};
} // namespace Service::android } // namespace Service::android

View file

@ -35,7 +35,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont
return { return {
buffer_queue_core, buffer_queue_core,
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)}; std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
} }
Display::Display(u64 id, std::string name_, Display::Display(u64 id, std::string name_,

View file

@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: 2015 Citra Emulator Project // SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <mutex>
#include <span> #include <span>
#include "common/assert.h" #include "common/assert.h"
@ -10,6 +12,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/page_table.h" #include "common/page_table.h"
#include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/core.h" #include "core/core.h"
@ -318,7 +321,7 @@ struct Memory::Impl {
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) { u8* const host_ptr) {
if constexpr (!UNSAFE) { if constexpr (!UNSAFE) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
} }
std::memcpy(host_ptr, src_buffer, copy_amount); std::memcpy(host_ptr, src_buffer, copy_amount);
}, },
@ -351,7 +354,7 @@ struct Memory::Impl {
}, },
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) { u8* const host_ptr) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
std::memset(host_ptr, 0, copy_amount); std::memset(host_ptr, 0, copy_amount);
}, },
[](const std::size_t copy_amount) {}); [](const std::size_t copy_amount) {});
@ -420,7 +423,7 @@ struct Memory::Impl {
const std::size_t block_size) { const std::size_t block_size) {
// dc cvac: Store to point of coherency // dc cvac: Store to point of coherency
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
@ -430,7 +433,7 @@ struct Memory::Impl {
const std::size_t block_size) { const std::size_t block_size) {
// dc civac: Store to point of coherency, and invalidate from cache // dc civac: Store to point of coherency, and invalidate from cache
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
@ -767,7 +770,18 @@ struct Memory::Impl {
} }
void HandleRasterizerWrite(VAddr address, size_t size) { void HandleRasterizerWrite(VAddr address, size_t size) {
const size_t core = system.GetCurrentHostThreadID(); constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
const size_t core = std::min(system.GetCurrentHostThreadID(),
sys_core); // any other calls threads go to syscore.
// Guard on sys_core;
if (core == sys_core) [[unlikely]] {
sys_core_guard.lock();
}
SCOPE_EXIT({
if (core == sys_core) [[unlikely]] {
sys_core_guard.unlock();
}
});
auto& current_area = rasterizer_write_areas[core]; auto& current_area = rasterizer_write_areas[core];
VAddr subaddress = address >> YUZU_PAGEBITS; VAddr subaddress = address >> YUZU_PAGEBITS;
bool do_collection = current_area.last_address == subaddress; bool do_collection = current_area.last_address == subaddress;
@ -799,6 +813,7 @@ struct Memory::Impl {
rasterizer_read_areas{}; rasterizer_read_areas{};
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
std::mutex sys_core_guard;
}; };
Memory::Memory(Core::System& system_) : system{system_} { Memory::Memory(Core::System& system_) : system{system_} {

View file

@ -415,7 +415,7 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
// This list is missing ZL/ZR since those are not considered buttons. // This list is missing ZL/ZR since those are not considered buttons.
// We will add those afterwards // We will add those afterwards
// This list also excludes any button that can't be really mapped // This list also excludes any button that can't be really mapped
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12> static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 14>
switch_to_gcadapter_button = { switch_to_gcadapter_button = {
std::pair{Settings::NativeButton::A, PadButton::ButtonA}, std::pair{Settings::NativeButton::A, PadButton::ButtonA},
{Settings::NativeButton::B, PadButton::ButtonB}, {Settings::NativeButton::B, PadButton::ButtonB},
@ -426,8 +426,10 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::DUp, PadButton::ButtonUp}, {Settings::NativeButton::DUp, PadButton::ButtonUp},
{Settings::NativeButton::DRight, PadButton::ButtonRight}, {Settings::NativeButton::DRight, PadButton::ButtonRight},
{Settings::NativeButton::DDown, PadButton::ButtonDown}, {Settings::NativeButton::DDown, PadButton::ButtonDown},
{Settings::NativeButton::SL, PadButton::TriggerL}, {Settings::NativeButton::SLLeft, PadButton::TriggerL},
{Settings::NativeButton::SR, PadButton::TriggerR}, {Settings::NativeButton::SRLeft, PadButton::TriggerR},
{Settings::NativeButton::SLRight, PadButton::TriggerL},
{Settings::NativeButton::SRRight, PadButton::TriggerR},
{Settings::NativeButton::R, PadButton::TriggerZ}, {Settings::NativeButton::R, PadButton::TriggerZ},
}; };
if (!params.Has("port")) { if (!params.Has("port")) {

View file

@ -680,8 +680,8 @@ ButtonMapping Joycons::GetButtonMappingForDevice(const Common::ParamPackage& par
Common::ParamPackage sr_button_params = button_params; Common::ParamPackage sr_button_params = button_params;
sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSL)); sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSL));
sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSR)); sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSR));
mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params)); mapping.insert_or_assign(Settings::NativeButton::SLLeft, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params)); mapping.insert_or_assign(Settings::NativeButton::SRLeft, std::move(sr_button_params));
} }
// Map SL and SR buttons for right joycons // Map SL and SR buttons for right joycons
@ -693,8 +693,8 @@ ButtonMapping Joycons::GetButtonMappingForDevice(const Common::ParamPackage& par
Common::ParamPackage sr_button_params = button_params; Common::ParamPackage sr_button_params = button_params;
sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSL)); sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSL));
sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSR)); sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSR));
mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params)); mapping.insert_or_assign(Settings::NativeButton::SLRight, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params)); mapping.insert_or_assign(Settings::NativeButton::SRRight, std::move(sr_button_params));
} }
return mapping; return mapping;

View file

@ -828,16 +828,18 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p
ButtonBindings SDLDriver::GetDefaultButtonBinding( ButtonBindings SDLDriver::GetDefaultButtonBinding(
const std::shared_ptr<SDLJoystick>& joystick) const { const std::shared_ptr<SDLJoystick>& joystick) const {
// Default SL/SR mapping for other controllers // Default SL/SR mapping for other controllers
auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; auto sll_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; auto srl_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
auto slr_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
auto srr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
if (joystick->IsJoyconLeft()) { if (joystick->IsJoyconLeft()) {
sl_button = SDL_CONTROLLER_BUTTON_PADDLE2; sll_button = SDL_CONTROLLER_BUTTON_PADDLE2;
sr_button = SDL_CONTROLLER_BUTTON_PADDLE4; srl_button = SDL_CONTROLLER_BUTTON_PADDLE4;
} }
if (joystick->IsJoyconRight()) { if (joystick->IsJoyconRight()) {
sl_button = SDL_CONTROLLER_BUTTON_PADDLE3; slr_button = SDL_CONTROLLER_BUTTON_PADDLE3;
sr_button = SDL_CONTROLLER_BUTTON_PADDLE1; srr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
} }
return { return {
@ -855,8 +857,10 @@ ButtonBindings SDLDriver::GetDefaultButtonBinding(
{Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
{Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
{Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
{Settings::NativeButton::SL, sl_button}, {Settings::NativeButton::SLLeft, sll_button},
{Settings::NativeButton::SR, sr_button}, {Settings::NativeButton::SRLeft, srl_button},
{Settings::NativeButton::SLRight, slr_button},
{Settings::NativeButton::SRRight, srr_button},
{Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
{Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1}, {Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1},
}; };

View file

@ -24,7 +24,7 @@ namespace InputCommon {
class SDLJoystick; class SDLJoystick;
using ButtonBindings = using ButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 18>; std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 20>;
using ZButtonBindings = using ZButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>; std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>;

View file

@ -396,7 +396,7 @@ std::vector<Common::ParamPackage> UDPClient::GetInputDevices() const {
ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) { ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) {
// This list excludes any button that can't be really mapped // This list excludes any button that can't be really mapped
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 20> static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 22>
switch_to_dsu_button = { switch_to_dsu_button = {
std::pair{Settings::NativeButton::A, PadButton::Circle}, std::pair{Settings::NativeButton::A, PadButton::Circle},
{Settings::NativeButton::B, PadButton::Cross}, {Settings::NativeButton::B, PadButton::Cross},
@ -412,8 +412,10 @@ ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::R, PadButton::R1}, {Settings::NativeButton::R, PadButton::R1},
{Settings::NativeButton::ZL, PadButton::L2}, {Settings::NativeButton::ZL, PadButton::L2},
{Settings::NativeButton::ZR, PadButton::R2}, {Settings::NativeButton::ZR, PadButton::R2},
{Settings::NativeButton::SL, PadButton::L2}, {Settings::NativeButton::SLLeft, PadButton::L2},
{Settings::NativeButton::SR, PadButton::R2}, {Settings::NativeButton::SRLeft, PadButton::R2},
{Settings::NativeButton::SLRight, PadButton::L2},
{Settings::NativeButton::SRRight, PadButton::R2},
{Settings::NativeButton::LStick, PadButton::L3}, {Settings::NativeButton::LStick, PadButton::L3},
{Settings::NativeButton::RStick, PadButton::R3}, {Settings::NativeButton::RStick, PadButton::R3},
{Settings::NativeButton::Home, PadButton::Home}, {Settings::NativeButton::Home, PadButton::Home},

View file

@ -86,10 +86,7 @@ public:
uncommitted_operations.emplace_back(std::move(func)); uncommitted_operations.emplace_back(std::move(func));
} }
pending_operations.emplace_back(std::move(uncommitted_operations)); pending_operations.emplace_back(std::move(uncommitted_operations));
{ QueueFence(new_fence);
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
QueueFence(new_fence);
}
if (!delay_fence) { if (!delay_fence) {
func(); func();
} }

View file

@ -555,7 +555,7 @@ void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) {
} }
{ {
std::scoped_lock lock{buffer_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex};
buffer_cache.CachedWriteMemory(addr, size); buffer_cache.WriteMemory(addr, size);
} }
shader_cache.InvalidateRegion(addr, size); shader_cache.InvalidateRegion(addr, size);
} }

View file

@ -132,16 +132,12 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
const bool use_accelerated = const bool use_accelerated =
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
const bool is_srgb = use_accelerated && screen_info.is_srgb; const bool is_srgb = use_accelerated && screen_info.is_srgb;
RenderScreenshot(*framebuffer, use_accelerated);
{ Frame* frame = present_manager.GetRenderFrame();
std::scoped_lock lock{rasterizer.LockCaches()}; blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb);
RenderScreenshot(*framebuffer, use_accelerated); scheduler.Flush(*frame->render_ready);
present_manager.Present(frame);
Frame* frame = present_manager.GetRenderFrame();
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb);
scheduler.Flush(*frame->render_ready);
present_manager.Present(frame);
}
gpu.RendererFrameEndNotify(); gpu.RendererFrameEndNotify();
rasterizer.TickFrame(); rasterizer.TickFrame();

View file

@ -199,7 +199,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
if (!pipeline) { if (!pipeline) {
return; return;
} }
std::scoped_lock lock{LockCaches()}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
// update engine as channel may be different. // update engine as channel may be different.
pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->SetEngine(maxwell3d, gpu_memory);
pipeline->Configure(is_indexed); pipeline->Configure(is_indexed);
@ -621,7 +621,7 @@ void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) {
} }
{ {
std::scoped_lock lock{buffer_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex};
buffer_cache.CachedWriteMemory(addr, size); buffer_cache.WriteMemory(addr, size);
} }
pipeline_cache.InvalidateRegion(addr, size); pipeline_cache.InvalidateRegion(addr, size);
} }
@ -710,7 +710,6 @@ void RasterizerVulkan::TiledCacheBarrier() {
} }
void RasterizerVulkan::FlushCommands() { void RasterizerVulkan::FlushCommands() {
std::scoped_lock lock{LockCaches()};
if (draw_counter == 0) { if (draw_counter == 0) {
return; return;
} }
@ -808,7 +807,6 @@ void RasterizerVulkan::FlushWork() {
if ((++draw_counter & 7) != 7) { if ((++draw_counter & 7) != 7) {
return; return;
} }
std::scoped_lock lock{LockCaches()};
if (draw_counter < DRAWS_TO_DISPATCH) { if (draw_counter < DRAWS_TO_DISPATCH) {
// Send recorded tasks to the worker thread // Send recorded tasks to the worker thread
scheduler.DispatchWork(); scheduler.DispatchWork();
@ -1507,7 +1505,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) { void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) {
CreateChannel(channel); CreateChannel(channel);
{ {
std::scoped_lock lock{LockCaches()}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.CreateChannel(channel); texture_cache.CreateChannel(channel);
buffer_cache.CreateChannel(channel); buffer_cache.CreateChannel(channel);
} }
@ -1520,7 +1518,7 @@ void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) {
const s32 channel_id = channel.bind_id; const s32 channel_id = channel.bind_id;
BindToChannel(channel_id); BindToChannel(channel_id);
{ {
std::scoped_lock lock{LockCaches()}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.BindToChannel(channel_id); texture_cache.BindToChannel(channel_id);
buffer_cache.BindToChannel(channel_id); buffer_cache.BindToChannel(channel_id);
} }
@ -1533,7 +1531,7 @@ void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) {
void RasterizerVulkan::ReleaseChannel(s32 channel_id) { void RasterizerVulkan::ReleaseChannel(s32 channel_id) {
EraseChannel(channel_id); EraseChannel(channel_id);
{ {
std::scoped_lock lock{LockCaches()}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.EraseChannel(channel_id); texture_cache.EraseChannel(channel_id);
buffer_cache.EraseChannel(channel_id); buffer_cache.EraseChannel(channel_id);
} }

View file

@ -133,10 +133,6 @@ public:
void ReleaseChannel(s32 channel_id) override; void ReleaseChannel(s32 channel_id) override;
std::scoped_lock<std::recursive_mutex, std::recursive_mutex> LockCaches() {
return std::scoped_lock{buffer_cache.mutex, texture_cache.mutex};
}
private: private:
static constexpr size_t MAX_TEXTURES = 192; static constexpr size_t MAX_TEXTURES = 192;
static constexpr size_t MAX_IMAGES = 48; static constexpr size_t MAX_IMAGES = 48;

View file

@ -35,6 +35,7 @@ const std::array<int, Settings::NativeButton::NumButtons> Config::default_button
Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
Qt::Key_Q, Qt::Key_E,
}; };
const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = { const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = {

View file

@ -322,11 +322,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
button_map = { button_map = {
ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR,
ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus,
ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown,
ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, ui->buttonSLLeft, ui->buttonSRLeft, ui->buttonHome, ui->buttonScreenshot,
ui->buttonSLRight, ui->buttonSRRight,
}; };
analog_map_buttons = {{ analog_map_buttons = {{
@ -1181,10 +1182,13 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
// List of all the widgets that will be hidden by any of the following layouts that need // List of all the widgets that will be hidden by any of the following layouts that need
// "unhidden" after the controller type changes // "unhidden" after the controller type changes
const std::array<QWidget*, 11> layout_show = { const std::array<QWidget*, 14> layout_show = {
ui->buttonShoulderButtonsSLSR, ui->buttonShoulderButtonsSLSRLeft,
ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget, ui->horizontalSpacerShoulderButtonsWidget,
ui->horizontalSpacerShoulderButtonsWidget2, ui->horizontalSpacerShoulderButtonsWidget2,
ui->horizontalSpacerShoulderButtonsWidget3,
ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonShoulderButtonsLeft, ui->buttonShoulderButtonsLeft,
ui->buttonMiscButtonsMinusScreenshot, ui->buttonMiscButtonsMinusScreenshot,
ui->bottomLeft, ui->bottomLeft,
@ -1202,16 +1206,19 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
std::vector<QWidget*> layout_hidden; std::vector<QWidget*> layout_hidden;
switch (layout) { switch (layout) {
case Core::HID::NpadStyleIndex::ProController: case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld: case Core::HID::NpadStyleIndex::Handheld:
layout_hidden = { layout_hidden = {
ui->buttonShoulderButtonsSLSR, ui->buttonShoulderButtonsSLSRLeft,
ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2, ui->horizontalSpacerShoulderButtonsWidget2,
ui->horizontalSpacerShoulderButtonsWidget4,
}; };
break; break;
case Core::HID::NpadStyleIndex::JoyconLeft: case Core::HID::NpadStyleIndex::JoyconLeft:
layout_hidden = { layout_hidden = {
ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2, ui->horizontalSpacerShoulderButtonsWidget2,
ui->horizontalSpacerShoulderButtonsWidget3,
ui->buttonShoulderButtonsRight, ui->buttonShoulderButtonsRight,
ui->buttonMiscButtonsPlusHome, ui->buttonMiscButtonsPlusHome,
ui->bottomRight, ui->bottomRight,
@ -1219,16 +1226,17 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
break; break;
case Core::HID::NpadStyleIndex::JoyconRight: case Core::HID::NpadStyleIndex::JoyconRight:
layout_hidden = { layout_hidden = {
ui->horizontalSpacerShoulderButtonsWidget, ui->buttonShoulderButtonsSLSRLeft, ui->horizontalSpacerShoulderButtonsWidget,
ui->buttonShoulderButtonsLeft, ui->horizontalSpacerShoulderButtonsWidget4, ui->buttonShoulderButtonsLeft,
ui->buttonMiscButtonsMinusScreenshot, ui->buttonMiscButtonsMinusScreenshot, ui->bottomLeft,
ui->bottomLeft,
}; };
break; break;
case Core::HID::NpadStyleIndex::GameCube: case Core::HID::NpadStyleIndex::GameCube:
layout_hidden = { layout_hidden = {
ui->buttonShoulderButtonsSLSR, ui->buttonShoulderButtonsSLSRLeft,
ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2, ui->horizontalSpacerShoulderButtonsWidget2,
ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonMiscButtonsMinusGroup, ui->buttonMiscButtonsMinusGroup,
ui->buttonMiscButtonsScreenshotGroup, ui->buttonMiscButtonsScreenshotGroup,
}; };

View file

@ -1208,6 +1208,159 @@
<property name="spacing"> <property name="spacing">
<number>3</number> <number>3</number>
</property> </property>
<item>
<widget class="QWidget" name="buttonShoulderButtonsSLSRLeft" native="true">
<layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRLeftVerticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="buttonShoulderButtonsSLLeftGroup">
<property name="title">
<string>SL</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="buttonShoulderButtonsSLLeftVerticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="buttonSLLeft">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
</property>
<property name="text">
<string>SL</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="buttonShoulderButtonsSRLeftGroup">
<property name="title">
<string>SR</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="buttonShoulderButtonsSRLeftVerticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="buttonSRLeft">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
</property>
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget4" native="true">
<layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget4Layout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacerShoulderButtons5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QWidget" name="buttonShoulderButtonsLeft" native="true"> <widget class="QWidget" name="buttonShoulderButtonsLeft" native="true">
<layout class="QVBoxLayout" name="buttonShoulderButtonsLeftVerticalLayout"> <layout class="QVBoxLayout" name="buttonShoulderButtonsLeftVerticalLayout">
@ -1830,125 +1983,125 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QWidget" name="buttonShoulderButtonsSLSR" native="true"> <widget class="QWidget" name="buttonShoulderButtonsSLSRRight" native="true">
<layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRVerticalLayout"> <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRRightVerticalLayout">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item alignment="Qt::AlignHCenter"> <item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="buttonShoulderButtonsSLGroup"> <widget class="QGroupBox" name="buttonShoulderButtonsSLRightGroup">
<property name="title"> <property name="title">
<string>SL</string> <string>SL</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
<layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout"> <layout class="QVBoxLayout" name="buttonShoulderButtonsSLRightVerticalLayout">
<property name="spacing"> <property name="spacing">
<number>3</number> <number>3</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>3</number> <number>3</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>3</number> <number>3</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>3</number> <number>3</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>3</number> <number>3</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="buttonSL"> <widget class="QPushButton" name="buttonSLRight">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>68</width> <width>68</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>68</width> <width>68</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">min-width: 68px;</string> <string notr="true">min-width: 68px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>SL</string> <string>SL</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="buttonShoulderButtonsSRRightGroup">
<property name="title">
<string>SR</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="buttonShoulderButtonsSRRightVerticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="buttonSRRight">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
</property>
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="buttonShoulderButtonsSRGroup">
<property name="title">
<string>SR</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="buttonSR">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
</property>
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View file

@ -297,8 +297,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
// Sideview SL and SR buttons // Sideview SL and SR buttons
button_color = colors.slider_button; button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(59, 52), button_values[SR], 5, 12, Direction::Left); DrawRoundButton(p, center + QPoint(59, 52), button_values[SRLeft], 5, 12, Direction::Left);
DrawRoundButton(p, center + QPoint(59, -69), button_values[SL], 5, 12, Direction::Left); DrawRoundButton(p, center + QPoint(59, -69), button_values[SLLeft], 5, 12, Direction::Left);
DrawLeftBody(p, center); DrawLeftBody(p, center);
@ -353,8 +353,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
// SR and SL buttons // SR and SL buttons
p.setPen(colors.outline); p.setPen(colors.outline);
button_color = colors.slider_button; button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(155, 52), button_values[SR], 5.2f, 12, Direction::None, 4); DrawRoundButton(p, center + QPoint(155, 52), button_values[SRLeft], 5.2f, 12, Direction::None,
DrawRoundButton(p, center + QPoint(155, -69), button_values[SL], 5.2f, 12, Direction::None, 4); 4);
DrawRoundButton(p, center + QPoint(155, -69), button_values[SLLeft], 5.2f, 12, Direction::None,
4);
// SR and SL text // SR and SL text
p.setPen(colors.transparent); p.setPen(colors.transparent);
@ -428,8 +430,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
// Sideview SL and SR buttons // Sideview SL and SR buttons
button_color = colors.slider_button; button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(-59, 52), button_values[SL], 5, 11, Direction::Right); DrawRoundButton(p, center + QPoint(-59, 52), button_values[SLRight], 5, 11,
DrawRoundButton(p, center + QPoint(-59, -69), button_values[SR], 5, 11, Direction::Right); Direction::Right);
DrawRoundButton(p, center + QPoint(-59, -69), button_values[SRRight], 5, 11,
Direction::Right);
DrawRightBody(p, center); DrawRightBody(p, center);
@ -484,8 +488,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
// SR and SL buttons // SR and SL buttons
p.setPen(colors.outline); p.setPen(colors.outline);
button_color = colors.slider_button; button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(-155, 52), button_values[SL], 5, 12, Direction::None, 4.0f); DrawRoundButton(p, center + QPoint(-155, 52), button_values[SLRight], 5, 12, Direction::None,
DrawRoundButton(p, center + QPoint(-155, -69), button_values[SR], 5, 12, Direction::None, 4.0f); 4.0f);
DrawRoundButton(p, center + QPoint(-155, -69), button_values[SRRight], 5, 12, Direction::None,
4.0f);
// SR and SL text // SR and SL text
p.setPen(colors.transparent); p.setPen(colors.transparent);
@ -557,6 +563,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up, DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up,
1); 1);
// Left SR and SL sideview buttons
button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(-20, -62), button_values[SLLeft], 4, 11,
Direction::Left);
DrawRoundButton(p, center + QPoint(-20, 47), button_values[SRLeft], 4, 11, Direction::Left);
// Right SR and SL sideview buttons
button_color = colors.slider_button;
DrawRoundButton(p, center + QPoint(20, 47), button_values[SLRight], 4, 11,
Direction::Right);
DrawRoundButton(p, center + QPoint(20, -62), button_values[SRRight], 4, 11,
Direction::Right);
DrawDualBody(p, center); DrawDualBody(p, center);
// Right trigger top view // Right trigger top view
@ -1792,16 +1811,6 @@ void PlayerControlPreview::DrawDualBody(QPainter& p, const QPointF center) {
p.setBrush(colors.right); p.setBrush(colors.right);
DrawPolygon(p, qright_joycon_topview); DrawPolygon(p, qright_joycon_topview);
// Right SR and SL sideview buttons
p.setPen(colors.outline);
p.setBrush(colors.slider_button);
DrawRoundRectangle(p, center + QPoint(19, 47), 7, 22, 1);
DrawRoundRectangle(p, center + QPoint(19, -62), 7, 22, 1);
// Left SR and SL sideview buttons
DrawRoundRectangle(p, center + QPoint(-19, 47), 7, 22, 1);
DrawRoundRectangle(p, center + QPoint(-19, -62), 7, 22, 1);
// Right Sideview body // Right Sideview body
p.setBrush(colors.slider); p.setBrush(colors.slider);
DrawPolygon(p, qright_joycon_slider); DrawPolygon(p, qright_joycon_slider);