mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	video_core: Implement GPU side Syncpoints
This commit is contained in:
		
							parent
							
								
									737e978f5b
								
							
						
					
					
						commit
						82b829625b
					
				| @ -143,7 +143,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp | |||||||
|     IoctlSubmitGpfifo params{}; |     IoctlSubmitGpfifo params{}; | ||||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); |     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", |     LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", | ||||||
|                 params.address, params.num_entries, params.flags); |                 params.address, params.num_entries, params.flags.raw); | ||||||
| 
 | 
 | ||||||
|     ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) + |     ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) + | ||||||
|                                    params.num_entries * sizeof(Tegra::CommandListHeader), |                                    params.num_entries * sizeof(Tegra::CommandListHeader), | ||||||
| @ -153,7 +153,17 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp | |||||||
|     std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], |     std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], | ||||||
|                 params.num_entries * sizeof(Tegra::CommandListHeader)); |                 params.num_entries * sizeof(Tegra::CommandListHeader)); | ||||||
| 
 | 
 | ||||||
|     Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); |     UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); | ||||||
|  |     UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); | ||||||
|  | 
 | ||||||
|  |     auto& gpu = Core::System::GetInstance().GPU(); | ||||||
|  |     u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); | ||||||
|  |     if (params.flags.increment.Value()) { | ||||||
|  |         params.fence_out.value += current_syncpoint_value; | ||||||
|  |     } else { | ||||||
|  |         params.fence_out.value = current_syncpoint_value; | ||||||
|  |     } | ||||||
|  |     gpu.PushGPUEntries(std::move(entries)); | ||||||
| 
 | 
 | ||||||
|     // TODO(Blinkhawk): Figure how thoios fence is set
 |     // TODO(Blinkhawk): Figure how thoios fence is set
 | ||||||
|     // params.fence_out.value = 0;
 |     // params.fence_out.value = 0;
 | ||||||
| @ -168,16 +178,24 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) | |||||||
|     IoctlSubmitGpfifo params{}; |     IoctlSubmitGpfifo params{}; | ||||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); |     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", |     LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", | ||||||
|                 params.address, params.num_entries, params.flags); |                 params.address, params.num_entries, params.flags.raw); | ||||||
| 
 | 
 | ||||||
|     Tegra::CommandList entries(params.num_entries); |     Tegra::CommandList entries(params.num_entries); | ||||||
|     Memory::ReadBlock(params.address, entries.data(), |     Memory::ReadBlock(params.address, entries.data(), | ||||||
|                       params.num_entries * sizeof(Tegra::CommandListHeader)); |                       params.num_entries * sizeof(Tegra::CommandListHeader)); | ||||||
| 
 | 
 | ||||||
|     Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); |     UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); | ||||||
|  |     UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); | ||||||
|  | 
 | ||||||
|  |     auto& gpu = Core::System::GetInstance().GPU(); | ||||||
|  |     u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); | ||||||
|  |     if (params.flags.increment.Value()) { | ||||||
|  |         params.fence_out.value += current_syncpoint_value; | ||||||
|  |     } else { | ||||||
|  |         params.fence_out.value = current_syncpoint_value; | ||||||
|  |     } | ||||||
|  |     gpu.PushGPUEntries(std::move(entries)); | ||||||
| 
 | 
 | ||||||
|     // TODO(Blinkhawk): Figure how thoios fence is set
 |  | ||||||
|     // params.fence_out.value = 0;
 |  | ||||||
|     std::memcpy(output.data(), ¶ms, output.size()); |     std::memcpy(output.data(), ¶ms, output.size()); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | |||||||
| @ -153,7 +153,13 @@ private: | |||||||
|     struct IoctlSubmitGpfifo { |     struct IoctlSubmitGpfifo { | ||||||
|         u64_le address;     // pointer to gpfifo entry structs
 |         u64_le address;     // pointer to gpfifo entry structs
 | ||||||
|         u32_le num_entries; // number of fence objects being submitted
 |         u32_le num_entries; // number of fence objects being submitted
 | ||||||
|         u32_le flags; |         union { | ||||||
|  |             u32_le raw; | ||||||
|  |             BitField<0, 1, u32_le> add_wait;      // append a wait sync_point to the list
 | ||||||
|  |             BitField<1, 1, u32_le> add_increment; // append an increment to the list
 | ||||||
|  |             BitField<2, 1, u32_le> new_hw_format; // Mostly ignored
 | ||||||
|  |             BitField<8, 1, u32_le> increment;     // increment the returned fence
 | ||||||
|  |         } flags; | ||||||
|         Fence 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(Fence), |     static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ | |||||||
| 
 | 
 | ||||||
| namespace Service::Nvidia { | namespace Service::Nvidia { | ||||||
| 
 | 
 | ||||||
|  | constexpr u32 MaxSyncPoints = 192; | ||||||
|  | 
 | ||||||
| struct Fence { | struct Fence { | ||||||
|     s32 id; |     s32 id; | ||||||
|     u32 value; |     u32 value; | ||||||
|  | |||||||
| @ -346,8 +346,9 @@ void Maxwell3D::ProcessSyncPoint() { | |||||||
|     const u32 sync_point = regs.sync_info.sync_point.Value(); |     const u32 sync_point = regs.sync_info.sync_point.Value(); | ||||||
|     const u32 increment = regs.sync_info.increment.Value(); |     const u32 increment = regs.sync_info.increment.Value(); | ||||||
|     const u32 cache_flush = regs.sync_info.unknown.Value(); |     const u32 cache_flush = regs.sync_info.unknown.Value(); | ||||||
|     LOG_DEBUG(HW_GPU, "Syncpoint set {}, increment: {}, unk: {}", sync_point, increment, |     if (increment) { | ||||||
|               cache_flush); |         system.GPU().IncrementSyncPoint(sync_point); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Maxwell3D::DrawArrays() { | void Maxwell3D::DrawArrays() { | ||||||
|  | |||||||
| @ -66,6 +66,30 @@ const DmaPusher& GPU::DmaPusher() const { | |||||||
|     return *dma_pusher; |     return *dma_pusher; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void GPU::IncrementSyncPoint(const u32 syncpoint_id) { | ||||||
|  |     syncpoints[syncpoint_id]++; | ||||||
|  |     if (!events[syncpoint_id].empty()) { | ||||||
|  |         u32 value = syncpoints[syncpoint_id].load(); | ||||||
|  |         auto it = events[syncpoint_id].begin(); | ||||||
|  |         while (it != events[syncpoint_id].end()) { | ||||||
|  |             if (value >= it->value) { | ||||||
|  |                 TriggerCpuInterrupt(it->event_id); | ||||||
|  |                 it = events[syncpoint_id].erase(it); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             it++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { | ||||||
|  |     return syncpoints[syncpoint_id].load(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { | ||||||
|  |     events[syncpoint_id].emplace_back(event_id, value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | ||||||
|     ASSERT(format != RenderTargetFormat::NONE); |     ASSERT(format != RenderTargetFormat::NONE); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,8 +5,11 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
|  | #include <atomic> | ||||||
|  | #include <list> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "core/hle/service/nvdrv/nvdata.h" | ||||||
| #include "core/hle/service/nvflinger/buffer_queue.h" | #include "core/hle/service/nvflinger/buffer_queue.h" | ||||||
| #include "video_core/dma_pusher.h" | #include "video_core/dma_pusher.h" | ||||||
| 
 | 
 | ||||||
| @ -164,6 +167,12 @@ public: | |||||||
|     /// Returns a reference to the GPU DMA pusher.
 |     /// Returns a reference to the GPU DMA pusher.
 | ||||||
|     Tegra::DmaPusher& DmaPusher(); |     Tegra::DmaPusher& DmaPusher(); | ||||||
| 
 | 
 | ||||||
|  |     void IncrementSyncPoint(const u32 syncpoint_id); | ||||||
|  | 
 | ||||||
|  |     u32 GetSyncpointValue(const u32 syncpoint_id) const; | ||||||
|  | 
 | ||||||
|  |     void RegisterEvent(const u32 event_id, const u32 sync_point_id, const u32 value); | ||||||
|  | 
 | ||||||
|     /// Returns a const reference to the GPU DMA pusher.
 |     /// Returns a const reference to the GPU DMA pusher.
 | ||||||
|     const Tegra::DmaPusher& DmaPusher() const; |     const Tegra::DmaPusher& DmaPusher() const; | ||||||
| 
 | 
 | ||||||
| @ -228,6 +237,11 @@ public: | |||||||
|     /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
 |     /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
 | ||||||
|     virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; |     virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; | ||||||
| 
 | 
 | ||||||
|  | protected: | ||||||
|  |     virtual void TriggerCpuInterrupt(const u32 event_id) const { | ||||||
|  |         // Todo implement this
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     void ProcessBindMethod(const MethodCall& method_call); |     void ProcessBindMethod(const MethodCall& method_call); | ||||||
|     void ProcessSemaphoreTriggerMethod(); |     void ProcessSemaphoreTriggerMethod(); | ||||||
| @ -262,6 +276,16 @@ private: | |||||||
|     std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; |     std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; | ||||||
|     /// Inline memory engine
 |     /// Inline memory engine
 | ||||||
|     std::unique_ptr<Engines::KeplerMemory> kepler_memory; |     std::unique_ptr<Engines::KeplerMemory> kepler_memory; | ||||||
|  | 
 | ||||||
|  |     std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; | ||||||
|  | 
 | ||||||
|  |     struct Event { | ||||||
|  |         Event(const u32 event_id, const u32 value) : event_id(event_id), value(value) {} | ||||||
|  |         u32 event_id; | ||||||
|  |         u32 value; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     std::array<std::list<Event>, Service::Nvidia::MaxSyncPoints> events; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define ASSERT_REG_POSITION(field_name, position)                                                  \ | #define ASSERT_REG_POSITION(field_name, position)                                                  \ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Fernando Sahmkow
						Fernando Sahmkow