diff options
| author | 2021-12-02 12:19:43 +0800 | |
|---|---|---|
| committer | 2021-12-02 12:48:42 +0800 | |
| commit | 2c47f8aa1886522898b5b3a73185b5662be3e9f3 (patch) | |
| tree | badff9fee7c63a693fd9da3c6fb2cfe34d2d9ed1 | |
| parent | Merge pull request #7483 from zhaobot/tx-update-20211201022129 (diff) | |
| download | yuzu-2c47f8aa1886522898b5b3a73185b5662be3e9f3.tar.gz yuzu-2c47f8aa1886522898b5b3a73185b5662be3e9f3.tar.xz yuzu-2c47f8aa1886522898b5b3a73185b5662be3e9f3.zip | |
Support multiple videos playing
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 43 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 4 |
6 files changed, 36 insertions, 41 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 0d7d4ad03..8e2a16d86 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -21,7 +21,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& | |||
| 21 | case 0x0: | 21 | case 0x0: |
| 22 | switch (command.cmd) { | 22 | switch (command.cmd) { |
| 23 | case 0x1: | 23 | case 0x1: |
| 24 | return Submit(input, output); | 24 | return Submit(fd, input, output); |
| 25 | case 0x2: | 25 | case 0x2: |
| 26 | return GetSyncpoint(input, output); | 26 | return GetSyncpoint(input, output); |
| 27 | case 0x3: | 27 | case 0x3: |
| @@ -62,11 +62,16 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& | |||
| 62 | return NvResult::NotImplemented; | 62 | return NvResult::NotImplemented; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void nvhost_nvdec::OnOpen(DeviceFD fd) {} | 65 | void nvhost_nvdec::OnOpen(DeviceFD fd) { |
| 66 | static u32 next_id{}; | ||
| 67 | fd_to_id[fd] = next_id++; | ||
| 68 | } | ||
| 66 | 69 | ||
| 67 | void nvhost_nvdec::OnClose(DeviceFD fd) { | 70 | void nvhost_nvdec::OnClose(DeviceFD fd) { |
| 68 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); | 71 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); |
| 69 | system.GPU().ClearCdmaInstance(); | 72 | if (fd_to_id.find(fd) != fd_to_id.end()) { |
| 73 | system.GPU().ClearCdmaInstance(fd_to_id[fd]); | ||
| 74 | } | ||
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | } // namespace Service::Nvidia::Devices | 77 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index e61261f98..8a05f0668 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -59,7 +59,8 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { | |||
| 59 | return NvResult::Success; | 59 | return NvResult::Success; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { | 62 | NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, |
| 63 | std::vector<u8>& output) { | ||
| 63 | IoctlSubmit params{}; | 64 | IoctlSubmit params{}; |
| 64 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | 65 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); |
| 65 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | 66 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); |
| @@ -93,7 +94,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u | |||
| 93 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); | 94 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); |
| 94 | system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(), | 95 | system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(), |
| 95 | cmdlist.size() * sizeof(u32)); | 96 | cmdlist.size() * sizeof(u32)); |
| 96 | gpu.PushCommandBuffer(cmdlist); | 97 | gpu.PushCommandBuffer(fd_to_id[fd], cmdlist); |
| 97 | } | 98 | } |
| 98 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | 99 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); |
| 99 | // Some games expect command_buffers to be written back | 100 | // Some games expect command_buffers to be written back |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 351625c17..e28c54df6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -104,13 +104,14 @@ protected: | |||
| 104 | 104 | ||
| 105 | /// Ioctl command implementations | 105 | /// Ioctl command implementations |
| 106 | NvResult SetNVMAPfd(const std::vector<u8>& input); | 106 | NvResult SetNVMAPfd(const std::vector<u8>& input); |
| 107 | NvResult Submit(const std::vector<u8>& input, std::vector<u8>& output); | 107 | NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output); |
| 108 | NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); | 108 | NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); |
| 109 | NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | 109 | NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); |
| 110 | NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | 110 | NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); |
| 111 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | 111 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); |
| 112 | NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); | 112 | NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); |
| 113 | 113 | ||
| 114 | std::unordered_map<DeviceFD, u32> fd_to_id{}; | ||
| 114 | s32_le nvmap_fd{}; | 115 | s32_le nvmap_fd{}; |
| 115 | u32_le submit_timeout{}; | 116 | u32_le submit_timeout{}; |
| 116 | std::shared_ptr<nvmap> nvmap_dev; | 117 | std::shared_ptr<nvmap> nvmap_dev; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index eac4dd530..420fe21c8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -21,7 +21,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i | |||
| 21 | case 0x0: | 21 | case 0x0: |
| 22 | switch (command.cmd) { | 22 | switch (command.cmd) { |
| 23 | case 0x1: | 23 | case 0x1: |
| 24 | return Submit(input, output); | 24 | return Submit(fd, input, output); |
| 25 | case 0x2: | 25 | case 0x2: |
| 26 | return GetSyncpoint(input, output); | 26 | return GetSyncpoint(input, output); |
| 27 | case 0x3: | 27 | case 0x3: |
| @@ -62,10 +62,15 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i | |||
| 62 | return NvResult::NotImplemented; | 62 | return NvResult::NotImplemented; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void nvhost_vic::OnOpen(DeviceFD fd) {} | 65 | void nvhost_vic::OnOpen(DeviceFD fd) { |
| 66 | static u32 next_id{}; | ||
| 67 | fd_to_id[fd] = next_id++; | ||
| 68 | } | ||
| 66 | 69 | ||
| 67 | void nvhost_vic::OnClose(DeviceFD fd) { | 70 | void nvhost_vic::OnClose(DeviceFD fd) { |
| 68 | system.GPU().ClearCdmaInstance(); | 71 | if (fd_to_id.find(fd) != fd_to_id.end()) { |
| 72 | system.GPU().ClearCdmaInstance(fd_to_id[fd]); | ||
| 73 | } | ||
| 69 | } | 74 | } |
| 70 | 75 | ||
| 71 | } // namespace Service::Nvidia::Devices | 76 | } // namespace Service::Nvidia::Devices |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index ab7c21a49..27a47954d 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -185,16 +185,6 @@ struct GPU::Impl { | |||
| 185 | return *dma_pusher; | 185 | return *dma_pusher; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | /// Returns a reference to the GPU CDMA pusher. | ||
| 189 | [[nodiscard]] Tegra::CDmaPusher& CDmaPusher() { | ||
| 190 | return *cdma_pusher; | ||
| 191 | } | ||
| 192 | |||
| 193 | /// Returns a const reference to the GPU CDMA pusher. | ||
| 194 | [[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const { | ||
| 195 | return *cdma_pusher; | ||
| 196 | } | ||
| 197 | |||
| 198 | /// Returns a reference to the underlying renderer. | 188 | /// Returns a reference to the underlying renderer. |
| 199 | [[nodiscard]] VideoCore::RendererBase& Renderer() { | 189 | [[nodiscard]] VideoCore::RendererBase& Renderer() { |
| 200 | return *renderer; | 190 | return *renderer; |
| @@ -338,25 +328,26 @@ struct GPU::Impl { | |||
| 338 | } | 328 | } |
| 339 | 329 | ||
| 340 | /// Push GPU command buffer entries to be processed | 330 | /// Push GPU command buffer entries to be processed |
| 341 | void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { | 331 | void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) { |
| 342 | if (!use_nvdec) { | 332 | if (!use_nvdec) { |
| 343 | return; | 333 | return; |
| 344 | } | 334 | } |
| 345 | 335 | ||
| 346 | if (!cdma_pusher) { | 336 | if (cdma_pushers.find(id) == cdma_pushers.end()) { |
| 347 | cdma_pusher = std::make_unique<Tegra::CDmaPusher>(gpu); | 337 | cdma_pushers[id] = std::make_unique<Tegra::CDmaPusher>(gpu); |
| 348 | } | 338 | } |
| 349 | 339 | ||
| 350 | // SubmitCommandBuffer would make the nvdec operations async, this is not currently working | 340 | // SubmitCommandBuffer would make the nvdec operations async, this is not currently working |
| 351 | // TODO(ameerj): RE proper async nvdec operation | 341 | // TODO(ameerj): RE proper async nvdec operation |
| 352 | // gpu_thread.SubmitCommandBuffer(std::move(entries)); | 342 | // gpu_thread.SubmitCommandBuffer(std::move(entries)); |
| 353 | 343 | cdma_pushers[id]->ProcessEntries(std::move(entries)); | |
| 354 | cdma_pusher->ProcessEntries(std::move(entries)); | ||
| 355 | } | 344 | } |
| 356 | 345 | ||
| 357 | /// Frees the CDMAPusher instance to free up resources | 346 | /// Frees the CDMAPusher instance to free up resources |
| 358 | void ClearCdmaInstance() { | 347 | void ClearCdmaInstance(u32 id) { |
| 359 | cdma_pusher.reset(); | 348 | if (cdma_pushers.find(id) != cdma_pushers.end()) { |
| 349 | cdma_pushers.erase(id); | ||
| 350 | } | ||
| 360 | } | 351 | } |
| 361 | 352 | ||
| 362 | /// Swap buffers (render frame) | 353 | /// Swap buffers (render frame) |
| @@ -659,7 +650,7 @@ struct GPU::Impl { | |||
| 659 | Core::System& system; | 650 | Core::System& system; |
| 660 | std::unique_ptr<Tegra::MemoryManager> memory_manager; | 651 | std::unique_ptr<Tegra::MemoryManager> memory_manager; |
| 661 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | 652 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; |
| 662 | std::unique_ptr<Tegra::CDmaPusher> cdma_pusher; | 653 | std::map<u32, std::unique_ptr<Tegra::CDmaPusher>> cdma_pushers; |
| 663 | std::unique_ptr<VideoCore::RendererBase> renderer; | 654 | std::unique_ptr<VideoCore::RendererBase> renderer; |
| 664 | VideoCore::RasterizerInterface* rasterizer = nullptr; | 655 | VideoCore::RasterizerInterface* rasterizer = nullptr; |
| 665 | const bool use_nvdec; | 656 | const bool use_nvdec; |
| @@ -811,14 +802,6 @@ const Tegra::DmaPusher& GPU::DmaPusher() const { | |||
| 811 | return impl->DmaPusher(); | 802 | return impl->DmaPusher(); |
| 812 | } | 803 | } |
| 813 | 804 | ||
| 814 | Tegra::CDmaPusher& GPU::CDmaPusher() { | ||
| 815 | return impl->CDmaPusher(); | ||
| 816 | } | ||
| 817 | |||
| 818 | const Tegra::CDmaPusher& GPU::CDmaPusher() const { | ||
| 819 | return impl->CDmaPusher(); | ||
| 820 | } | ||
| 821 | |||
| 822 | VideoCore::RendererBase& GPU::Renderer() { | 805 | VideoCore::RendererBase& GPU::Renderer() { |
| 823 | return impl->Renderer(); | 806 | return impl->Renderer(); |
| 824 | } | 807 | } |
| @@ -887,12 +870,12 @@ void GPU::PushGPUEntries(Tegra::CommandList&& entries) { | |||
| 887 | impl->PushGPUEntries(std::move(entries)); | 870 | impl->PushGPUEntries(std::move(entries)); |
| 888 | } | 871 | } |
| 889 | 872 | ||
| 890 | void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { | 873 | void GPU::PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) { |
| 891 | impl->PushCommandBuffer(entries); | 874 | impl->PushCommandBuffer(id, entries); |
| 892 | } | 875 | } |
| 893 | 876 | ||
| 894 | void GPU::ClearCdmaInstance() { | 877 | void GPU::ClearCdmaInstance(u32 id) { |
| 895 | impl->ClearCdmaInstance(); | 878 | impl->ClearCdmaInstance(id); |
| 896 | } | 879 | } |
| 897 | 880 | ||
| 898 | void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | 881 | void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index c89a5d693..500411176 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -242,10 +242,10 @@ public: | |||
| 242 | void PushGPUEntries(Tegra::CommandList&& entries); | 242 | void PushGPUEntries(Tegra::CommandList&& entries); |
| 243 | 243 | ||
| 244 | /// Push GPU command buffer entries to be processed | 244 | /// Push GPU command buffer entries to be processed |
| 245 | void PushCommandBuffer(Tegra::ChCommandHeaderList& entries); | 245 | void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries); |
| 246 | 246 | ||
| 247 | /// Frees the CDMAPusher instance to free up resources | 247 | /// Frees the CDMAPusher instance to free up resources |
| 248 | void ClearCdmaInstance(); | 248 | void ClearCdmaInstance(u32 id); |
| 249 | 249 | ||
| 250 | /// Swap buffers (render frame) | 250 | /// Swap buffers (render frame) |
| 251 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); | 251 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); |