diff options
author | bunnei <bunneidev@gmail.com> | 2018-11-28 16:12:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-28 16:12:37 +0100 |
commit | 6f849887c9e7fa51743809c3a4bcfd2e319dff8d (patch) | |
tree | ba26ea7fcb626dacab4b7997149ad52c21ba526c /src/video_core/dma_pusher.h | |
parent | Merge pull request #1735 from FernandoS27/tex-spacing (diff) | |
parent | dma_pushbuffer: Optimize to avoid loop and copy on Push. (diff) | |
download | yuzu-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.h | 99 |
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 |