summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-06-07 11:34:55 -0400
committerGravatar FernandoS272019-07-05 15:49:10 -0400
commit737e978f5b1440a044ef90f346c8616c2de49a81 (patch)
tree42b3c99171a3929f64db141db81193a0067b3523
parentnvflinger: Implement swap intervals (diff)
downloadyuzu-737e978f5b1440a044ef90f346c8616c2de49a81.tar.gz
yuzu-737e978f5b1440a044ef90f346c8616c2de49a81.tar.xz
yuzu-737e978f5b1440a044ef90f346c8616c2de49a81.zip
nv_services: Correct buffer queue fencing and GPFifo fencing
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h22
-rw-r--r--src/core/hle/service/nvdrv/nvdata.h25
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h8
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp9
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h8
-rw-r--r--src/core/hle/service/vi/vi.cpp46
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
369 hle/service/nvdrv/devices/nvmap.h 369 hle/service/nvdrv/devices/nvmap.h
370 hle/service/nvdrv/interface.cpp 370 hle/service/nvdrv/interface.cpp
371 hle/service/nvdrv/interface.h 371 hle/service/nvdrv/interface.h
372 hle/service/nvdrv/nvdata.h
372 hle/service/nvdrv/nvdrv.cpp 373 hle/service/nvdrv/nvdrv.cpp
373 hle/service/nvdrv/nvdrv.h 374 hle/service/nvdrv/nvdrv.h
374 hle/service/nvdrv/nvmemp.cpp 375 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
155 155
156 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); 156 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries));
157 157
158 params.fence_out.id = 0; 158 // TODO(Blinkhawk): Figure how thoios fence is set
159 params.fence_out.value = 0; 159 // params.fence_out.value = 0;
160 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo)); 160 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
161 return 0; 161 return 0;
162} 162}
@@ -176,8 +176,8 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
176 176
177 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); 177 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries));
178 178
179 params.fence_out.id = 0; 179 // TODO(Blinkhawk): Figure how thoios fence is set
180 params.fence_out.value = 0; 180 // params.fence_out.value = 0;
181 std::memcpy(output.data(), &params, output.size()); 181 std::memcpy(output.data(), &params, output.size());
182 return 0; 182 return 0;
183} 183}
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:
113 static_assert(sizeof(IoctlGetErrorNotification) == 16, 113 static_assert(sizeof(IoctlGetErrorNotification) == 16,
114 "IoctlGetErrorNotification is incorrect size"); 114 "IoctlGetErrorNotification is incorrect size");
115 115
116 struct IoctlFence { 116 struct Fence {
117 u32_le id; 117 u32_le id;
118 u32_le value; 118 u32_le value;
119 }; 119 };
120 static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size"); 120 static_assert(sizeof(Fence) == 8, "Fence is incorrect size");
121 121
122 struct IoctlAllocGpfifoEx { 122 struct IoctlAllocGpfifoEx {
123 u32_le num_entries; 123 u32_le num_entries;
@@ -132,13 +132,13 @@ private:
132 static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); 132 static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size");
133 133
134 struct IoctlAllocGpfifoEx2 { 134 struct IoctlAllocGpfifoEx2 {
135 u32_le num_entries; // in 135 u32_le num_entries; // in
136 u32_le flags; // in 136 u32_le flags; // in
137 u32_le unk0; // in (1 works) 137 u32_le unk0; // in (1 works)
138 IoctlFence fence_out; // out 138 Fence fence_out; // out
139 u32_le unk1; // in 139 u32_le unk1; // in
140 u32_le unk2; // in 140 u32_le unk2; // in
141 u32_le unk3; // in 141 u32_le unk3; // in
142 }; 142 };
143 static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); 143 static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size");
144 144
@@ -154,9 +154,9 @@ private:
154 u64_le address; // pointer to gpfifo entry structs 154 u64_le address; // pointer to gpfifo entry structs
155 u32_le num_entries; // number of fence objects being submitted 155 u32_le num_entries; // number of fence objects being submitted
156 u32_le flags; 156 u32_le flags;
157 IoctlFence fence_out; // returned new fence object for others to wait on 157 Fence fence_out; // returned new fence object for others to wait on
158 }; 158 };
159 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence), 159 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence),
160 "IoctlSubmitGpfifo is incorrect size"); 160 "IoctlSubmitGpfifo is incorrect size");
161 161
162 struct IoctlGetWaitbase { 162 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 @@
1#pragma once
2
3#include <array>
4#include "common/common_types.h"
5
6namespace Service::Nvidia {
7
8struct Fence {
9 s32 id;
10 u32 value;
11};
12
13static_assert(sizeof(Fence) == 8, "Fence has wrong size");
14
15struct MultiFence {
16 u32 num_fences;
17 std::array<Fence, 4> fences;
18};
19
20enum class NvResult : u32 {
21 Success = 0,
22 TryAgain = 11,
23};
24
25} // 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 @@
8#include <unordered_map> 8#include <unordered_map>
9#include <vector> 9#include <vector>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/service/nvdrv/nvdata.h"
11#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
12 13
13namespace Service::NVFlinger { 14namespace Service::NVFlinger {
@@ -20,13 +21,6 @@ namespace Devices {
20class nvdevice; 21class nvdevice;
21} 22}
22 23
23struct IoctlFence {
24 u32 id;
25 u32 value;
26};
27
28static_assert(sizeof(IoctlFence) == 8, "IoctlFence has wrong size");
29
30class Module final { 24class Module final {
31public: 25public:
32 Module(); 26 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)
34 buffer_wait_event.writable->Signal(); 34 buffer_wait_event.writable->Signal();
35} 35}
36 36
37std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) { 37std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
38 u32 height) {
38 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { 39 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
39 // Only consider free buffers. Buffers become free once again after they've been Acquired 40 // Only consider free buffers. Buffers become free once again after they've been Acquired
40 // and Released by the compositor, see the NVFlinger::Compose method. 41 // and Released by the compositor, see the NVFlinger::Compose method.
@@ -51,7 +52,7 @@ std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
51 } 52 }
52 53
53 itr->status = Buffer::Status::Dequeued; 54 itr->status = Buffer::Status::Dequeued;
54 return itr->slot; 55 return {{itr->slot, &itr->multi_fence}};
55} 56}
56 57
57const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { 58const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
@@ -63,7 +64,8 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
63} 64}
64 65
65void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, 66void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
66 const Common::Rectangle<int>& crop_rect, u32 swap_interval) { 67 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
68 Service::Nvidia::MultiFence& multi_fence) {
67 auto itr = std::find_if(queue.begin(), queue.end(), 69 auto itr = std::find_if(queue.begin(), queue.end(),
68 [&](const Buffer& buffer) { return buffer.slot == slot; }); 70 [&](const Buffer& buffer) { return buffer.slot == slot; });
69 ASSERT(itr != queue.end()); 71 ASSERT(itr != queue.end());
@@ -72,6 +74,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
72 itr->transform = transform; 74 itr->transform = transform;
73 itr->crop_rect = crop_rect; 75 itr->crop_rect = crop_rect;
74 itr->swap_interval = swap_interval; 76 itr->swap_interval = swap_interval;
77 itr->multi_fence = multi_fence;
75} 78}
76 79
77std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { 80std::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 @@
12#include "common/swap.h" 12#include "common/swap.h"
13#include "core/hle/kernel/object.h" 13#include "core/hle/kernel/object.h"
14#include "core/hle/kernel/writable_event.h" 14#include "core/hle/kernel/writable_event.h"
15#include "core/hle/service/nvdrv/nvdata.h"
15 16
16namespace Service::NVFlinger { 17namespace Service::NVFlinger {
17 18
@@ -69,13 +70,16 @@ public:
69 BufferTransformFlags transform; 70 BufferTransformFlags transform;
70 Common::Rectangle<int> crop_rect; 71 Common::Rectangle<int> crop_rect;
71 u32 swap_interval; 72 u32 swap_interval;
73 Service::Nvidia::MultiFence multi_fence;
72 }; 74 };
73 75
74 void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer); 76 void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
75 std::optional<u32> DequeueBuffer(u32 width, u32 height); 77 std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> DequeueBuffer(u32 width,
78 u32 height);
76 const IGBPBuffer& RequestBuffer(u32 slot) const; 79 const IGBPBuffer& RequestBuffer(u32 slot) const;
77 void QueueBuffer(u32 slot, BufferTransformFlags transform, 80 void QueueBuffer(u32 slot, BufferTransformFlags transform,
78 const Common::Rectangle<int>& crop_rect, u32 swap_interval); 81 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
82 Service::Nvidia::MultiFence& multi_fence);
79 std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer(); 83 std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
80 void ReleaseBuffer(u32 slot); 84 void ReleaseBuffer(u32 slot);
81 u32 Query(QueryType type); 85 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 @@
21#include "core/hle/kernel/readable_event.h" 21#include "core/hle/kernel/readable_event.h"
22#include "core/hle/kernel/thread.h" 22#include "core/hle/kernel/thread.h"
23#include "core/hle/kernel/writable_event.h" 23#include "core/hle/kernel/writable_event.h"
24#include "core/hle/service/nvdrv/nvdata.h"
24#include "core/hle/service/nvdrv/nvdrv.h" 25#include "core/hle/service/nvdrv/nvdrv.h"
25#include "core/hle/service/nvflinger/buffer_queue.h" 26#include "core/hle/service/nvflinger/buffer_queue.h"
26#include "core/hle/service/nvflinger/nvflinger.h" 27#include "core/hle/service/nvflinger/nvflinger.h"
@@ -328,32 +329,22 @@ public:
328 Data data; 329 Data data;
329}; 330};
330 331
331struct BufferProducerFence {
332 u32 is_valid;
333 std::array<Nvidia::IoctlFence, 4> fences;
334};
335static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong size");
336
337class IGBPDequeueBufferResponseParcel : public Parcel { 332class IGBPDequeueBufferResponseParcel : public Parcel {
338public: 333public:
339 explicit IGBPDequeueBufferResponseParcel(u32 slot) : slot(slot) {} 334 explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence)
335 : slot(slot), multi_fence(multi_fence) {}
340 ~IGBPDequeueBufferResponseParcel() override = default; 336 ~IGBPDequeueBufferResponseParcel() override = default;
341 337
342protected: 338protected:
343 void SerializeData() override { 339 void SerializeData() override {
344 // TODO(Subv): Find out how this Fence is used.
345 BufferProducerFence fence = {};
346 fence.is_valid = 1;
347 for (auto& fence_ : fence.fences)
348 fence_.id = -1;
349
350 Write(slot); 340 Write(slot);
351 Write<u32_le>(1); 341 Write<u32_le>(1);
352 WriteObject(fence); 342 WriteObject(multi_fence);
353 Write<u32_le>(0); 343 Write<u32_le>(0);
354 } 344 }
355 345
356 u32_le slot; 346 u32_le slot;
347 Service::Nvidia::MultiFence multi_fence;
357}; 348};
358 349
359class IGBPRequestBufferRequestParcel : public Parcel { 350class IGBPRequestBufferRequestParcel : public Parcel {
@@ -400,12 +391,6 @@ public:
400 data = Read<Data>(); 391 data = Read<Data>();
401 } 392 }
402 393
403 struct Fence {
404 u32_le id;
405 u32_le value;
406 };
407 static_assert(sizeof(Fence) == 8, "Fence has wrong size");
408
409 struct Data { 394 struct Data {
410 u32_le slot; 395 u32_le slot;
411 INSERT_PADDING_WORDS(3); 396 INSERT_PADDING_WORDS(3);
@@ -420,14 +405,13 @@ public:
420 u32_le sticky_transform; 405 u32_le sticky_transform;
421 INSERT_PADDING_WORDS(1); 406 INSERT_PADDING_WORDS(1);
422 u32_le swap_interval; 407 u32_le swap_interval;
423 u32_le fence_is_valid; 408 Service::Nvidia::MultiFence multi_fence;
424 std::array<Fence, 2> fences;
425 409
426 Common::Rectangle<int> GetCropRect() const { 410 Common::Rectangle<int> GetCropRect() const {
427 return {crop_left, crop_top, crop_right, crop_bottom}; 411 return {crop_left, crop_top, crop_right, crop_bottom};
428 } 412 }
429 }; 413 };
430 static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); 414 static_assert(sizeof(Data) == 96, "ParcelData has wrong size");
431 415
432 Data data; 416 Data data;
433}; 417};
@@ -548,11 +532,11 @@ private:
548 IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; 532 IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
549 const u32 width{request.data.width}; 533 const u32 width{request.data.width};
550 const u32 height{request.data.height}; 534 const u32 height{request.data.height};
551 std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); 535 auto result = buffer_queue.DequeueBuffer(width, height);
552 536
553 if (slot) { 537 if (result) {
554 // Buffer is available 538 // Buffer is available
555 IGBPDequeueBufferResponseParcel response{*slot}; 539 IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second};
556 ctx.WriteBuffer(response.Serialize()); 540 ctx.WriteBuffer(response.Serialize());
557 } else { 541 } else {
558 // Wait the current thread until a buffer becomes available 542 // Wait the current thread until a buffer becomes available
@@ -562,10 +546,11 @@ private:
562 Kernel::ThreadWakeupReason reason) { 546 Kernel::ThreadWakeupReason reason) {
563 // Repeat TransactParcel DequeueBuffer when a buffer is available 547 // Repeat TransactParcel DequeueBuffer when a buffer is available
564 auto& buffer_queue = nv_flinger->FindBufferQueue(id); 548 auto& buffer_queue = nv_flinger->FindBufferQueue(id);
565 std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); 549 auto result = buffer_queue.DequeueBuffer(width, height);
566 ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); 550 ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
567 551
568 IGBPDequeueBufferResponseParcel response{*slot}; 552 IGBPDequeueBufferResponseParcel response{(*result).first,
553 *(*result).second};
569 ctx.WriteBuffer(response.Serialize()); 554 ctx.WriteBuffer(response.Serialize());
570 IPC::ResponseBuilder rb{ctx, 2}; 555 IPC::ResponseBuilder rb{ctx, 2};
571 rb.Push(RESULT_SUCCESS); 556 rb.Push(RESULT_SUCCESS);
@@ -583,7 +568,8 @@ private:
583 IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; 568 IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
584 569
585 buffer_queue.QueueBuffer(request.data.slot, request.data.transform, 570 buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
586 request.data.GetCropRect(), request.data.swap_interval); 571 request.data.GetCropRect(), request.data.swap_interval,
572 request.data.multi_fence);
587 573
588 IGBPQueueBufferResponseParcel response{1280, 720}; 574 IGBPQueueBufferResponseParcel response{1280, 720};
589 ctx.WriteBuffer(response.Serialize()); 575 ctx.WriteBuffer(response.Serialize());