summaryrefslogtreecommitdiffstats
path: root/src/video_core/dma_pusher.h
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-11-28 16:12:37 +0100
committerGitHub <noreply@github.com>2018-11-28 16:12:37 +0100
commit6f849887c9e7fa51743809c3a4bcfd2e319dff8d (patch)
treeba26ea7fcb626dacab4b7997149ad52c21ba526c /src/video_core/dma_pusher.h
parentMerge pull request #1735 from FernandoS27/tex-spacing (diff)
parentdma_pushbuffer: Optimize to avoid loop and copy on Push. (diff)
downloadyuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar.gz
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar.bz2
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar.lz
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar.xz
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.tar.zst
yuzu-6f849887c9e7fa51743809c3a4bcfd2e319dff8d.zip
Diffstat (limited to 'src/video_core/dma_pusher.h')
-rw-r--r--src/video_core/dma_pusher.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
new file mode 100644
index 000000000..16e0697c4
--- /dev/null
+++ b/src/video_core/dma_pusher.h
@@ -0,0 +1,99 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include <queue>
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "video_core/memory_manager.h"
+
+namespace Tegra {
+
+enum class SubmissionMode : u32 {
+ IncreasingOld = 0,
+ Increasing = 1,
+ NonIncreasingOld = 2,
+ NonIncreasing = 3,
+ Inline = 4,
+ IncreaseOnce = 5
+};
+
+struct CommandListHeader {
+ union {
+ u64 raw;
+ BitField<0, 40, GPUVAddr> addr;
+ BitField<41, 1, u64> is_non_main;
+ BitField<42, 21, u64> size;
+ };
+};
+static_assert(sizeof(CommandListHeader) == sizeof(u64), "CommandListHeader is incorrect size");
+
+union CommandHeader {
+ u32 argument;
+ BitField<0, 13, u32> method;
+ BitField<0, 24, u32> method_count_;
+ BitField<13, 3, u32> subchannel;
+ BitField<16, 13, u32> arg_count;
+ BitField<16, 13, u32> method_count;
+ BitField<29, 3, SubmissionMode> mode;
+};
+static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout");
+static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
+
+class GPU;
+
+using CommandList = std::vector<Tegra::CommandListHeader>;
+
+/**
+ * The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the
+ * emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled
+ * into a "command stream" consisting of 32-bit words that make up "commands".
+ * See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for
+ * details on this implementation.
+ */
+class DmaPusher {
+public:
+ explicit DmaPusher(GPU& gpu);
+ ~DmaPusher();
+
+ void Push(CommandList&& entries) {
+ dma_pushbuffer.push(std::move(entries));
+ }
+
+ void DispatchCalls();
+
+private:
+ bool Step();
+
+ void SetState(const CommandHeader& command_header);
+
+ void CallMethod(u32 argument) const;
+
+ GPU& gpu;
+
+ std::queue<CommandList> dma_pushbuffer; ///< Queue of command lists to be processed
+ std::size_t dma_pushbuffer_subindex{}; ///< Index within a command list within the pushbuffer
+
+ struct DmaState {
+ u32 method; ///< Current method
+ u32 subchannel; ///< Current subchannel
+ u32 method_count; ///< Current method count
+ u32 length_pending; ///< Large NI command length pending
+ bool non_incrementing; ///< Current command’s NI flag
+ };
+
+ DmaState dma_state{};
+ bool dma_increment_once{};
+
+ GPUVAddr dma_put{}; ///< pushbuffer current end address
+ GPUVAddr dma_get{}; ///< pushbuffer current read address
+ GPUVAddr dma_mget{}; ///< main pushbuffer last read address
+ bool ib_enable{true}; ///< IB mode enabled
+ bool non_main{}; ///< non-main pushbuffer active
+};
+
+} // namespace Tegra