diff options
author | Fernando S <fsahmkow27@gmail.com> | 2022-10-06 21:29:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-06 21:29:53 +0200 |
commit | 1effa578f12f79d7816e3543291f302f126cc1d2 (patch) | |
tree | 14803b31b6817294d40d57446f6fa94c5ff3fe9a /src/video_core/host1x | |
parent | Merge pull request #9025 from FernandoS27/slava-ukrayini (diff) | |
parent | vulkan_blitter: Fix pool allocation double free. (diff) | |
download | yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.gz yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.bz2 yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.lz yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.xz yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.zst yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.zip |
Diffstat (limited to '')
-rw-r--r-- | src/video_core/host1x/codecs/codec.cpp (renamed from src/video_core/command_classes/codecs/codec.cpp) | 44 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/codec.h (renamed from src/video_core/command_classes/codecs/codec.h) | 21 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/h264.cpp (renamed from src/video_core/command_classes/codecs/h264.cpp) | 17 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/h264.h (renamed from src/video_core/command_classes/codecs/h264.h) | 16 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/vp8.cpp (renamed from src/video_core/command_classes/codecs/vp8.cpp) | 12 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/vp8.h (renamed from src/video_core/command_classes/codecs/vp8.h) | 15 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/vp9.cpp (renamed from src/video_core/command_classes/codecs/vp9.cpp) | 23 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/vp9.h (renamed from src/video_core/command_classes/codecs/vp9.h) | 22 | ||||
-rw-r--r-- | src/video_core/host1x/codecs/vp9_types.h (renamed from src/video_core/command_classes/codecs/vp9_types.h) | 1 | ||||
-rw-r--r-- | src/video_core/host1x/control.cpp | 33 | ||||
-rw-r--r-- | src/video_core/host1x/control.h (renamed from src/video_core/command_classes/host1x.h) | 20 | ||||
-rw-r--r-- | src/video_core/host1x/host1x.cpp | 17 | ||||
-rw-r--r-- | src/video_core/host1x/host1x.h | 57 | ||||
-rw-r--r-- | src/video_core/host1x/nvdec.cpp (renamed from src/video_core/command_classes/nvdec.cpp) | 11 | ||||
-rw-r--r-- | src/video_core/host1x/nvdec.h (renamed from src/video_core/command_classes/nvdec.h) | 14 | ||||
-rw-r--r-- | src/video_core/host1x/nvdec_common.h (renamed from src/video_core/command_classes/nvdec_common.h) | 4 | ||||
-rw-r--r-- | src/video_core/host1x/sync_manager.cpp (renamed from src/video_core/command_classes/sync_manager.cpp) | 13 | ||||
-rw-r--r-- | src/video_core/host1x/sync_manager.h (renamed from src/video_core/command_classes/sync_manager.h) | 12 | ||||
-rw-r--r-- | src/video_core/host1x/syncpoint_manager.cpp | 96 | ||||
-rw-r--r-- | src/video_core/host1x/syncpoint_manager.h | 98 | ||||
-rw-r--r-- | src/video_core/host1x/vic.cpp (renamed from src/video_core/command_classes/vic.cpp) | 36 | ||||
-rw-r--r-- | src/video_core/host1x/vic.h (renamed from src/video_core/command_classes/vic.h) | 13 |
22 files changed, 476 insertions, 119 deletions
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index a5eb97b7f..42e7d6e4f 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp @@ -6,11 +6,11 @@ #include <vector> #include "common/assert.h" #include "common/settings.h" -#include "video_core/command_classes/codecs/codec.h" -#include "video_core/command_classes/codecs/h264.h" -#include "video_core/command_classes/codecs/vp8.h" -#include "video_core/command_classes/codecs/vp9.h" -#include "video_core/gpu.h" +#include "video_core/host1x/codecs/codec.h" +#include "video_core/host1x/codecs/h264.h" +#include "video_core/host1x/codecs/vp8.h" +#include "video_core/host1x/codecs/vp9.h" +#include "video_core/host1x/host1x.h" #include "video_core/memory_manager.h" extern "C" { @@ -73,10 +73,10 @@ void AVFrameDeleter(AVFrame* ptr) { av_frame_free(&ptr); } -Codec::Codec(GPU& gpu_, const NvdecCommon::NvdecRegisters& regs) - : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)), - vp8_decoder(std::make_unique<Decoder::VP8>(gpu)), - vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {} +Codec::Codec(Host1x::Host1x& host1x_, const Host1x::NvdecCommon::NvdecRegisters& regs) + : host1x(host1x_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(host1x)), + vp8_decoder(std::make_unique<Decoder::VP8>(host1x)), + vp9_decoder(std::make_unique<Decoder::VP9>(host1x)) {} Codec::~Codec() { if (!initialized) { @@ -168,11 +168,11 @@ void Codec::InitializeGpuDecoder() { void Codec::Initialize() { const AVCodecID codec = [&] { switch (current_codec) { - case NvdecCommon::VideoCodec::H264: + case Host1x::NvdecCommon::VideoCodec::H264: return AV_CODEC_ID_H264; - case NvdecCommon::VideoCodec::VP8: + case Host1x::NvdecCommon::VideoCodec::VP8: return AV_CODEC_ID_VP8; - case NvdecCommon::VideoCodec::VP9: + case Host1x::NvdecCommon::VideoCodec::VP9: return AV_CODEC_ID_VP9; default: UNIMPLEMENTED_MSG("Unknown codec {}", current_codec); @@ -197,7 +197,7 @@ void Codec::Initialize() { initialized = true; } -void Codec::SetTargetCodec(NvdecCommon::VideoCodec codec) { +void Codec::SetTargetCodec(Host1x::NvdecCommon::VideoCodec codec) { if (current_codec != codec) { current_codec = codec; LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", GetCurrentCodecName()); @@ -215,11 +215,11 @@ void Codec::Decode() { bool vp9_hidden_frame = false; const auto& frame_data = [&]() { switch (current_codec) { - case Tegra::NvdecCommon::VideoCodec::H264: + case Tegra::Host1x::NvdecCommon::VideoCodec::H264: return h264_decoder->ComposeFrame(state, is_first_frame); - case Tegra::NvdecCommon::VideoCodec::VP8: + case Tegra::Host1x::NvdecCommon::VideoCodec::VP8: return vp8_decoder->ComposeFrame(state); - case Tegra::NvdecCommon::VideoCodec::VP9: + case Tegra::Host1x::NvdecCommon::VideoCodec::VP9: vp9_decoder->ComposeFrame(state); vp9_hidden_frame = vp9_decoder->WasFrameHidden(); return vp9_decoder->GetFrameBytes(); @@ -287,21 +287,21 @@ AVFramePtr Codec::GetCurrentFrame() { return frame; } -NvdecCommon::VideoCodec Codec::GetCurrentCodec() const { +Host1x::NvdecCommon::VideoCodec Codec::GetCurrentCodec() const { return current_codec; } std::string_view Codec::GetCurrentCodecName() const { switch (current_codec) { - case NvdecCommon::VideoCodec::None: + case Host1x::NvdecCommon::VideoCodec::None: return "None"; - case NvdecCommon::VideoCodec::H264: + case Host1x::NvdecCommon::VideoCodec::H264: return "H264"; - case NvdecCommon::VideoCodec::VP8: + case Host1x::NvdecCommon::VideoCodec::VP8: return "VP8"; - case NvdecCommon::VideoCodec::H265: + case Host1x::NvdecCommon::VideoCodec::H265: return "H265"; - case NvdecCommon::VideoCodec::VP9: + case Host1x::NvdecCommon::VideoCodec::VP9: return "VP9"; default: return "Unknown"; diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/host1x/codecs/codec.h index 0c2405465..0d45fb7fe 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/host1x/codecs/codec.h @@ -6,8 +6,8 @@ #include <memory> #include <string_view> #include <queue> - -#include "video_core/command_classes/nvdec_common.h" +#include "common/common_types.h" +#include "video_core/host1x/nvdec_common.h" extern "C" { #if defined(__GNUC__) || defined(__clang__) @@ -21,7 +21,6 @@ extern "C" { } namespace Tegra { -class GPU; void AVFrameDeleter(AVFrame* ptr); using AVFramePtr = std::unique_ptr<AVFrame, decltype(&AVFrameDeleter)>; @@ -32,16 +31,20 @@ class VP8; class VP9; } // namespace Decoder +namespace Host1x { +class Host1x; +} // namespace Host1x + class Codec { public: - explicit Codec(GPU& gpu, const NvdecCommon::NvdecRegisters& regs); + explicit Codec(Host1x::Host1x& host1x, const Host1x::NvdecCommon::NvdecRegisters& regs); ~Codec(); /// Initialize the codec, returning success or failure void Initialize(); /// Sets NVDEC video stream codec - void SetTargetCodec(NvdecCommon::VideoCodec codec); + void SetTargetCodec(Host1x::NvdecCommon::VideoCodec codec); /// Call decoders to construct headers, decode AVFrame with ffmpeg void Decode(); @@ -50,7 +53,7 @@ public: [[nodiscard]] AVFramePtr GetCurrentFrame(); /// Returns the value of current_codec - [[nodiscard]] NvdecCommon::VideoCodec GetCurrentCodec() const; + [[nodiscard]] Host1x::NvdecCommon::VideoCodec GetCurrentCodec() const; /// Return name of the current codec [[nodiscard]] std::string_view GetCurrentCodecName() const; @@ -63,14 +66,14 @@ private: bool CreateGpuAvDevice(); bool initialized{}; - NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; + Host1x::NvdecCommon::VideoCodec current_codec{Host1x::NvdecCommon::VideoCodec::None}; const AVCodec* av_codec{nullptr}; AVCodecContext* av_codec_ctx{nullptr}; AVBufferRef* av_gpu_decoder{nullptr}; - GPU& gpu; - const NvdecCommon::NvdecRegisters& state; + Host1x::Host1x& host1x; + const Host1x::NvdecCommon::NvdecRegisters& state; std::unique_ptr<Decoder::H264> h264_decoder; std::unique_ptr<Decoder::VP8> vp8_decoder; std::unique_ptr<Decoder::VP9> vp9_decoder; diff --git a/src/video_core/command_classes/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index e2acd54d4..e87bd65fa 100644 --- a/src/video_core/command_classes/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -5,8 +5,8 @@ #include <bit> #include "common/settings.h" -#include "video_core/command_classes/codecs/h264.h" -#include "video_core/gpu.h" +#include "video_core/host1x/codecs/h264.h" +#include "video_core/host1x/host1x.h" #include "video_core/memory_manager.h" namespace Tegra::Decoder { @@ -24,19 +24,20 @@ constexpr std::array<u8, 16> zig_zag_scan{ }; } // Anonymous namespace -H264::H264(GPU& gpu_) : gpu(gpu_) {} +H264::H264(Host1x::Host1x& host1x_) : host1x{host1x_} {} H264::~H264() = default; -const std::vector<u8>& H264::ComposeFrame(const NvdecCommon::NvdecRegisters& state, +const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, bool is_first_frame) { H264DecoderContext context; - gpu.MemoryManager().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext)); + host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, + sizeof(H264DecoderContext)); const s64 frame_number = context.h264_parameter_set.frame_number.Value(); if (!is_first_frame && frame_number != 0) { frame.resize(context.stream_len); - gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); + host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); return frame; } @@ -155,8 +156,8 @@ const std::vector<u8>& H264::ComposeFrame(const NvdecCommon::NvdecRegisters& sta frame.resize(encoded_header.size() + context.stream_len); std::memcpy(frame.data(), encoded_header.data(), encoded_header.size()); - gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, - frame.data() + encoded_header.size(), context.stream_len); + host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, + frame.data() + encoded_header.size(), context.stream_len); return frame; } diff --git a/src/video_core/command_classes/codecs/h264.h b/src/video_core/host1x/codecs/h264.h index 261574364..5cc86454e 100644 --- a/src/video_core/command_classes/codecs/h264.h +++ b/src/video_core/host1x/codecs/h264.h @@ -8,10 +8,14 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "video_core/command_classes/nvdec_common.h" +#include "video_core/host1x/nvdec_common.h" namespace Tegra { -class GPU; + +namespace Host1x { +class Host1x; +} // namespace Host1x + namespace Decoder { class H264BitWriter { @@ -55,16 +59,16 @@ private: class H264 { public: - explicit H264(GPU& gpu); + explicit H264(Host1x::Host1x& host1x); ~H264(); /// Compose the H264 frame for FFmpeg decoding - [[nodiscard]] const std::vector<u8>& ComposeFrame(const NvdecCommon::NvdecRegisters& state, - bool is_first_frame = false); + [[nodiscard]] const std::vector<u8>& ComposeFrame( + const Host1x::NvdecCommon::NvdecRegisters& state, bool is_first_frame = false); private: std::vector<u8> frame; - GPU& gpu; + Host1x::Host1x& host1x; struct H264ParameterSet { s32 log2_max_pic_order_cnt_lsb_minus4; ///< 0x00 diff --git a/src/video_core/command_classes/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp index c83b9bbc2..28fb12cb8 100644 --- a/src/video_core/command_classes/codecs/vp8.cpp +++ b/src/video_core/host1x/codecs/vp8.cpp @@ -3,18 +3,18 @@ #include <vector> -#include "video_core/command_classes/codecs/vp8.h" -#include "video_core/gpu.h" +#include "video_core/host1x/codecs/vp8.h" +#include "video_core/host1x/host1x.h" #include "video_core/memory_manager.h" namespace Tegra::Decoder { -VP8::VP8(GPU& gpu_) : gpu(gpu_) {} +VP8::VP8(Host1x::Host1x& host1x_) : host1x{host1x_} {} VP8::~VP8() = default; -const std::vector<u8>& VP8::ComposeFrame(const NvdecCommon::NvdecRegisters& state) { +const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { VP8PictureInfo info; - gpu.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); + host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); const bool is_key_frame = info.key_frame == 1u; const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size); @@ -45,7 +45,7 @@ const std::vector<u8>& VP8::ComposeFrame(const NvdecCommon::NvdecRegisters& stat frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f)); } const u64 bitstream_offset = state.frame_bitstream_offset; - gpu.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size); + host1x.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size); return frame; } diff --git a/src/video_core/command_classes/codecs/vp8.h b/src/video_core/host1x/codecs/vp8.h index 3357667b0..5bf07ecab 100644 --- a/src/video_core/command_classes/codecs/vp8.h +++ b/src/video_core/host1x/codecs/vp8.h @@ -8,23 +8,28 @@ #include "common/common_funcs.h" #include "common/common_types.h" -#include "video_core/command_classes/nvdec_common.h" +#include "video_core/host1x/nvdec_common.h" namespace Tegra { -class GPU; + +namespace Host1x { +class Host1x; +} // namespace Host1x + namespace Decoder { class VP8 { public: - explicit VP8(GPU& gpu); + explicit VP8(Host1x::Host1x& host1x); ~VP8(); /// Compose the VP8 frame for FFmpeg decoding - [[nodiscard]] const std::vector<u8>& ComposeFrame(const NvdecCommon::NvdecRegisters& state); + [[nodiscard]] const std::vector<u8>& ComposeFrame( + const Host1x::NvdecCommon::NvdecRegisters& state); private: std::vector<u8> frame; - GPU& gpu; + Host1x::Host1x& host1x; struct VP8PictureInfo { INSERT_PADDING_WORDS_NOINIT(14); diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index c01431441..cf40c9012 100644 --- a/src/video_core/command_classes/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp @@ -4,8 +4,8 @@ #include <algorithm> // for std::copy #include <numeric> #include "common/assert.h" -#include "video_core/command_classes/codecs/vp9.h" -#include "video_core/gpu.h" +#include "video_core/host1x/codecs/vp9.h" +#include "video_core/host1x/host1x.h" #include "video_core/memory_manager.h" namespace Tegra::Decoder { @@ -236,7 +236,7 @@ constexpr std::array<u8, 254> map_lut{ } } // Anonymous namespace -VP9::VP9(GPU& gpu_) : gpu{gpu_} {} +VP9::VP9(Host1x::Host1x& host1x_) : host1x{host1x_} {} VP9::~VP9() = default; @@ -355,9 +355,9 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_ } } -Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) { +Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) { PictureInfo picture_info; - gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); + host1x.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); Vp9PictureInfo vp9_info = picture_info.Convert(); InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); @@ -372,18 +372,19 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) { EntropyProbs entropy; - gpu.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs)); + host1x.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs)); entropy.Convert(dst); } -Vp9FrameContainer VP9::GetCurrentFrame(const NvdecCommon::NvdecRegisters& state) { +Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { Vp9FrameContainer current_frame{}; { - gpu.SyncGuestHost(); + // gpu.SyncGuestHost(); epic, why? current_frame.info = GetVp9PictureInfo(state); current_frame.bit_stream.resize(current_frame.info.bitstream_size); - gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(), - current_frame.info.bitstream_size); + host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, + current_frame.bit_stream.data(), + current_frame.info.bitstream_size); } if (!next_frame.bit_stream.empty()) { Vp9FrameContainer temp{ @@ -769,7 +770,7 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { return uncomp_writer; } -void VP9::ComposeFrame(const NvdecCommon::NvdecRegisters& state) { +void VP9::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { std::vector<u8> bitstream; { Vp9FrameContainer curr_frame = GetCurrentFrame(state); diff --git a/src/video_core/command_classes/codecs/vp9.h b/src/video_core/host1x/codecs/vp9.h index ecc40e8b1..d4083e8d3 100644 --- a/src/video_core/command_classes/codecs/vp9.h +++ b/src/video_core/host1x/codecs/vp9.h @@ -8,11 +8,15 @@ #include "common/common_types.h" #include "common/stream.h" -#include "video_core/command_classes/codecs/vp9_types.h" -#include "video_core/command_classes/nvdec_common.h" +#include "video_core/host1x/codecs/vp9_types.h" +#include "video_core/host1x/nvdec_common.h" namespace Tegra { -class GPU; + +namespace Host1x { +class Host1x; +} // namespace Host1x + namespace Decoder { /// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the @@ -106,7 +110,7 @@ private: class VP9 { public: - explicit VP9(GPU& gpu_); + explicit VP9(Host1x::Host1x& host1x); ~VP9(); VP9(const VP9&) = delete; @@ -117,7 +121,7 @@ public: /// Composes the VP9 frame from the GPU state information. /// Based on the official VP9 spec documentation - void ComposeFrame(const NvdecCommon::NvdecRegisters& state); + void ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state); /// Returns true if the most recent frame was a hidden frame. [[nodiscard]] bool WasFrameHidden() const { @@ -162,19 +166,21 @@ private: void WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob); /// Returns VP9 information from NVDEC provided offset and size - [[nodiscard]] Vp9PictureInfo GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state); + [[nodiscard]] Vp9PictureInfo GetVp9PictureInfo( + const Host1x::NvdecCommon::NvdecRegisters& state); /// Read and convert NVDEC provided entropy probs to Vp9EntropyProbs struct void InsertEntropy(u64 offset, Vp9EntropyProbs& dst); /// Returns frame to be decoded after buffering - [[nodiscard]] Vp9FrameContainer GetCurrentFrame(const NvdecCommon::NvdecRegisters& state); + [[nodiscard]] Vp9FrameContainer GetCurrentFrame( + const Host1x::NvdecCommon::NvdecRegisters& state); /// Use NVDEC providied information to compose the headers for the current frame [[nodiscard]] std::vector<u8> ComposeCompressedHeader(); [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader(); - GPU& gpu; + Host1x::Host1x& host1x; std::vector<u8> frame; std::array<s8, 4> loop_filter_ref_deltas{}; diff --git a/src/video_core/command_classes/codecs/vp9_types.h b/src/video_core/host1x/codecs/vp9_types.h index bb3d8df6e..adad8ed7e 100644 --- a/src/video_core/command_classes/codecs/vp9_types.h +++ b/src/video_core/host1x/codecs/vp9_types.h @@ -9,7 +9,6 @@ #include "common/common_types.h" namespace Tegra { -class GPU; namespace Decoder { struct Vp9FrameDimensions { diff --git a/src/video_core/host1x/control.cpp b/src/video_core/host1x/control.cpp new file mode 100644 index 000000000..dceefdb7f --- /dev/null +++ b/src/video_core/host1x/control.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/assert.h" +#include "video_core/host1x/control.h" +#include "video_core/host1x/host1x.h" + +namespace Tegra::Host1x { + +Control::Control(Host1x& host1x_) : host1x(host1x_) {} + +Control::~Control() = default; + +void Control::ProcessMethod(Method method, u32 argument) { + switch (method) { + case Method::LoadSyncptPayload32: + syncpoint_value = argument; + break; + case Method::WaitSyncpt: + case Method::WaitSyncpt32: + Execute(argument); + break; + default: + UNIMPLEMENTED_MSG("Control method 0x{:X}", static_cast<u32>(method)); + break; + } +} + +void Control::Execute(u32 data) { + host1x.GetSyncpointManager().WaitHost(data, syncpoint_value); +} + +} // namespace Tegra::Host1x diff --git a/src/video_core/command_classes/host1x.h b/src/video_core/host1x/control.h index bb48a4381..e117888a3 100644 --- a/src/video_core/command_classes/host1x.h +++ b/src/video_core/host1x/control.h @@ -1,15 +1,19 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors +// SPDX-License-Identifier: GPL-3.0-or-later #pragma once #include "common/common_types.h" namespace Tegra { -class GPU; + +namespace Host1x { + +class Host1x; class Nvdec; -class Host1x { +class Control { public: enum class Method : u32 { WaitSyncpt = 0x8, @@ -17,8 +21,8 @@ public: WaitSyncpt32 = 0x50, }; - explicit Host1x(GPU& gpu); - ~Host1x(); + explicit Control(Host1x& host1x); + ~Control(); /// Writes the method into the state, Invoke Execute() if encountered void ProcessMethod(Method method, u32 argument); @@ -28,7 +32,9 @@ private: void Execute(u32 data); u32 syncpoint_value{}; - GPU& gpu; + Host1x& host1x; }; +} // namespace Host1x + } // namespace Tegra diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp new file mode 100644 index 000000000..7c317a85d --- /dev/null +++ b/src/video_core/host1x/host1x.cpp @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/core.h" +#include "video_core/host1x/host1x.h" + +namespace Tegra { + +namespace Host1x { + +Host1x::Host1x(Core::System& system_) + : system{system_}, syncpoint_manager{}, memory_manager{system, 32, 12}, + allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {} + +} // namespace Host1x + +} // namespace Tegra diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h new file mode 100644 index 000000000..57082ae54 --- /dev/null +++ b/src/video_core/host1x/host1x.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" + +#include "common/address_space.h" +#include "video_core/host1x/syncpoint_manager.h" +#include "video_core/memory_manager.h" + +namespace Core { +class System; +} // namespace Core + +namespace Tegra { + +namespace Host1x { + +class Host1x { +public: + explicit Host1x(Core::System& system); + + SyncpointManager& GetSyncpointManager() { + return syncpoint_manager; + } + + const SyncpointManager& GetSyncpointManager() const { + return syncpoint_manager; + } + + Tegra::MemoryManager& MemoryManager() { + return memory_manager; + } + + const Tegra::MemoryManager& MemoryManager() const { + return memory_manager; + } + + Common::FlatAllocator<u32, 0, 32>& Allocator() { + return *allocator; + } + + const Common::FlatAllocator<u32, 0, 32>& Allocator() const { + return *allocator; + } + +private: + Core::System& system; + SyncpointManager syncpoint_manager; + Tegra::MemoryManager memory_manager; + std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator; +}; + +} // namespace Host1x + +} // namespace Tegra diff --git a/src/video_core/command_classes/nvdec.cpp b/src/video_core/host1x/nvdec.cpp index 4fbbe3da6..a4bd5b79f 100644 --- a/src/video_core/command_classes/nvdec.cpp +++ b/src/video_core/host1x/nvdec.cpp @@ -2,15 +2,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" -#include "video_core/command_classes/nvdec.h" -#include "video_core/gpu.h" +#include "video_core/host1x/host1x.h" +#include "video_core/host1x/nvdec.h" -namespace Tegra { +namespace Tegra::Host1x { #define NVDEC_REG_INDEX(field_name) \ (offsetof(NvdecCommon::NvdecRegisters, field_name) / sizeof(u64)) -Nvdec::Nvdec(GPU& gpu_) : gpu(gpu_), state{}, codec(std::make_unique<Codec>(gpu, state)) {} +Nvdec::Nvdec(Host1x& host1x_) + : host1x(host1x_), state{}, codec(std::make_unique<Codec>(host1x, state)) {} Nvdec::~Nvdec() = default; @@ -44,4 +45,4 @@ void Nvdec::Execute() { } } -} // namespace Tegra +} // namespace Tegra::Host1x diff --git a/src/video_core/command_classes/nvdec.h b/src/video_core/host1x/nvdec.h index 488531fc6..3949d5181 100644 --- a/src/video_core/command_classes/nvdec.h +++ b/src/video_core/host1x/nvdec.h @@ -6,14 +6,17 @@ #include <memory> #include <vector> #include "common/common_types.h" -#include "video_core/command_classes/codecs/codec.h" +#include "video_core/host1x/codecs/codec.h" namespace Tegra { -class GPU; + +namespace Host1x { + +class Host1x; class Nvdec { public: - explicit Nvdec(GPU& gpu); + explicit Nvdec(Host1x& host1x); ~Nvdec(); /// Writes the method into the state, Invoke Execute() if encountered @@ -26,8 +29,11 @@ private: /// Invoke codec to decode a frame void Execute(); - GPU& gpu; + Host1x& host1x; NvdecCommon::NvdecRegisters state; std::unique_ptr<Codec> codec; }; + +} // namespace Host1x + } // namespace Tegra diff --git a/src/video_core/command_classes/nvdec_common.h b/src/video_core/host1x/nvdec_common.h index 521e5b52b..49d67ebbe 100644 --- a/src/video_core/command_classes/nvdec_common.h +++ b/src/video_core/host1x/nvdec_common.h @@ -7,7 +7,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" -namespace Tegra::NvdecCommon { +namespace Tegra::Host1x::NvdecCommon { enum class VideoCodec : u64 { None = 0x0, @@ -94,4 +94,4 @@ ASSERT_REG_POSITION(vp9_curr_frame_mvs_offset, 0x176); #undef ASSERT_REG_POSITION -} // namespace Tegra::NvdecCommon +} // namespace Tegra::Host1x::NvdecCommon diff --git a/src/video_core/command_classes/sync_manager.cpp b/src/video_core/host1x/sync_manager.cpp index 67e58046f..5ef9ea217 100644 --- a/src/video_core/command_classes/sync_manager.cpp +++ b/src/video_core/host1x/sync_manager.cpp @@ -3,10 +3,13 @@ #include <algorithm> #include "sync_manager.h" -#include "video_core/gpu.h" +#include "video_core/host1x/host1x.h" +#include "video_core/host1x/syncpoint_manager.h" namespace Tegra { -SyncptIncrManager::SyncptIncrManager(GPU& gpu_) : gpu(gpu_) {} +namespace Host1x { + +SyncptIncrManager::SyncptIncrManager(Host1x& host1x_) : host1x(host1x_) {} SyncptIncrManager::~SyncptIncrManager() = default; void SyncptIncrManager::Increment(u32 id) { @@ -36,8 +39,12 @@ void SyncptIncrManager::IncrementAllDone() { if (!increments[done_count].complete) { break; } - gpu.IncrementSyncPoint(increments[done_count].syncpt_id); + auto& syncpoint_manager = host1x.GetSyncpointManager(); + syncpoint_manager.IncrementGuest(increments[done_count].syncpt_id); + syncpoint_manager.IncrementHost(increments[done_count].syncpt_id); } increments.erase(increments.begin(), increments.begin() + done_count); } + +} // namespace Host1x } // namespace Tegra diff --git a/src/video_core/command_classes/sync_manager.h b/src/video_core/host1x/sync_manager.h index 6dfaae080..7bb77fa27 100644 --- a/src/video_core/command_classes/sync_manager.h +++ b/src/video_core/host1x/sync_manager.h @@ -8,7 +8,11 @@ #include "common/common_types.h" namespace Tegra { -class GPU; + +namespace Host1x { + +class Host1x; + struct SyncptIncr { u32 id; u32 class_id; @@ -21,7 +25,7 @@ struct SyncptIncr { class SyncptIncrManager { public: - explicit SyncptIncrManager(GPU& gpu); + explicit SyncptIncrManager(Host1x& host1x); ~SyncptIncrManager(); /// Add syncpoint id and increment all @@ -41,7 +45,9 @@ private: std::mutex increment_lock; u32 current_id{}; - GPU& gpu; + Host1x& host1x; }; +} // namespace Host1x + } // namespace Tegra diff --git a/src/video_core/host1x/syncpoint_manager.cpp b/src/video_core/host1x/syncpoint_manager.cpp new file mode 100644 index 000000000..326e8355a --- /dev/null +++ b/src/video_core/host1x/syncpoint_manager.cpp @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/microprofile.h" +#include "video_core/host1x/syncpoint_manager.h" + +namespace Tegra { + +namespace Host1x { + +MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); + +SyncpointManager::ActionHandle SyncpointManager::RegisterAction( + std::atomic<u32>& syncpoint, std::list<RegisteredAction>& action_storage, u32 expected_value, + std::function<void()>&& action) { + if (syncpoint.load(std::memory_order_acquire) >= expected_value) { + action(); + return {}; + } + + std::unique_lock lk(guard); + if (syncpoint.load(std::memory_order_relaxed) >= expected_value) { + action(); + return {}; + } + auto it = action_storage.begin(); + while (it != action_storage.end()) { + if (it->expected_value >= expected_value) { + break; + } + ++it; + } + return action_storage.emplace(it, expected_value, std::move(action)); +} + +void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_storage, + ActionHandle& handle) { + std::unique_lock lk(guard); + action_storage.erase(handle); +} + +void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle) { + DeregisterAction(guest_action_storage[syncpoint_id], handle); +} + +void SyncpointManager::DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle) { + DeregisterAction(host_action_storage[syncpoint_id], handle); +} + +void SyncpointManager::IncrementGuest(u32 syncpoint_id) { + Increment(syncpoints_guest[syncpoint_id], wait_guest_cv, guest_action_storage[syncpoint_id]); +} + +void SyncpointManager::IncrementHost(u32 syncpoint_id) { + Increment(syncpoints_host[syncpoint_id], wait_host_cv, host_action_storage[syncpoint_id]); +} + +void SyncpointManager::WaitGuest(u32 syncpoint_id, u32 expected_value) { + Wait(syncpoints_guest[syncpoint_id], wait_guest_cv, expected_value); +} + +void SyncpointManager::WaitHost(u32 syncpoint_id, u32 expected_value) { + MICROPROFILE_SCOPE(GPU_wait); + Wait(syncpoints_host[syncpoint_id], wait_host_cv, expected_value); +} + +void SyncpointManager::Increment(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, + std::list<RegisteredAction>& action_storage) { + auto new_value{syncpoint.fetch_add(1, std::memory_order_acq_rel) + 1}; + + std::unique_lock lk(guard); + auto it = action_storage.begin(); + while (it != action_storage.end()) { + if (it->expected_value > new_value) { + break; + } + it->action(); + it = action_storage.erase(it); + } + wait_cv.notify_all(); +} + +void SyncpointManager::Wait(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, + u32 expected_value) { + const auto pred = [&]() { return syncpoint.load(std::memory_order_acquire) >= expected_value; }; + if (pred()) { + return; + } + + std::unique_lock lk(guard); + wait_cv.wait(lk, pred); +} + +} // namespace Host1x + +} // namespace Tegra diff --git a/src/video_core/host1x/syncpoint_manager.h b/src/video_core/host1x/syncpoint_manager.h new file mode 100644 index 000000000..50a264e23 --- /dev/null +++ b/src/video_core/host1x/syncpoint_manager.h @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> +#include <atomic> +#include <condition_variable> +#include <functional> +#include <list> +#include <mutex> + +#include "common/common_types.h" + +namespace Tegra { + +namespace Host1x { + +class SyncpointManager { +public: + u32 GetGuestSyncpointValue(u32 id) const { + return syncpoints_guest[id].load(std::memory_order_acquire); + } + + u32 GetHostSyncpointValue(u32 id) const { + return syncpoints_host[id].load(std::memory_order_acquire); + } + + struct RegisteredAction { + explicit RegisteredAction(u32 expected_value_, std::function<void()>&& action_) + : expected_value{expected_value_}, action{std::move(action_)} {} + u32 expected_value; + std::function<void()> action; + }; + using ActionHandle = std::list<RegisteredAction>::iterator; + + template <typename Func> + ActionHandle RegisterGuestAction(u32 syncpoint_id, u32 expected_value, Func&& action) { + std::function<void()> func(action); + return RegisterAction(syncpoints_guest[syncpoint_id], guest_action_storage[syncpoint_id], + expected_value, std::move(func)); + } + + template <typename Func> + ActionHandle RegisterHostAction(u32 syncpoint_id, u32 expected_value, Func&& action) { + std::function<void()> func(action); + return RegisterAction(syncpoints_host[syncpoint_id], host_action_storage[syncpoint_id], + expected_value, std::move(func)); + } + + void DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle); + + void DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle); + + void IncrementGuest(u32 syncpoint_id); + + void IncrementHost(u32 syncpoint_id); + + void WaitGuest(u32 syncpoint_id, u32 expected_value); + + void WaitHost(u32 syncpoint_id, u32 expected_value); + + bool IsReadyGuest(u32 syncpoint_id, u32 expected_value) const { + return syncpoints_guest[syncpoint_id].load(std::memory_order_acquire) >= expected_value; + } + + bool IsReadyHost(u32 syncpoint_id, u32 expected_value) const { + return syncpoints_host[syncpoint_id].load(std::memory_order_acquire) >= expected_value; + } + +private: + void Increment(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, + std::list<RegisteredAction>& action_storage); + + ActionHandle RegisterAction(std::atomic<u32>& syncpoint, + std::list<RegisteredAction>& action_storage, u32 expected_value, + std::function<void()>&& action); + + void DeregisterAction(std::list<RegisteredAction>& action_storage, ActionHandle& handle); + + void Wait(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, u32 expected_value); + + static constexpr size_t NUM_MAX_SYNCPOINTS = 192; + + std::array<std::atomic<u32>, NUM_MAX_SYNCPOINTS> syncpoints_guest{}; + std::array<std::atomic<u32>, NUM_MAX_SYNCPOINTS> syncpoints_host{}; + + std::array<std::list<RegisteredAction>, NUM_MAX_SYNCPOINTS> guest_action_storage; + std::array<std::list<RegisteredAction>, NUM_MAX_SYNCPOINTS> host_action_storage; + + std::mutex guard; + std::condition_variable wait_guest_cv; + std::condition_variable wait_host_cv; +}; + +} // namespace Host1x + +} // namespace Tegra diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/host1x/vic.cpp index 7c17df353..ac0b7d20e 100644 --- a/src/video_core/command_classes/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -18,14 +18,17 @@ extern "C" { #include "common/bit_field.h" #include "common/logging/log.h" -#include "video_core/command_classes/nvdec.h" -#include "video_core/command_classes/vic.h" #include "video_core/engines/maxwell_3d.h" -#include "video_core/gpu.h" +#include "video_core/host1x/host1x.h" +#include "video_core/host1x/nvdec.h" +#include "video_core/host1x/vic.h" #include "video_core/memory_manager.h" #include "video_core/textures/decoders.h" namespace Tegra { + +namespace Host1x { + namespace { enum class VideoPixelFormat : u64_le { RGBA8 = 0x1f, @@ -46,8 +49,8 @@ union VicConfig { BitField<46, 14, u64_le> surface_height_minus1; }; -Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_) - : gpu(gpu_), +Vic::Vic(Host1x& host1x_, std::shared_ptr<Nvdec> nvdec_processor_) + : host1x(host1x_), nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {} Vic::~Vic() = default; @@ -78,7 +81,7 @@ void Vic::Execute() { LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); return; } - const VicConfig config{gpu.MemoryManager().Read<u64>(config_struct_address + 0x20)}; + const VicConfig config{host1x.MemoryManager().Read<u64>(config_struct_address + 0x20)}; const AVFramePtr frame_ptr = nvdec_processor->GetFrame(); const auto* frame = frame_ptr.get(); if (!frame) { @@ -153,15 +156,16 @@ void Vic::WriteRGBFrame(const AVFrame* frame, const VicConfig& config) { const u32 block_height = static_cast<u32>(config.block_linear_height_log2); const auto size = Texture::CalculateSize(true, 4, width, height, 1, block_height, 0); luma_buffer.resize(size); - Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(), - converted_frame_buf_addr, block_height, 0, 0); + std::span<const u8> frame_buff(converted_frame_buf_addr, 4 * width * height); + Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height, + block_height, 0, width * 4); - gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); + host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); } else { // send pitch linear frame const size_t linear_size = width * height * 4; - gpu.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, - linear_size); + host1x.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, + linear_size); } } @@ -189,8 +193,8 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) { luma_buffer[dst + x] = luma_src[src + x]; } } - gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), - luma_buffer.size()); + host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), + luma_buffer.size()); // Chroma const std::size_t half_height = frame_height / 2; @@ -231,8 +235,10 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) { ASSERT(false); break; } - gpu.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), - chroma_buffer.size()); + host1x.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), + chroma_buffer.size()); } +} // namespace Host1x + } // namespace Tegra diff --git a/src/video_core/command_classes/vic.h b/src/video_core/host1x/vic.h index 010daa6b6..2b78786e8 100644 --- a/src/video_core/command_classes/vic.h +++ b/src/video_core/host1x/vic.h @@ -10,7 +10,10 @@ struct SwsContext; namespace Tegra { -class GPU; + +namespace Host1x { + +class Host1x; class Nvdec; union VicConfig; @@ -25,7 +28,7 @@ public: SetOutputSurfaceChromaUnusedOffset = 0x1ca }; - explicit Vic(GPU& gpu, std::shared_ptr<Nvdec> nvdec_processor); + explicit Vic(Host1x& host1x, std::shared_ptr<Nvdec> nvdec_processor); ~Vic(); @@ -39,8 +42,8 @@ private: void WriteYUVFrame(const AVFrame* frame, const VicConfig& config); - GPU& gpu; - std::shared_ptr<Tegra::Nvdec> nvdec_processor; + Host1x& host1x; + std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor; /// Avoid reallocation of the following buffers every frame, as their /// size does not change during a stream @@ -58,4 +61,6 @@ private: s32 scaler_height{}; }; +} // namespace Host1x + } // namespace Tegra |