diff options
| author | 2020-10-29 21:13:04 -0700 | |
|---|---|---|
| committer | 2020-11-01 01:52:38 -0700 | |
| commit | c64545d07ae57816bc658ca7c45559d0b0d49f89 (patch) | |
| tree | 37642d8f8e2d870637c64d7ca89fa0098afa54fb | |
| parent | service: hle: nvflinger: Fix potential shutdown crash when GPU is destroyed. (diff) | |
| download | yuzu-c64545d07ae57816bc658ca7c45559d0b0d49f89.tar.gz yuzu-c64545d07ae57816bc658ca7c45559d0b0d49f89.tar.xz yuzu-c64545d07ae57816bc658ca7c45559d0b0d49f89.zip | |
video_core: dma_pusher: Add support for prefetched command lists.
| -rw-r--r-- | src/video_core/dma_pusher.cpp | 56 | ||||
| -rw-r--r-- | src/video_core/dma_pusher.h | 21 |
2 files changed, 52 insertions, 25 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index f2f96ac33..9c49c6153 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp | |||
| @@ -45,32 +45,42 @@ bool DmaPusher::Step() { | |||
| 45 | return false; | 45 | return false; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | const CommandList& command_list{dma_pushbuffer.front()}; | 48 | CommandList& command_list{dma_pushbuffer.front()}; |
| 49 | ASSERT_OR_EXECUTE(!command_list.empty(), { | 49 | |
| 50 | // Somehow the command_list is empty, in order to avoid a crash | 50 | ASSERT_OR_EXECUTE( |
| 51 | // We ignore it and assume its size is 0. | 51 | command_list.command_lists.size() || command_list.prefetch_command_list.size(), { |
| 52 | // Somehow the command_list is empty, in order to avoid a crash | ||
| 53 | // We ignore it and assume its size is 0. | ||
| 54 | dma_pushbuffer.pop(); | ||
| 55 | dma_pushbuffer_subindex = 0; | ||
| 56 | return true; | ||
| 57 | }); | ||
| 58 | |||
| 59 | if (command_list.prefetch_command_list.size()) { | ||
| 60 | // Prefetched command list from nvdrv, used for things like synchronization | ||
| 61 | command_headers = std::move(command_list.prefetch_command_list); | ||
| 52 | dma_pushbuffer.pop(); | 62 | dma_pushbuffer.pop(); |
| 53 | dma_pushbuffer_subindex = 0; | 63 | } else { |
| 54 | return true; | 64 | const CommandListHeader command_list_header{ |
| 55 | }); | 65 | command_list.command_lists[dma_pushbuffer_subindex]}; |
| 56 | const CommandListHeader command_list_header{command_list[dma_pushbuffer_subindex++]}; | 66 | const u64 next_hash = command_list.command_list_hashes[dma_pushbuffer_subindex++]; |
| 57 | const GPUVAddr dma_get = command_list_header.addr; | 67 | const GPUVAddr dma_get = command_list_header.addr; |
| 58 | 68 | ||
| 59 | if (dma_pushbuffer_subindex >= command_list.size()) { | 69 | if (dma_pushbuffer_subindex >= command_list.command_lists.size()) { |
| 60 | // We've gone through the current list, remove it from the queue | 70 | // We've gone through the current list, remove it from the queue |
| 61 | dma_pushbuffer.pop(); | 71 | dma_pushbuffer.pop(); |
| 62 | dma_pushbuffer_subindex = 0; | 72 | dma_pushbuffer_subindex = 0; |
| 63 | } | 73 | } |
| 64 | |||
| 65 | if (command_list_header.size == 0) { | ||
| 66 | return true; | ||
| 67 | } | ||
| 68 | 74 | ||
| 69 | // Push buffer non-empty, read a word | 75 | if (command_list_header.size == 0) { |
| 70 | command_headers.resize(command_list_header.size); | 76 | return true; |
| 71 | gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(), | 77 | } |
| 72 | command_list_header.size * sizeof(u32)); | ||
| 73 | 78 | ||
| 79 | // Push buffer non-empty, read a word | ||
| 80 | command_headers.resize(command_list_header.size); | ||
| 81 | gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(), | ||
| 82 | command_list_header.size * sizeof(u32)); | ||
| 83 | } | ||
| 74 | for (std::size_t index = 0; index < command_headers.size();) { | 84 | for (std::size_t index = 0; index < command_headers.size();) { |
| 75 | const CommandHeader& command_header = command_headers[index]; | 85 | const CommandHeader& command_header = command_headers[index]; |
| 76 | 86 | ||
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h index 2026b7857..99b30ca0d 100644 --- a/src/video_core/dma_pusher.h +++ b/src/video_core/dma_pusher.h | |||
| @@ -74,9 +74,26 @@ union CommandHeader { | |||
| 74 | static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout"); | 74 | static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout"); |
| 75 | static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); | 75 | static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); |
| 76 | 76 | ||
| 77 | static constexpr CommandHeader BuildCommandHeader(BufferMethods method, u32 arg_count, | ||
| 78 | SubmissionMode mode) { | ||
| 79 | CommandHeader result{}; | ||
| 80 | result.method.Assign(static_cast<u32>(method)); | ||
| 81 | result.arg_count.Assign(arg_count); | ||
| 82 | result.mode.Assign(mode); | ||
| 83 | return result; | ||
| 84 | } | ||
| 85 | |||
| 77 | class GPU; | 86 | class GPU; |
| 78 | 87 | ||
| 79 | using CommandList = std::vector<Tegra::CommandListHeader>; | 88 | struct CommandList final { |
| 89 | CommandList() = default; | ||
| 90 | explicit CommandList(std::size_t size) : command_lists(size) {} | ||
| 91 | explicit CommandList(std::vector<Tegra::CommandHeader>&& prefetch_command_list) | ||
| 92 | : prefetch_command_list{std::move(prefetch_command_list)} {} | ||
| 93 | |||
| 94 | std::vector<Tegra::CommandListHeader> command_lists; | ||
| 95 | std::vector<Tegra::CommandHeader> prefetch_command_list; | ||
| 96 | }; | ||
| 80 | 97 | ||
| 81 | /** | 98 | /** |
| 82 | * The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the | 99 | * The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the |
| @@ -85,7 +102,7 @@ using CommandList = std::vector<Tegra::CommandListHeader>; | |||
| 85 | * See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for | 102 | * See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for |
| 86 | * details on this implementation. | 103 | * details on this implementation. |
| 87 | */ | 104 | */ |
| 88 | class DmaPusher { | 105 | class DmaPusher final { |
| 89 | public: | 106 | public: |
| 90 | explicit DmaPusher(Core::System& system, GPU& gpu); | 107 | explicit DmaPusher(Core::System& system, GPU& gpu); |
| 91 | ~DmaPusher(); | 108 | ~DmaPusher(); |