diff options
author | bunnei <bunneidev@gmail.com> | 2018-11-24 05:20:56 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2018-11-27 05:14:01 +0100 |
commit | abea6fa90c901d0b47487ed38d44511b18f0addf (patch) | |
tree | 65ba9fc6ff7609ea569ea1e3d05f91caa56ffa14 /src/video_core/dma_pusher.h | |
parent | Merge pull request #1805 from lioncash/resource (diff) | |
download | yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.gz yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.bz2 yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.lz yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.xz yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.zst yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.zip |
Diffstat (limited to '')
-rw-r--r-- | src/video_core/dma_pusher.h | 95 |
1 files changed, 95 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..39d98e46e --- /dev/null +++ b/src/video_core/dma_pusher.h @@ -0,0 +1,95 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#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; + +/** + * 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(const CommandListHeader& command_list_header) { + dma_pushbuffer.push(command_list_header); + } + + void DispatchCalls(); + +private: + bool Step(); + + void SetState(const CommandHeader& command_header); + + void CallMethod(u32 argument) const; + + GPU& gpu; + + std::queue<CommandListHeader> dma_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 |