From dc90dd680139b0c47f42f985500072b33cc75a34 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Fri, 26 May 2023 22:07:40 +0200 Subject: [PATCH] early-access version 3615 --- CMakeLists.txt | 1 + CMakeModules/CopyYuzuFFmpegDeps.cmake | 2 +- CMakeModules/CopyYuzuQt5Deps.cmake | 2 +- CMakeModules/CopyYuzuSDLDeps.cmake | 2 +- README.md | 2 +- externals/CMakeLists.txt | 42 +++++---- externals/ffmpeg/CMakeLists.txt | 5 +- externals/glad/CMakeLists.txt | 2 +- externals/libusb/CMakeLists.txt | 2 +- externals/opus/CMakeLists.txt | 2 +- .../hle/service/time/time_zone_manager.cpp | 40 +++++++- src/video_core/buffer_cache/buffer_cache.h | 2 - src/video_core/host1x/codecs/codec.cpp | 93 ++++++++++++++++++- src/video_core/host1x/codecs/codec.h | 8 ++ src/yuzu/CMakeLists.txt | 6 +- 15 files changed, 173 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b798420f..50a4cf08d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,6 +453,7 @@ endif() # List of all FFmpeg components required set(FFmpeg_COMPONENTS avcodec + avfilter avutil swscale) diff --git a/CMakeModules/CopyYuzuFFmpegDeps.cmake b/CMakeModules/CopyYuzuFFmpegDeps.cmake index 45ca5f523..a74fbb9ee 100755 --- a/CMakeModules/CopyYuzuFFmpegDeps.cmake +++ b/CMakeModules/CopyYuzuFFmpegDeps.cmake @@ -3,7 +3,7 @@ function(copy_yuzu_FFmpeg_deps target_dir) include(WindowsCopyFiles) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") + set(DLL_DEST "$/") file(READ "${FFmpeg_PATH}/requirements.txt" FFmpeg_REQUIRED_DLLS) string(STRIP "${FFmpeg_REQUIRED_DLLS}" FFmpeg_REQUIRED_DLLS) windows_copy_files(${target_dir} ${FFmpeg_DLL_DIR} ${DLL_DEST} ${FFmpeg_REQUIRED_DLLS}) diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake index d246d1a2b..ee7d166ea 100755 --- a/CMakeModules/CopyYuzuQt5Deps.cmake +++ b/CMakeModules/CopyYuzuQt5Deps.cmake @@ -4,7 +4,7 @@ function(copy_yuzu_Qt5_deps target_dir) include(WindowsCopyFiles) if (MSVC) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") + set(DLL_DEST "$/") set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") else() set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/") diff --git a/CMakeModules/CopyYuzuSDLDeps.cmake b/CMakeModules/CopyYuzuSDLDeps.cmake index 66c67007c..0f0cc04d8 100755 --- a/CMakeModules/CopyYuzuSDLDeps.cmake +++ b/CMakeModules/CopyYuzuSDLDeps.cmake @@ -3,6 +3,6 @@ function(copy_yuzu_SDL_deps target_dir) include(WindowsCopyFiles) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") + set(DLL_DEST "$/") windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) endfunction(copy_yuzu_SDL_deps) diff --git a/README.md b/README.md index e28f1d89a..5514ea5c4 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3614. +This is the source code for early-access 3615. ## Legal Notice diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 07c28d97a..9ad30d427 100755 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -8,15 +8,21 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Disable tests in all externals supporting the standard option name set(BUILD_TESTING OFF) +# Build only static externals +set(BUILD_SHARED_LIBS OFF) + +# Skip install rules for all externals +set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) + # xbyak if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak) - add_subdirectory(xbyak EXCLUDE_FROM_ALL) + add_subdirectory(xbyak) endif() # Dynarmic if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic) set(DYNARMIC_IGNORE_ASSERTS ON) - add_subdirectory(dynarmic EXCLUDE_FROM_ALL) + add_subdirectory(dynarmic) add_library(dynarmic::dynarmic ALIAS dynarmic) endif() @@ -34,7 +40,7 @@ if (NOT TARGET inih::INIReader) endif() # mbedtls -add_subdirectory(mbedtls EXCLUDE_FROM_ALL) +add_subdirectory(mbedtls) target_include_directories(mbedtls PUBLIC ./mbedtls/include) # MicroProfile @@ -48,7 +54,7 @@ endif() # libusb if (ENABLE_LIBUSB AND NOT TARGET libusb::usb) - add_subdirectory(libusb EXCLUDE_FROM_ALL) + add_subdirectory(libusb) endif() # SDL2 @@ -67,18 +73,16 @@ if (YUZU_USE_EXTERNAL_SDL2) set(HIDAPI ON) endif() - set(SDL_STATIC ON) - set(SDL_SHARED OFF) if (APPLE) set(SDL_FILE ON) endif() - add_subdirectory(SDL EXCLUDE_FROM_ALL) + add_subdirectory(SDL) endif() # ENet if (NOT TARGET enet::enet) - add_subdirectory(enet EXCLUDE_FROM_ALL) + add_subdirectory(enet) target_include_directories(enet INTERFACE ./enet/include) add_library(enet::enet ALIAS enet) endif() @@ -86,24 +90,26 @@ endif() # Cubeb if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb) set(BUILD_TESTS OFF) - add_subdirectory(cubeb EXCLUDE_FROM_ALL) + set(BUILD_TOOLS OFF) + add_subdirectory(cubeb) add_library(cubeb::cubeb ALIAS cubeb) endif() # DiscordRPC if (USE_DISCORD_PRESENCE AND NOT TARGET DiscordRPC::discord-rpc) - add_subdirectory(discord-rpc EXCLUDE_FROM_ALL) + set(BUILD_EXAMPLES OFF) + add_subdirectory(discord-rpc) target_include_directories(discord-rpc INTERFACE ./discord-rpc/include) add_library(DiscordRPC::discord-rpc ALIAS discord-rpc) endif() # Sirit -add_subdirectory(sirit EXCLUDE_FROM_ALL) +add_subdirectory(sirit) # httplib if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib) set(HTTPLIB_REQUIRE_OPENSSL ON) - add_subdirectory(cpp-httplib EXCLUDE_FROM_ALL) + add_subdirectory(cpp-httplib) endif() # cpp-jwt @@ -111,12 +117,12 @@ if (ENABLE_WEB_SERVICE AND NOT TARGET cpp-jwt::cpp-jwt) set(CPP_JWT_BUILD_EXAMPLES OFF) set(CPP_JWT_BUILD_TESTS OFF) set(CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF) - add_subdirectory(cpp-jwt EXCLUDE_FROM_ALL) + add_subdirectory(cpp-jwt) endif() # Opus if (NOT TARGET Opus::opus) - add_subdirectory(opus EXCLUDE_FROM_ALL) + add_subdirectory(opus) endif() # FFMpeg @@ -130,16 +136,14 @@ endif() # Vulkan-Headers if (YUZU_USE_EXTERNAL_VULKAN_HEADERS) - add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL) + add_subdirectory(Vulkan-Headers) endif() if (NOT TARGET LLVM::Demangle) - add_library(demangle STATIC) + add_library(demangle demangle/ItaniumDemangle.cpp) target_include_directories(demangle PUBLIC ./demangle) - target_sources(demangle PRIVATE demangle/ItaniumDemangle.cpp) add_library(LLVM::Demangle ALIAS demangle) endif() -add_library(stb STATIC) +add_library(stb stb/stb_dxt.cpp) target_include_directories(stb PUBLIC ./stb) -target_sources(stb PRIVATE stb/stb_dxt.cpp) diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index de3815243..7e696375a 100755 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -131,7 +131,6 @@ if (NOT WIN32) COMMAND /bin/bash ${FFmpeg_PREFIX}/configure --disable-avdevice - --disable-avfilter --disable-avformat --disable-doc --disable-everything @@ -143,6 +142,7 @@ if (NOT WIN32) --enable-decoder=h264 --enable-decoder=vp8 --enable-decoder=vp9 + --enable-filter=yadif --cc="${FFmpeg_CC}" --cxx="${FFmpeg_CXX}" ${FFmpeg_HWACCEL_FLAGS} @@ -199,7 +199,7 @@ if (NOT WIN32) endif() else(WIN32) # Use yuzu FFmpeg binaries - set(FFmpeg_EXT_NAME "ffmpeg-4.4") + set(FFmpeg_EXT_NAME "ffmpeg-5.1.3") set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}") download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "") set(FFmpeg_FOUND YES) @@ -210,6 +210,7 @@ else(WIN32) set(FFmpeg_LIBRARIES ${FFmpeg_LIBRARY_DIR}/swscale.lib ${FFmpeg_LIBRARY_DIR}/avcodec.lib + ${FFmpeg_LIBRARY_DIR}/avfilter.lib ${FFmpeg_LIBRARY_DIR}/avutil.lib CACHE PATH "Paths to FFmpeg libraries" FORCE) # exported variables diff --git a/externals/glad/CMakeLists.txt b/externals/glad/CMakeLists.txt index 7ca90f4da..0aadab8b5 100755 --- a/externals/glad/CMakeLists.txt +++ b/externals/glad/CMakeLists.txt @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2015 Yuri Kunde Schlesner # SPDX-License-Identifier: GPL-2.0-or-later -add_library(glad STATIC +add_library(glad src/glad.c include/KHR/khrplatform.h include/glad/glad.h diff --git a/externals/libusb/CMakeLists.txt b/externals/libusb/CMakeLists.txt index 45ccbd94d..2d1794fc2 100755 --- a/externals/libusb/CMakeLists.txt +++ b/externals/libusb/CMakeLists.txt @@ -122,7 +122,7 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") add_compile_options(/utf-8) endif() - add_library(usb STATIC EXCLUDE_FROM_ALL + add_library(usb libusb/libusb/core.c libusb/libusb/core.c libusb/libusb/descriptor.c diff --git a/externals/opus/CMakeLists.txt b/externals/opus/CMakeLists.txt index e18ea25b4..89a29f0d3 100755 --- a/externals/opus/CMakeLists.txt +++ b/externals/opus/CMakeLists.txt @@ -23,7 +23,7 @@ else() endif() endif() -add_library(opus STATIC +add_library(opus # CELT sources opus/celt/bands.c opus/celt/celt.c diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index 6dd5fd7af..48c262ec2 100755 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/assert.h" #include "common/logging/log.h" @@ -9,6 +10,7 @@ #include "core/file_sys/nca_metadata.h" #include "core/file_sys/registered_cache.h" #include "core/hle/service/time/time_zone_manager.h" +#include "core/hle/service/time/time_zone_types.h" namespace Service::Time::TimeZone { @@ -632,11 +634,47 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi UNIMPLEMENTED(); } } + + const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool { + if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) { + return {}; + } + + const struct TimeTypeInfo* ap = &rule.ttis[a]; + const struct TimeTypeInfo* bp = &rule.ttis[b]; + + return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst && + (std::strcmp(&rule.chars[ap->abbreviation_list_index], + &rule.chars[bp->abbreviation_list_index]) == 0)); + }; + if (time_zone_rule.type_count == 0) { return {}; } if (time_zone_rule.time_count > 1) { - UNIMPLEMENTED(); + if (time_zone_rule.ats[0] <= std::numeric_limits::max() - seconds_per_repeat) { + s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat; + int repeatattype = time_zone_rule.types[0]; + for (int i = 1; i < time_zone_rule.time_count; ++i) { + if (time_zone_rule.ats[i] == repeatat && + typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) { + time_zone_rule.go_back = true; + break; + } + } + } + if (std::numeric_limits::min() + seconds_per_repeat <= + time_zone_rule.ats[time_zone_rule.time_count - 1]) { + s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat; + int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1]; + for (int i = time_zone_rule.time_count; i >= 0; --i) { + if (time_zone_rule.ats[i] == repeatat && + typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) { + time_zone_rule.go_ahead = true; + break; + } + } + } } s32 default_type{}; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index c5caf2d77..685695b68 100755 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1276,8 +1276,6 @@ typename BufferCache

::OverlapResult BufferCache

::ResolveOverlaps(VAddr cpu has_stream_leap = true; if (expands_right) { begin -= CACHING_PAGESIZE * 256; - // We're about to increment cpu_addr by YUZU_PAGESIZE, but have not yet checked for - // a buffer at the new begin. cpu_addr = begin - CACHING_PAGESIZE; } if (expands_left) { diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index 99b8f4464..31be8b797 100755 --- a/src/video_core/host1x/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp @@ -5,6 +5,7 @@ #include #include #include "common/assert.h" +#include "common/scope_exit.h" #include "common/settings.h" #include "video_core/host1x/codecs/codec.h" #include "video_core/host1x/codecs/h264.h" @@ -14,6 +15,8 @@ #include "video_core/memory_manager.h" extern "C" { +#include +#include #include #ifdef LIBVA_FOUND // for querying VAAPI driver information @@ -85,6 +88,10 @@ Codec::~Codec() { // Free libav memory avcodec_free_context(&av_codec_ctx); av_buffer_unref(&av_gpu_decoder); + + if (filters_initialized) { + avfilter_graph_free(&av_filter_graph); + } } bool Codec::CreateGpuAvDevice() { @@ -167,6 +174,62 @@ void Codec::InitializeGpuDecoder() { av_codec_ctx->get_format = GetGpuFormat; } +void Codec::InitializeAvFilters(AVFrame* frame) { + const AVFilter* buffer_src = avfilter_get_by_name("buffer"); + const AVFilter* buffer_sink = avfilter_get_by_name("buffersink"); + AVFilterInOut* inputs = avfilter_inout_alloc(); + AVFilterInOut* outputs = avfilter_inout_alloc(); + SCOPE_EXIT({ + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + }); + + // Don't know how to get the accurate time_base but it doesn't matter for yadif filter + // so just use 1/1 to make buffer filter happy + std::string args = fmt::format("video_size={}x{}:pix_fmt={}:time_base=1/1", frame->width, + frame->height, frame->format); + + av_filter_graph = avfilter_graph_alloc(); + int ret = avfilter_graph_create_filter(&av_filter_src_ctx, buffer_src, "in", args.c_str(), + nullptr, av_filter_graph); + if (ret < 0) { + LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter source error: {}", ret); + return; + } + + ret = avfilter_graph_create_filter(&av_filter_sink_ctx, buffer_sink, "out", nullptr, nullptr, + av_filter_graph); + if (ret < 0) { + LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter sink error: {}", ret); + return; + } + + inputs->name = av_strdup("out"); + inputs->filter_ctx = av_filter_sink_ctx; + inputs->pad_idx = 0; + inputs->next = nullptr; + + outputs->name = av_strdup("in"); + outputs->filter_ctx = av_filter_src_ctx; + outputs->pad_idx = 0; + outputs->next = nullptr; + + const char* description = "yadif=1:-1:0"; + ret = avfilter_graph_parse_ptr(av_filter_graph, description, &inputs, &outputs, nullptr); + if (ret < 0) { + LOG_ERROR(Service_NVDRV, "avfilter_graph_parse_ptr error: {}", ret); + return; + } + + ret = avfilter_graph_config(av_filter_graph, nullptr); + if (ret < 0) { + LOG_ERROR(Service_NVDRV, "avfilter_graph_config error: {}", ret); + return; + } + + filters_initialized = true; +} + void Codec::Initialize() { const AVCodecID codec = [&] { switch (current_codec) { @@ -271,8 +334,34 @@ void Codec::Decode() { UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format); return; } - av_frames.push(std::move(final_frame)); - if (av_frames.size() > 10) { + if (!final_frame->interlaced_frame) { + av_frames.push(std::move(final_frame)); + } else { + if (!filters_initialized) { + InitializeAvFilters(final_frame.get()); + } + if (const int ret = av_buffersrc_add_frame_flags(av_filter_src_ctx, final_frame.get(), + AV_BUFFERSRC_FLAG_KEEP_REF); + ret) { + LOG_DEBUG(Service_NVDRV, "av_buffersrc_add_frame_flags error {}", ret); + return; + } + while (true) { + auto filter_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter}; + + int ret = av_buffersink_get_frame(av_filter_sink_ctx, filter_frame.get()); + + if (ret == AVERROR(EAGAIN) || ret == AVERROR(AVERROR_EOF)) + break; + if (ret < 0) { + LOG_DEBUG(Service_NVDRV, "av_buffersink_get_frame error {}", ret); + return; + } + + av_frames.push(std::move(filter_frame)); + } + } + while (av_frames.size() > 10) { LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame"); av_frames.pop(); } diff --git a/src/video_core/host1x/codecs/codec.h b/src/video_core/host1x/codecs/codec.h index 5cba334d4..cd7af19b1 100755 --- a/src/video_core/host1x/codecs/codec.h +++ b/src/video_core/host1x/codecs/codec.h @@ -15,6 +15,7 @@ extern "C" { #pragma GCC diagnostic ignored "-Wconversion" #endif #include +#include #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif @@ -61,17 +62,24 @@ public: private: void InitializeAvCodecContext(); + void InitializeAvFilters(AVFrame* frame); + void InitializeGpuDecoder(); bool CreateGpuAvDevice(); bool initialized{}; + bool filters_initialized{}; Host1x::NvdecCommon::VideoCodec current_codec{Host1x::NvdecCommon::VideoCodec::None}; const AVCodec* av_codec{nullptr}; AVCodecContext* av_codec_ctx{nullptr}; AVBufferRef* av_gpu_decoder{nullptr}; + AVFilterContext* av_filter_src_ctx{nullptr}; + AVFilterContext* av_filter_sink_ctx{nullptr}; + AVFilterGraph* av_filter_graph{nullptr}; + Host1x::Host1x& host1x; const Host1x::NvdecCommon::NvdecRegisters& state; std::unique_ptr h264_decoder; diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index d9f07ea41..ad63fd818 100755 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -378,11 +378,7 @@ if(UNIX AND NOT APPLE) endif() if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6) - if (MSVC AND NOT ${CMAKE_GENERATOR} STREQUAL "Ninja") - set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin/$") - else() - set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin") - endif() + set(YUZU_EXE_DIR "$") add_custom_command(TARGET yuzu POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${YUZU_EXE_DIR}/yuzu.exe" --dir "${YUZU_EXE_DIR}" --libdir "${YUZU_EXE_DIR}" --plugindir "${YUZU_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0) endif()