early-access version 2804

This commit is contained in:
pineappleEA 2022-06-27 23:04:31 +02:00
parent 8a674958a7
commit 5cf5fef861
18 changed files with 99 additions and 43 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access
=============
This is the source code for early-access 2803.
This is the source code for early-access 2804.
## Legal Notice

View file

@ -161,7 +161,7 @@ bool KProcess::ReleaseUserException(KThread* thread) {
std::addressof(num_waiters),
reinterpret_cast<uintptr_t>(std::addressof(exception_thread)));
next != nullptr) {
next->SetState(ThreadState::Runnable);
next->EndWait(ResultSuccess);
}
KScheduler::SetSchedulerUpdateNeeded(kernel);

View file

@ -487,9 +487,7 @@ void KThread::Unpin() {
// Resume any threads that began waiting on us while we were pinned.
for (auto it = pinned_waiter_list.begin(); it != pinned_waiter_list.end(); ++it) {
if (it->GetState() == ThreadState::Waiting) {
it->SetState(ThreadState::Runnable);
}
it->EndWait(ResultSuccess);
}
}
@ -884,6 +882,7 @@ void KThread::AddWaiterImpl(KThread* thread) {
// Keep track of how many kernel waiters we have.
if (IsKernelAddressKey(thread->GetAddressKey())) {
ASSERT((num_kernel_waiters++) >= 0);
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
// Insert the waiter.
@ -897,6 +896,7 @@ void KThread::RemoveWaiterImpl(KThread* thread) {
// Keep track of how many kernel waiters we have.
if (IsKernelAddressKey(thread->GetAddressKey())) {
ASSERT((num_kernel_waiters--) > 0);
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
// Remove the waiter.
@ -972,6 +972,7 @@ KThread* KThread::RemoveWaiterByKey(s32* out_num_waiters, VAddr key) {
// Keep track of how many kernel waiters we have.
if (IsKernelAddressKey(thread->GetAddressKey())) {
ASSERT((num_kernel_waiters--) > 0);
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
it = waiter_list.erase(it);

View file

@ -691,6 +691,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
// 6.0.0+
TotalPhysicalMemoryAvailableWithoutSystemResource = 21,
TotalPhysicalMemoryUsedWithoutSystemResource = 22,
// Homebrew only
MesosphereCurrentProcess = 65001,
};
const auto info_id_type = static_cast<GetInfoType>(info_id);
@ -913,6 +916,27 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
return ResultSuccess;
}
case GetInfoType::MesosphereCurrentProcess: {
// Verify the input handle is invalid.
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
// Verify the sub-type is valid.
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
// Get the handle table.
KProcess* current_process = system.Kernel().CurrentProcess();
KHandleTable& handle_table = current_process->GetHandleTable();
// Get a new handle for the current process.
Handle tmp;
R_TRY(handle_table.Add(&tmp, current_process));
// Set the output.
*result = tmp;
// We succeeded.
return ResultSuccess;
}
default:
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
return ResultInvalidEnumValue;

View file

@ -719,9 +719,8 @@ Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
}
void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
if (activation_mode != NpadHandheldActivationMode::None &&
activation_mode != NpadHandheldActivationMode::Single) {
ASSERT_MSG(false, "Activation mode should be always None or Single");
if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
return;
}

View file

@ -81,6 +81,7 @@ public:
Dual = 0,
Single = 1,
None = 2,
MaxActivationMode = 3,
};
// This is nn::hid::NpadCommunicationMode

View file

@ -207,6 +207,19 @@ void NvMap::UnpinHandle(Handle::Id handle) {
}
}
void NvMap::DuplicateHandle(Handle::Id handle, bool internal_session) {
auto handle_description{GetHandle(handle)};
if (!handle_description) {
LOG_CRITICAL(Service_NVDRV, "Unregistered handle!");
return;
}
auto result = handle_description->Duplicate(internal_session);
if (result != NvResult::Success) {
LOG_CRITICAL(Service_NVDRV, "Could not duplicate handle!");
}
}
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
std::weak_ptr<Handle> hWeak{GetHandle(handle)};
FreeInfo freeInfo;
@ -254,7 +267,7 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
// Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed
if (!hWeak.expired()) {
LOG_ERROR(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
freeInfo.address = 0;
}

View file

@ -162,6 +162,11 @@ public:
*/
void UnpinHandle(Handle::Id handle);
/**
* @brief Tries to duplicate a handle
*/
void DuplicateHandle(Handle::Id handle, bool internal_session = false);
/**
* @brief Tries to free a handle and remove a single dupe
* @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned

View file

@ -69,18 +69,6 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
void nvmap::OnOpen(DeviceFD fd) {}
void nvmap::OnClose(DeviceFD fd) {}
VAddr nvmap::GetObjectAddress(u32 handle) const {
auto obj = file.GetHandle(handle);
if (obj) {
return obj->address;
}
return 0;
}
std::shared_ptr<NvCore::NvMap::Handle> nvmap::GetObject(u32 handle) const {
return file.GetHandle(handle);
}
NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
IocCreateParams params;
std::memcpy(&params, input.data(), sizeof(params));

View file

@ -36,11 +36,6 @@ public:
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
/// Returns the allocated address of an nvmap object given its handle.
VAddr GetObjectAddress(u32 handle) const;
std::shared_ptr<NvCore::NvMap::Handle> GetObject(u32 handle) const;
enum class HandleParameterType : u32_le {
Size = 1,
Alignment = 2,

View file

@ -96,6 +96,7 @@ public:
private:
friend class EventInterface;
friend class Service::NVFlinger::NVFlinger;
/// Id to use for the next open file descriptor.
DeviceFD next_fd = 1;
@ -111,8 +112,6 @@ private:
/// Manages syncpoints on the host
NvCore::Container container;
void CreateEvent(u32 event_id);
void FreeEvent(u32 event_id);
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
};

View file

@ -5,15 +5,18 @@
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvflinger/buffer_item.h"
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvflinger/buffer_queue_core.h"
#include "core/hle/service/nvflinger/producer_listener.h"
#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
namespace Service::android {
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
: core{std::move(core_)}, slots{core->slots} {}
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
Service::Nvidia::NvCore::NvMap& nvmap_)
: core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
BufferQueueConsumer::~BufferQueueConsumer() = default;
@ -133,6 +136,8 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
slots[slot].buffer_state = BufferState::Free;
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
listener = core->connected_producer_listener;
LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);

View file

@ -13,6 +13,10 @@
#include "core/hle/service/nvflinger/buffer_queue_defs.h"
#include "core/hle/service/nvflinger/status.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android {
class BufferItem;
@ -21,7 +25,8 @@ class IConsumerListener;
class BufferQueueConsumer final {
public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
Service::Nvidia::NvCore::NvMap& nvmap_);
~BufferQueueConsumer();
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
@ -32,6 +37,7 @@ public:
private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
Service::Nvidia::NvCore::NvMap& nvmap;
};
} // namespace Service::android

View file

@ -14,7 +14,7 @@
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvflinger/buffer_queue_core.h"
#include "core/hle/service/nvflinger/buffer_queue_producer.h"
#include "core/hle/service/nvflinger/consumer_listener.h"
@ -26,8 +26,10 @@
namespace Service::android {
BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
std::shared_ptr<BufferQueueCore> buffer_queue_core_)
: service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots) {
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
Service::Nvidia::NvCore::NvMap& nvmap_)
: service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots),
nvmap(nvmap_) {
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
}
@ -530,6 +532,8 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
item.is_droppable = core->dequeue_buffer_cannot_block || async;
item.swap_interval = swap_interval;
nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true);
sticky_transform = sticky_transform_;
if (core->queue.empty()) {

View file

@ -31,6 +31,10 @@ namespace Service::KernelHelpers {
class ServiceContext;
} // namespace Service::KernelHelpers
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android {
class BufferQueueCore;
@ -39,7 +43,8 @@ class IProducerListener;
class BufferQueueProducer final : public IBinder {
public:
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
std::shared_ptr<BufferQueueCore> buffer_queue_core_);
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
Service::Nvidia::NvCore::NvMap& nvmap_);
~BufferQueueProducer();
void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
@ -78,6 +83,8 @@ private:
s32 next_callback_ticket{};
s32 current_callback_ticket{};
std::condition_variable_any callback_condition;
Service::Nvidia::NvCore::NvMap& nvmap;
};
} // namespace Service::android

View file

@ -139,7 +139,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
const auto buffer_id = next_buffer_queue_id++;
display.CreateLayer(layer_id, buffer_id);
display.CreateLayer(layer_id, buffer_id, nvdrv->container);
}
void NVFlinger::CloseLayer(u64 layer_id) {

View file

@ -12,6 +12,7 @@
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvflinger/buffer_item_consumer.h"
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvflinger/buffer_queue_core.h"
@ -28,11 +29,13 @@ struct BufferQueue {
std::unique_ptr<android::BufferQueueConsumer> consumer;
};
static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context) {
static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
Service::Nvidia::NvCore::NvMap& nvmap) {
auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
return {buffer_queue_core,
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core),
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
return {
buffer_queue_core,
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)};
}
Display::Display(u64 id, std::string name_,
@ -63,10 +66,11 @@ void Display::SignalVSyncEvent() {
vsync_event->GetWritableEvent().Signal();
}
void Display::CreateLayer(u64 layer_id, u32 binder_id) {
void Display::CreateLayer(u64 layer_id, u32 binder_id,
Service::Nvidia::NvCore::Container& nv_core) {
ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
auto [core, producer, consumer] = CreateBufferQueue(service_context);
auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
buffer_item_consumer->Connect(false);

View file

@ -26,6 +26,11 @@ namespace Service::NVFlinger {
class HosBinderDriverServer;
}
namespace Service::Nvidia::NvCore {
class Container;
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::VI {
class Layer;
@ -84,7 +89,7 @@ public:
/// @param layer_id The ID to assign to the created layer.
/// @param binder_id The ID assigned to the buffer queue.
///
void CreateLayer(u64 layer_id, u32 binder_id);
void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
/// Closes and removes a layer from this display with the given ID.
///