diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 22 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdata.h | 25 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 46 | 
8 files changed, 70 insertions, 57 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 30eb9d82e..c22585bfb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -369,6 +369,7 @@ add_library(core STATIC      hle/service/nvdrv/devices/nvmap.h      hle/service/nvdrv/interface.cpp      hle/service/nvdrv/interface.h +    hle/service/nvdrv/nvdata.h      hle/service/nvdrv/nvdrv.cpp      hle/service/nvdrv/nvdrv.h      hle/service/nvdrv/nvmemp.cpp diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 8ce7bc7a5..8a53eddb1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -155,8 +155,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp      Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); -    params.fence_out.id = 0; -    params.fence_out.value = 0; +    // TODO(Blinkhawk): Figure how thoios fence is set +    // params.fence_out.value = 0;      std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo));      return 0;  } @@ -176,8 +176,8 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)      Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); -    params.fence_out.id = 0; -    params.fence_out.value = 0; +    // TODO(Blinkhawk): Figure how thoios fence is set +    // params.fence_out.value = 0;      std::memcpy(output.data(), ¶ms, output.size());      return 0;  } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 62beb5c0c..d95cedb09 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -113,11 +113,11 @@ private:      static_assert(sizeof(IoctlGetErrorNotification) == 16,                    "IoctlGetErrorNotification is incorrect size"); -    struct IoctlFence { +    struct Fence {          u32_le id;          u32_le value;      }; -    static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size"); +    static_assert(sizeof(Fence) == 8, "Fence is incorrect size");      struct IoctlAllocGpfifoEx {          u32_le num_entries; @@ -132,13 +132,13 @@ private:      static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size");      struct IoctlAllocGpfifoEx2 { -        u32_le num_entries;   // in -        u32_le flags;         // in -        u32_le unk0;          // in (1 works) -        IoctlFence fence_out; // out -        u32_le unk1;          // in -        u32_le unk2;          // in -        u32_le unk3;          // in +        u32_le num_entries; // in +        u32_le flags;       // in +        u32_le unk0;        // in (1 works) +        Fence fence_out;    // out +        u32_le unk1;        // in +        u32_le unk2;        // in +        u32_le unk3;        // in      };      static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); @@ -154,9 +154,9 @@ private:          u64_le address;     // pointer to gpfifo entry structs          u32_le num_entries; // number of fence objects being submitted          u32_le flags; -        IoctlFence fence_out; // returned new fence object for others to wait on +        Fence fence_out; // returned new fence object for others to wait on      }; -    static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence), +    static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence),                    "IoctlSubmitGpfifo is incorrect size");      struct IoctlGetWaitbase { diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h new file mode 100644 index 000000000..7e1dce232 --- /dev/null +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -0,0 +1,25 @@ +#pragma once + +#include <array> +#include "common/common_types.h" + +namespace Service::Nvidia { + +struct Fence { +    s32 id; +    u32 value; +}; + +static_assert(sizeof(Fence) == 8, "Fence has wrong size"); + +struct MultiFence { +    u32 num_fences; +    std::array<Fence, 4> fences; +}; + +enum class NvResult : u32 { +    Success = 0, +    TryAgain = 11, +}; + +} // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 53564f696..bacd7cdb7 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -8,6 +8,7 @@  #include <unordered_map>  #include <vector>  #include "common/common_types.h" +#include "core/hle/service/nvdrv/nvdata.h"  #include "core/hle/service/service.h"  namespace Service::NVFlinger { @@ -20,13 +21,6 @@ namespace Devices {  class nvdevice;  } -struct IoctlFence { -    u32 id; -    u32 value; -}; - -static_assert(sizeof(IoctlFence) == 8, "IoctlFence has wrong size"); -  class Module final {  public:      Module(); diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index dca75c35e..75e47b8c7 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -34,7 +34,8 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)      buffer_wait_event.writable->Signal();  } -std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) { +std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, +                                                                                       u32 height) {      auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {          // Only consider free buffers. Buffers become free once again after they've been Acquired          // and Released by the compositor, see the NVFlinger::Compose method. @@ -51,7 +52,7 @@ std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {      }      itr->status = Buffer::Status::Dequeued; -    return itr->slot; +    return {{itr->slot, &itr->multi_fence}};  }  const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { @@ -63,7 +64,8 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {  }  void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, -                              const Common::Rectangle<int>& crop_rect, u32 swap_interval) { +                              const Common::Rectangle<int>& crop_rect, u32 swap_interval, +                              Service::Nvidia::MultiFence& multi_fence) {      auto itr = std::find_if(queue.begin(), queue.end(),                              [&](const Buffer& buffer) { return buffer.slot == slot; });      ASSERT(itr != queue.end()); @@ -72,6 +74,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,      itr->transform = transform;      itr->crop_rect = crop_rect;      itr->swap_interval = swap_interval; +    itr->multi_fence = multi_fence;  }  std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 139b98b9f..c163e565c 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -12,6 +12,7 @@  #include "common/swap.h"  #include "core/hle/kernel/object.h"  #include "core/hle/kernel/writable_event.h" +#include "core/hle/service/nvdrv/nvdata.h"  namespace Service::NVFlinger { @@ -69,13 +70,16 @@ public:          BufferTransformFlags transform;          Common::Rectangle<int> crop_rect;          u32 swap_interval; +        Service::Nvidia::MultiFence multi_fence;      };      void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer); -    std::optional<u32> DequeueBuffer(u32 width, u32 height); +    std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> DequeueBuffer(u32 width, +                                                                              u32 height);      const IGBPBuffer& RequestBuffer(u32 slot) const;      void QueueBuffer(u32 slot, BufferTransformFlags transform, -                     const Common::Rectangle<int>& crop_rect, u32 swap_interval); +                     const Common::Rectangle<int>& crop_rect, u32 swap_interval, +                     Service::Nvidia::MultiFence& multi_fence);      std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();      void ReleaseBuffer(u32 slot);      u32 Query(QueryType type); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 55bd252c2..894bcdc04 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -21,6 +21,7 @@  #include "core/hle/kernel/readable_event.h"  #include "core/hle/kernel/thread.h"  #include "core/hle/kernel/writable_event.h" +#include "core/hle/service/nvdrv/nvdata.h"  #include "core/hle/service/nvdrv/nvdrv.h"  #include "core/hle/service/nvflinger/buffer_queue.h"  #include "core/hle/service/nvflinger/nvflinger.h" @@ -328,32 +329,22 @@ public:      Data data;  }; -struct BufferProducerFence { -    u32 is_valid; -    std::array<Nvidia::IoctlFence, 4> fences; -}; -static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong size"); -  class IGBPDequeueBufferResponseParcel : public Parcel {  public: -    explicit IGBPDequeueBufferResponseParcel(u32 slot) : slot(slot) {} +    explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) +        : slot(slot), multi_fence(multi_fence) {}      ~IGBPDequeueBufferResponseParcel() override = default;  protected:      void SerializeData() override { -        // TODO(Subv): Find out how this Fence is used. -        BufferProducerFence fence = {}; -        fence.is_valid = 1; -        for (auto& fence_ : fence.fences) -            fence_.id = -1; -          Write(slot);          Write<u32_le>(1); -        WriteObject(fence); +        WriteObject(multi_fence);          Write<u32_le>(0);      }      u32_le slot; +    Service::Nvidia::MultiFence multi_fence;  };  class IGBPRequestBufferRequestParcel : public Parcel { @@ -400,12 +391,6 @@ public:          data = Read<Data>();      } -    struct Fence { -        u32_le id; -        u32_le value; -    }; -    static_assert(sizeof(Fence) == 8, "Fence has wrong size"); -      struct Data {          u32_le slot;          INSERT_PADDING_WORDS(3); @@ -420,14 +405,13 @@ public:          u32_le sticky_transform;          INSERT_PADDING_WORDS(1);          u32_le swap_interval; -        u32_le fence_is_valid; -        std::array<Fence, 2> fences; +        Service::Nvidia::MultiFence multi_fence;          Common::Rectangle<int> GetCropRect() const {              return {crop_left, crop_top, crop_right, crop_bottom};          }      }; -    static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); +    static_assert(sizeof(Data) == 96, "ParcelData has wrong size");      Data data;  }; @@ -548,11 +532,11 @@ private:              IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};              const u32 width{request.data.width};              const u32 height{request.data.height}; -            std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); +            auto result = buffer_queue.DequeueBuffer(width, height); -            if (slot) { +            if (result) {                  // Buffer is available -                IGBPDequeueBufferResponseParcel response{*slot}; +                IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second};                  ctx.WriteBuffer(response.Serialize());              } else {                  // Wait the current thread until a buffer becomes available @@ -562,10 +546,11 @@ private:                          Kernel::ThreadWakeupReason reason) {                          // Repeat TransactParcel DequeueBuffer when a buffer is available                          auto& buffer_queue = nv_flinger->FindBufferQueue(id); -                        std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); -                        ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); +                        auto result = buffer_queue.DequeueBuffer(width, height); +                        ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); -                        IGBPDequeueBufferResponseParcel response{*slot}; +                        IGBPDequeueBufferResponseParcel response{(*result).first, +                                                                 *(*result).second};                          ctx.WriteBuffer(response.Serialize());                          IPC::ResponseBuilder rb{ctx, 2};                          rb.Push(RESULT_SUCCESS); @@ -583,7 +568,8 @@ private:              IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};              buffer_queue.QueueBuffer(request.data.slot, request.data.transform, -                                     request.data.GetCropRect(), request.data.swap_interval); +                                     request.data.GetCropRect(), request.data.swap_interval, +                                     request.data.multi_fence);              IGBPQueueBufferResponseParcel response{1280, 720};              ctx.WriteBuffer(response.Serialize()); | 
