// Copyright 2020 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include #include "common/bit_field.h" #include "common/common_types.h" #include "video_core/command_classes/sync_manager.h" namespace Tegra { class GPU; class Nvdec; class Vic; class Host1x; enum class ChSubmissionMode : u32 { SetClass = 0, Incrementing = 1, NonIncrementing = 2, Mask = 3, Immediate = 4, Restart = 5, Gather = 6, }; enum class ChClassId : u32 { NoClass = 0x0, Host1x = 0x1, VideoEncodeMpeg = 0x20, VideoEncodeNvEnc = 0x21, VideoStreamingVi = 0x30, VideoStreamingIsp = 0x32, VideoStreamingIspB = 0x34, VideoStreamingViI2c = 0x36, GraphicsVic = 0x5d, Graphics3D = 0x60, GraphicsGpu = 0x61, Tsec = 0xe0, TsecB = 0xe1, NvJpg = 0xc0, NvDec = 0xf0 }; enum class ChMethod : u32 { Empty = 0, SetMethod = 0x10, SetData = 0x11, }; union ChCommandHeader { u32 raw; BitField<0, 16, u32> value; BitField<16, 12, ChMethod> method_offset; BitField<28, 4, ChSubmissionMode> submission_mode; }; static_assert(sizeof(ChCommandHeader) == sizeof(u32), "ChCommand header is an invalid size"); struct ChCommand { ChClassId class_id{}; int method_offset{}; std::vector arguments; }; using ChCommandHeaderList = std::vector; using ChCommandList = std::vector; struct ThiRegisters { u32_le increment_syncpt{}; INSERT_PADDING_WORDS(1); u32_le increment_syncpt_error{}; u32_le ctx_switch_incremement_syncpt{}; INSERT_PADDING_WORDS(4); u32_le ctx_switch{}; INSERT_PADDING_WORDS(1); u32_le ctx_syncpt_eof{}; INSERT_PADDING_WORDS(5); u32_le method_0{}; u32_le method_1{}; INSERT_PADDING_WORDS(12); u32_le int_status{}; u32_le int_mask{}; }; enum class ThiMethod : u32 { IncSyncpt = offsetof(ThiRegisters, increment_syncpt) / sizeof(u32), SetMethod0 = offsetof(ThiRegisters, method_0) / sizeof(u32), SetMethod1 = offsetof(ThiRegisters, method_1) / sizeof(u32), }; class CDmaPusher { public: explicit CDmaPusher(GPU& gpu_); ~CDmaPusher(); /// Push NVDEC command buffer entries into queue void Push(ChCommandHeaderList&& entries); /// Process queued command buffer entries void DispatchCalls(); /// Process one queue element void Step(); /// Invoke command class devices to execute the command based on the current state void ExecuteCommand(u32 state_offset, u32 data); private: /// Write arguments value to the ThiRegisters member at the specified offset void ThiStateWrite(ThiRegisters& state, u32 state_offset, const std::vector& arguments); GPU& gpu; std::shared_ptr nvdec_processor; std::unique_ptr vic_processor; std::unique_ptr host1x_processor; std::unique_ptr nvdec_sync; std::unique_ptr vic_sync; ChClassId current_class{}; ThiRegisters vic_thi_state{}; ThiRegisters nvdec_thi_state{}; s32 count{}; s32 offset{}; s32 mask{}; bool incrementing{}; // Queue of command lists to be processed std::queue cdma_queue; }; } // namespace Tegra