From 9fccf8f02a59dd10730abfb81d5380b2a689d23c Mon Sep 17 00:00:00 2001 From: Jarrod Norwell Date: Mon, 1 Jul 2024 03:05:59 +0800 Subject: [PATCH] Started adding GetBufferHistory to fix MS: BL (based on Ryujinx's impl), added check to fix __noop --- externals/SDL | 2 +- src/common/microprofile.h | 6 +++- .../nvnflinger/buffer_queue_consumer.cpp | 17 ++++++++++ .../service/nvnflinger/buffer_queue_core.cpp | 4 ++- .../service/nvnflinger/buffer_queue_core.h | 9 ++++++ .../nvnflinger/buffer_queue_producer.cpp | 32 +++++++++++++++++-- .../nvnflinger/buffer_queue_producer.h | 2 ++ src/core/hle/service/nvnflinger/buffer_slot.h | 2 ++ 8 files changed, 69 insertions(+), 5 deletions(-) diff --git a/externals/SDL b/externals/SDL index c60e270..e1e36d2 160000 --- a/externals/SDL +++ b/externals/SDL @@ -1 +1 @@ -Subproject commit c60e2704c88ecb8bf55d69085b9c1bd2a68e5321 +Subproject commit e1e36d213bea3a0b56d91b454c53a2c94312a5be diff --git a/src/common/microprofile.h b/src/common/microprofile.h index 0614ac7..029f59b 100644 --- a/src/common/microprofile.h +++ b/src/common/microprofile.h @@ -20,7 +20,11 @@ typedef void* HANDLE; #endif #if MICROPROFILE_ENABLED == 0 -#define MicroProfileOnThreadExit __noop +#ifdef _WIN32 +#define MicroProfileOnThreadExit() __noop +#else +#define MicroProfileOnThreadExit() 0 +#endif #endif #include diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index 3a1467e..fd5b6ad 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -101,6 +101,14 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, // slot to the producer, it will wait for the fence to pass. We should fix this // by properly waiting for the fence in the BufferItemConsumer. // slots[slot].fence = Fence::NoFence(); + + const auto target_frame_number = slots[slot].frame_number; + for (int i = 0; i < core->history.size(); i++) { + if (core->history[i].frame_number = target_frame_number) { + core->history[i].state = BufferState::Acquired; + break; + } + } } // If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to @@ -255,6 +263,15 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { return Status::NoError; } +/* SetPresentTime +for (int i = 0; i < core->history.size(); i++) { + if (core->history[i].frame_number = target_frame_number) { + core->history[i].state == BufferState::Acquired; + break; + } +} +*/ + void BufferQueueConsumer::Transact(u32 code, std::span parcel_data, std::span parcel_reply, u32 flags) { // Values used by BnGraphicBufferConsumer onTransact diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp index d45b7a6..6567b49 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp @@ -10,7 +10,9 @@ namespace Service::android { -BufferQueueCore::BufferQueueCore() = default; +BufferQueueCore::BufferQueueCore() { + history.resize(8); +}; BufferQueueCore::~BufferQueueCore() = default; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index 2a05cdd..669166d 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -72,6 +72,15 @@ private: u32 transform_hint{}; bool is_allocating{}; mutable std::condition_variable_any is_allocating_condition; + + class BufferInfo final { + public: + u64 frame_number{}; + s64 queue_time{}, presentation_time{}; + BufferState state{BufferState::Free}; + }; + + std::vector history; }; } // 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 6a10043..0f8009d 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -512,6 +512,8 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, slots[slot].buffer_state = BufferState::Queued; ++core->frame_counter; slots[slot].frame_number = core->frame_counter; + slots[slot].queue_time = 0; // this is not the true value + slots[slot].presentation_time = 0; // doesn't need to be set afaik but do it anyway item.acquire_called = slots[slot].acquire_called; item.graphic_buffer = slots[slot].graphic_buffer; @@ -528,6 +530,13 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, item.is_droppable = core->dequeue_buffer_cannot_block || async; item.swap_interval = swap_interval; + // TODO: .queue_time should be changed to the correct value + position = (position + 1) % 8; + LOG_WARNING(Service_Nvnflinger, "position={}", position); + core->history[position] = {.frame_number = core->frame_counter, + .queue_time = slots[slot].queue_time, + .state = BufferState::Queued}; + sticky_transform = sticky_transform_; if (core->queue.empty()) { @@ -922,9 +931,28 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, status = SetBufferCount(buffer_count); break; } - case TransactionId::GetBufferHistory: - LOG_WARNING(Service_Nvnflinger, "(STUBBED) called, transaction=GetBufferHistory"); + case TransactionId::GetBufferHistory: { + LOG_WARNING(Service_Nvnflinger, "(STUBBED) called"); + + std::scoped_lock lock{core->mutex}; + + auto buffer_history_count = std::min(parcel_in.Read(), (s32)core->history.size()); + + BufferQueueCore::BufferInfo* info = new BufferQueueCore::BufferInfo[buffer_history_count]; + auto pos = position; + for (int i = 0; i < buffer_history_count; i++) { + info[i] = core->history[(pos - i) % core->history.size()]; + LOG_WARNING(Service_Nvnflinger, "frame_number={}, state={}", + core->history[(pos - i) % core->history.size()].frame_number, + (u32)core->history[(pos - i) % core->history.size()].state); + pos--; + } + + parcel_out.WriteFlattenedObject(info); + status = Status::NoError; + break; + } default: ASSERT_MSG(false, "Unimplemented TransactionId {}", code); break; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 6b015c3..886e2ed 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -86,6 +86,8 @@ private: s32 current_callback_ticket{}; std::condition_variable_any callback_condition; + u64 position; + Service::Nvidia::NvCore::NvMap& nvmap; }; diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index be91da8..3f69181 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h @@ -34,6 +34,8 @@ struct BufferSlot final { bool needs_cleanup_on_release{}; bool attached_by_consumer{}; bool is_preallocated{}; + + s64 queue_time{}, presentation_time{}; }; } // namespace Service::android