early-access version 1260

This commit is contained in:
pineappleEA
2020-12-29 11:39:08 +00:00
parent db53458619
commit 8016e08b0d
63 changed files with 962 additions and 471 deletions

View File

@@ -25,12 +25,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
ASSERT(slot < buffer_slots);
LOG_WARNING(Service, "Adding graphics buffer {}", slot);
{
std::unique_lock lock{queue_mutex};
free_buffers.push_back(slot);
}
condition.notify_one();
free_buffers.push_back(slot);
buffers[slot] = {
.slot = slot,
.status = Buffer::Status::Free,
@@ -46,20 +41,10 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
u32 height) {
// Wait for first request before trying to dequeue
{
std::unique_lock lock{queue_mutex};
condition.wait(lock, [this] { return !free_buffers.empty() || !is_connect; });
}
if (!is_connect) {
// Buffer was disconnected while the thread was blocked, this is most likely due to
// emulation being stopped
if (free_buffers.empty()) {
return std::nullopt;
}
std::unique_lock lock{queue_mutex};
auto f_itr = free_buffers.begin();
auto slot = buffers.size();
@@ -112,11 +97,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
buffers[slot].multi_fence = multi_fence;
buffers[slot].swap_interval = 0;
{
std::unique_lock lock{queue_mutex};
free_buffers.push_back(slot);
}
condition.notify_one();
free_buffers.push_back(slot);
buffer_wait_event.writable->Signal();
}
@@ -146,28 +127,15 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
ASSERT(buffers[slot].slot == slot);
buffers[slot].status = Buffer::Status::Free;
{
std::unique_lock lock{queue_mutex};
free_buffers.push_back(slot);
}
condition.notify_one();
free_buffers.push_back(slot);
buffer_wait_event.writable->Signal();
}
void BufferQueue::Connect() {
queue_sequence.clear();
id = 1;
layer_id = 1;
is_connect = true;
}
void BufferQueue::Disconnect() {
buffers.fill({});
queue_sequence.clear();
buffer_wait_event.writable->Signal();
is_connect = false;
condition.notify_one();
}
u32 BufferQueue::Query(QueryType type) {

View File

@@ -4,9 +4,7 @@
#pragma once
#include <condition_variable>
#include <list>
#include <mutex>
#include <optional>
#include <vector>
@@ -101,7 +99,6 @@ public:
void CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence);
std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
void ReleaseBuffer(u32 slot);
void Connect();
void Disconnect();
u32 Query(QueryType type);
@@ -109,28 +106,18 @@ public:
return id;
}
bool IsConnected() const {
return is_connect;
}
std::shared_ptr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const;
std::shared_ptr<Kernel::ReadableEvent> GetBufferWaitEvent() const;
private:
BufferQueue(const BufferQueue&) = delete;
u32 id{};
u64 layer_id{};
std::atomic_bool is_connect{};
u32 id;
u64 layer_id;
std::list<u32> free_buffers;
std::array<Buffer, buffer_slots> buffers;
std::list<u32> queue_sequence;
Kernel::EventPair buffer_wait_event;
std::mutex queue_mutex;
std::condition_variable condition;
};
} // namespace Service::NVFlinger

View File

@@ -88,10 +88,6 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
}
NVFlinger::~NVFlinger() {
for (auto& buffer_queue : buffer_queues) {
buffer_queue->Disconnect();
}
if (system.IsMulticore()) {
is_running = false;
wait_event->Set();
@@ -108,8 +104,6 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
}
std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
const auto guard = Lock();
LOG_DEBUG(Service, "Opening \"{}\" display", name);
// TODO(Subv): Currently we only support the Default display.
@@ -127,7 +121,6 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
}
std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
const auto guard = Lock();
auto* const display = FindDisplay(display_id);
if (display == nullptr) {
@@ -136,22 +129,18 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
const u64 layer_id = next_layer_id++;
const u32 buffer_queue_id = next_buffer_queue_id++;
buffer_queues.emplace_back(
std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id));
display->CreateLayer(layer_id, *buffer_queues.back());
buffer_queues.emplace_back(system.Kernel(), buffer_queue_id, layer_id);
display->CreateLayer(layer_id, buffer_queues.back());
return layer_id;
}
void NVFlinger::CloseLayer(u64 layer_id) {
const auto guard = Lock();
for (auto& display : displays) {
display.CloseLayer(layer_id);
}
}
std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const {
const auto guard = Lock();
const auto* const layer = FindLayer(display_id, layer_id);
if (layer == nullptr) {
@@ -162,7 +151,6 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
}
std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
const auto guard = Lock();
auto* const display = FindDisplay(display_id);
if (display == nullptr) {
@@ -172,16 +160,20 @@ std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id)
return display->GetVSyncEvent();
}
BufferQueue* NVFlinger::FindBufferQueue(u32 id) {
const auto guard = Lock();
BufferQueue& NVFlinger::FindBufferQueue(u32 id) {
const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(),
[id](const auto& queue) { return queue->GetId() == id; });
[id](const auto& queue) { return queue.GetId() == id; });
if (itr == buffer_queues.end()) {
return nullptr;
}
ASSERT(itr != buffer_queues.end());
return *itr;
}
return itr->get();
const BufferQueue& NVFlinger::FindBufferQueue(u32 id) const {
const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(),
[id](const auto& queue) { return queue.GetId() == id; });
ASSERT(itr != buffer_queues.end());
return *itr;
}
VI::Display* NVFlinger::FindDisplay(u64 display_id) {

View File

@@ -75,7 +75,10 @@ public:
[[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
/// Obtains a buffer queue identified by the ID.
[[nodiscard]] BufferQueue* FindBufferQueue(u32 id);
[[nodiscard]] BufferQueue& FindBufferQueue(u32 id);
/// Obtains a buffer queue identified by the ID.
[[nodiscard]] const BufferQueue& FindBufferQueue(u32 id) const;
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
/// finished.
@@ -83,11 +86,11 @@ public:
[[nodiscard]] s64 GetNextTicks() const;
private:
[[nodiscard]] std::unique_lock<std::mutex> Lock() const {
return std::unique_lock{*guard};
}
private:
/// Finds the display identified by the specified ID.
[[nodiscard]] VI::Display* FindDisplay(u64 display_id);
@@ -107,7 +110,7 @@ private:
std::shared_ptr<Nvidia::Module> nvdrv;
std::vector<VI::Display> displays;
std::vector<std::unique_ptr<BufferQueue>> buffer_queues;
std::vector<BufferQueue> buffer_queues;
/// Id to use for the next layer that is created, this counter is shared among all displays.
u64 next_layer_id = 1;