diff options
-rw-r--r-- | .ci/scripts/common/pre-upload.sh | 2 | ||||
-rwxr-xr-x | .ci/scripts/linux/docker.sh | 15 | ||||
-rwxr-xr-x | .ci/scripts/linux/upload.sh | 5 | ||||
-rw-r--r-- | externals/nx_tzdb/CMakeLists.txt | 2 | ||||
m--------- | externals/nx_tzdb/tzdb_to_nx | 0 | ||||
-rw-r--r-- | src/common/common_funcs.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_a.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_manager.cpp | 86 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_manager.h | 9 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_types.h | 14 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_u.cpp | 74 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 14 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 2 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 44 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 2 | ||||
-rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 1 | ||||
-rw-r--r-- | src/yuzu/util/util.cpp | 81 |
19 files changed, 271 insertions, 106 deletions
diff --git a/.ci/scripts/common/pre-upload.sh b/.ci/scripts/common/pre-upload.sh index 705362a3c..3583f9840 100644 --- a/.ci/scripts/common/pre-upload.sh +++ b/.ci/scripts/common/pre-upload.sh @@ -5,6 +5,6 @@ GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`" GITREV="`git show -s --format='%h'`" -ARTIFACTS_DIR="artifacts" +ARTIFACTS_DIR="$PWD/artifacts" mkdir -p "${ARTIFACTS_DIR}/" diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index e5d83d4b9..a16577b27 100755 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh @@ -11,7 +11,7 @@ ccache -s mkdir build || true && cd build cmake .. \ -DBoost_USE_STATIC_LIBS=ON \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_CXX_FLAGS="-march=x86-64-v2" \ -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \ -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \ @@ -31,6 +31,19 @@ ccache -s ctest -VV -C Release +# Separate debug symbols from specified executables +for EXE in yuzu; do + EXE_PATH="bin/$EXE" + # Copy debug symbols out + objcopy --only-keep-debug $EXE_PATH $EXE_PATH.debug + # Add debug link and strip debug symbols + objcopy -g --add-gnu-debuglink=$EXE_PATH.debug $EXE_PATH $EXE_PATH.out + # Overwrite original with stripped copy + mv $EXE_PATH.out $EXE_PATH +done +# Strip debug symbols from all executables +find bin/ -type f -not -regex '.*.debug' -exec strip -g {} ';' + DESTDIR="$PWD/AppDir" ninja install rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh index e0f336427..fbb2d9c1b 100755 --- a/.ci/scripts/linux/upload.sh +++ b/.ci/scripts/linux/upload.sh @@ -59,4 +59,9 @@ if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage" fi +# Copy debug symbols to artifacts +cd build/bin +tar $COMPRESSION_FLAGS "${ARTIFACTS_DIR}/${REV_NAME}-debug.tar.xz" *.debug +cd - + . .ci/scripts/common/post-upload.sh diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt index 593786250..0fad24642 100644 --- a/externals/nx_tzdb/CMakeLists.txt +++ b/externals/nx_tzdb/CMakeLists.txt @@ -27,7 +27,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID) set(CAN_BUILD_NX_TZDB false) endif() -set(NX_TZDB_VERSION "220816") +set(NX_TZDB_VERSION "221202") set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip") set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb") diff --git a/externals/nx_tzdb/tzdb_to_nx b/externals/nx_tzdb/tzdb_to_nx -Subproject 212afa2394a74226dcf1b7996a570aae17debb6 +Subproject 0d17dd066d91f954a4c89d46dcb067eead6b1e4 diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 0dad9338a..47d028d48 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -39,8 +39,12 @@ #define Crash() exit(1) #endif +#define LTO_NOINLINE __attribute__((noinline)) + #else // _MSC_VER +#define LTO_NOINLINE + // Locale Cross-Compatibility #define locale_t _locale_t diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index a1134b7e2..cb025c3d6 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -373,7 +373,7 @@ struct KernelCore::Impl { static inline thread_local u8 host_thread_id = UINT8_MAX; /// Sets the host thread ID for the caller. - u32 SetHostThreadId(std::size_t core_id) { + LTO_NOINLINE u32 SetHostThreadId(std::size_t core_id) { // This should only be called during core init. ASSERT(host_thread_id == UINT8_MAX); @@ -384,13 +384,13 @@ struct KernelCore::Impl { } /// Gets the host thread ID for the caller - u32 GetHostThreadId() const { + LTO_NOINLINE u32 GetHostThreadId() const { return host_thread_id; } // Gets the dummy KThread for the caller, allocating a new one if this is the first time - KThread* GetHostDummyThread(KThread* existing_thread) { - const auto initialize{[](KThread* thread) { + LTO_NOINLINE KThread* GetHostDummyThread(KThread* existing_thread) { + const auto initialize{[](KThread* thread) LTO_NOINLINE { ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); return thread; }}; @@ -424,11 +424,11 @@ struct KernelCore::Impl { static inline thread_local bool is_phantom_mode_for_singlecore{false}; - bool IsPhantomModeForSingleCore() const { + LTO_NOINLINE bool IsPhantomModeForSingleCore() const { return is_phantom_mode_for_singlecore; } - void SetIsPhantomModeForSingleCore(bool value) { + LTO_NOINLINE void SetIsPhantomModeForSingleCore(bool value) { ASSERT(!is_multicore); is_phantom_mode_for_singlecore = value; } @@ -439,14 +439,14 @@ struct KernelCore::Impl { static inline thread_local KThread* current_thread{nullptr}; - KThread* GetCurrentEmuThread() { + LTO_NOINLINE KThread* GetCurrentEmuThread() { if (!current_thread) { current_thread = GetHostDummyThread(nullptr); } return current_thread; } - void SetCurrentEmuThread(KThread* thread) { + LTO_NOINLINE void SetCurrentEmuThread(KThread* thread) { current_thread = thread; } diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp index 286f9fd10..31dd98140 100644 --- a/src/core/hle/service/caps/caps.cpp +++ b/src/core/hle/service/caps/caps.cpp @@ -16,7 +16,7 @@ namespace Service::Capture { void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - auto album_manager = std::make_shared<AlbumManager>(); + auto album_manager = std::make_shared<AlbumManager>(system); server_manager->RegisterNamedService( "caps:a", std::make_shared<IAlbumAccessorService>(system, album_manager)); diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index e22f72bf6..9925720a3 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp @@ -128,9 +128,9 @@ void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) { ctx.WriteBuffer(entries); } - IPC::ResponseBuilder rb{ctx, 3}; + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(result); - rb.Push(entries.size()); + rb.Push<u64>(entries.size()); } void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) { diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp index 2df6a930a..2b4e3f076 100644 --- a/src/core/hle/service/caps/caps_manager.cpp +++ b/src/core/hle/service/caps/caps_manager.cpp @@ -8,12 +8,15 @@ #include "common/fs/file.h" #include "common/fs/path_util.h" #include "common/logging/log.h" +#include "core/core.h" #include "core/hle/service/caps/caps_manager.h" #include "core/hle/service/caps/caps_result.h" +#include "core/hle/service/time/time_manager.h" +#include "core/hle/service/time/time_zone_content_manager.h" namespace Service::Capture { -AlbumManager::AlbumManager() {} +AlbumManager::AlbumManager(Core::System& system_) : system{system_} {} AlbumManager::~AlbumManager() = default; @@ -83,6 +86,34 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu } Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, + ContentType contex_type, s64 start_posix_time, + s64 end_posix_time, u64 aruid) const { + if (!is_mounted) { + return ResultIsNotMounted; + } + + std::vector<ApplicationAlbumEntry> album_entries; + const auto start_date = ConvertToAlbumDateTime(start_posix_time); + const auto end_date = ConvertToAlbumDateTime(end_posix_time); + const auto result = GetAlbumFileList(album_entries, contex_type, start_date, end_date, aruid); + + if (result.IsError()) { + return result; + } + + for (const auto& album_entry : album_entries) { + ApplicationAlbumFileEntry entry{ + .entry = album_entry, + .datetime = album_entry.datetime, + .unknown = {}, + }; + out_entries.push_back(entry); + } + + return ResultSuccess; +} + +Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, ContentType contex_type, AlbumFileDateTime start_date, AlbumFileDateTime end_date, u64 aruid) const { if (!is_mounted) { @@ -93,31 +124,25 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou if (file_id.type != contex_type) { continue; } - if (file_id.date > start_date) { continue; } - if (file_id.date < end_date) { continue; } - if (out_entries.size() >= SdAlbumFileLimit) { break; } const auto entry_size = Common::FS::GetSize(path); - ApplicationAlbumFileEntry entry{.entry = - { - .size = entry_size, - .hash{}, - .datetime = file_id.date, - .storage = file_id.storage, - .content = contex_type, - .unknown = 1, - }, - .datetime = file_id.date, - .unknown = {}}; + ApplicationAlbumEntry entry{ + .size = entry_size, + .hash{}, + .datetime = file_id.date, + .storage = file_id.storage, + .content = contex_type, + .unknown = 1, + }; out_entries.push_back(entry); } @@ -274,12 +299,12 @@ Result AlbumManager::GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem: .application_id = static_cast<u64>(std::stoll(application, 0, 16)), .date = { - .year = static_cast<u16>(std::stoi(year)), - .month = static_cast<u8>(std::stoi(month)), - .day = static_cast<u8>(std::stoi(day)), - .hour = static_cast<u8>(std::stoi(hour)), - .minute = static_cast<u8>(std::stoi(minute)), - .second = static_cast<u8>(std::stoi(second)), + .year = static_cast<s16>(std::stoi(year)), + .month = static_cast<s8>(std::stoi(month)), + .day = static_cast<s8>(std::stoi(day)), + .hour = static_cast<s8>(std::stoi(hour)), + .minute = static_cast<s8>(std::stoi(minute)), + .second = static_cast<s8>(std::stoi(second)), .unique_id = 0, }, .storage = AlbumStorage::Sd, @@ -339,4 +364,23 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p return ResultSuccess; } + +AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const { + Time::TimeZone::CalendarInfo calendar_date{}; + const auto& time_zone_manager = + system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); + + time_zone_manager.ToCalendarTimeWithMyRules(posix_time, calendar_date); + + return { + .year = calendar_date.time.year, + .month = calendar_date.time.month, + .day = calendar_date.time.day, + .hour = calendar_date.time.hour, + .minute = calendar_date.time.minute, + .second = calendar_date.time.second, + .unique_id = 0, + }; +} + } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h index 8337c655c..f65eb12c1 100644 --- a/src/core/hle/service/caps/caps_manager.h +++ b/src/core/hle/service/caps/caps_manager.h @@ -37,7 +37,7 @@ namespace Service::Capture { class AlbumManager { public: - explicit AlbumManager(); + explicit AlbumManager(Core::System& system_); ~AlbumManager(); Result DeleteAlbumFile(const AlbumFileId& file_id); @@ -45,6 +45,9 @@ public: Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage, u8 flags) const; Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, + ContentType contex_type, s64 start_posix_time, s64 end_posix_time, + u64 aruid) const; + Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, ContentType contex_type, AlbumFileDateTime start_date, AlbumFileDateTime end_date, u64 aruid) const; Result GetAutoSavingStorage(bool& out_is_autosaving) const; @@ -65,8 +68,12 @@ private: Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width, int height, ScreenShotDecoderFlag flag) const; + AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const; + bool is_mounted{}; std::unordered_map<AlbumFileId, std::filesystem::path> album_files; + + Core::System& system; }; } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_types.h b/src/core/hle/service/caps/caps_types.h index bf6061273..7fd357954 100644 --- a/src/core/hle/service/caps/caps_types.h +++ b/src/core/hle/service/caps/caps_types.h @@ -41,13 +41,13 @@ enum class ScreenShotDecoderFlag : u64 { // This is nn::capsrv::AlbumFileDateTime struct AlbumFileDateTime { - u16 year{}; - u8 month{}; - u8 day{}; - u8 hour{}; - u8 minute{}; - u8 second{}; - u8 unique_id{}; + s16 year{}; + s8 month{}; + s8 day{}; + s8 hour{}; + s8 minute{}; + s8 second{}; + s8 unique_id{}; friend constexpr bool operator==(const AlbumFileDateTime&, const AlbumFileDateTime&) = default; friend constexpr bool operator>(const AlbumFileDateTime& a, const AlbumFileDateTime& b) { diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp index 260f25490..b6b33fb2f 100644 --- a/src/core/hle/service/caps/caps_u.cpp +++ b/src/core/hle/service/caps/caps_u.cpp @@ -50,22 +50,35 @@ void IAlbumApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) { void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto pid{rp.Pop<s32>()}; - const auto content_type{rp.PopEnum<ContentType>()}; - const auto start_posix_time{rp.Pop<s64>()}; - const auto end_posix_time{rp.Pop<s64>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + ContentType content_type; + INSERT_PADDING_BYTES(7); + s64 start_posix_time; + s64 end_posix_time; + u64 applet_resource_user_id; + }; + static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; LOG_WARNING(Service_Capture, - "(STUBBED) called. pid={}, content_type={}, start_posix_time={}, " - "end_posix_time={}, applet_resource_user_id={}", - pid, content_type, start_posix_time, end_posix_time, applet_resource_user_id); + "(STUBBED) called. content_type={}, start_posix_time={}, end_posix_time={}, " + "applet_resource_user_id={}", + parameters.content_type, parameters.start_posix_time, parameters.end_posix_time, + parameters.applet_resource_user_id); - // TODO: Translate posix to DateTime + Result result = ResultSuccess; + + if (result.IsSuccess()) { + result = manager->IsAlbumMounted(AlbumStorage::Sd); + } std::vector<ApplicationAlbumFileEntry> entries; - const Result result = - manager->GetAlbumFileList(entries, content_type, {}, {}, applet_resource_user_id); + if (result.IsSuccess()) { + result = manager->GetAlbumFileList(entries, parameters.content_type, + parameters.start_posix_time, parameters.end_posix_time, + parameters.applet_resource_user_id); + } if (!entries.empty()) { ctx.WriteBuffer(entries); @@ -78,19 +91,38 @@ void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestCo void IAlbumApplicationService::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto pid{rp.Pop<s32>()}; - const auto content_type{rp.PopEnum<ContentType>()}; - const auto start_date_time{rp.PopRaw<AlbumFileDateTime>()}; - const auto end_date_time{rp.PopRaw<AlbumFileDateTime>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + ContentType content_type; + INSERT_PADDING_BYTES(1); + AlbumFileDateTime start_date_time; + AlbumFileDateTime end_date_time; + INSERT_PADDING_BYTES(6); + u64 applet_resource_user_id; + }; + static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; LOG_WARNING(Service_Capture, - "(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid, - content_type, applet_resource_user_id); + "(STUBBED) called. content_type={}, start_date={}/{}/{}, " + "end_date={}/{}/{}, applet_resource_user_id={}", + parameters.content_type, parameters.start_date_time.year, + parameters.start_date_time.month, parameters.start_date_time.day, + parameters.end_date_time.year, parameters.end_date_time.month, + parameters.end_date_time.day, parameters.applet_resource_user_id); - std::vector<ApplicationAlbumFileEntry> entries; - const Result result = manager->GetAlbumFileList(entries, content_type, start_date_time, - end_date_time, applet_resource_user_id); + Result result = ResultSuccess; + + if (result.IsSuccess()) { + result = manager->IsAlbumMounted(AlbumStorage::Sd); + } + + std::vector<ApplicationAlbumEntry> entries; + if (result.IsSuccess()) { + result = + manager->GetAlbumFileList(entries, parameters.content_type, parameters.start_date_time, + parameters.end_date_time, parameters.applet_resource_user_id); + } if (!entries.empty()) { ctx.WriteBuffer(entries); diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 9cafd2983..512eef575 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -1048,6 +1048,10 @@ void Image::Scale(bool up_scale) { } bool Image::ScaleUp(bool ignore) { + const auto& resolution = runtime->resolution; + if (!resolution.active) { + return false; + } if (True(flags & ImageFlagBits::Rescaled)) { return false; } @@ -1060,9 +1064,6 @@ bool Image::ScaleUp(bool ignore) { return false; } flags |= ImageFlagBits::Rescaled; - if (!runtime->resolution.active) { - return false; - } has_scaled = true; if (ignore) { current_texture = upscaled_backup.handle; @@ -1073,13 +1074,14 @@ bool Image::ScaleUp(bool ignore) { } bool Image::ScaleDown(bool ignore) { - if (False(flags & ImageFlagBits::Rescaled)) { + const auto& resolution = runtime->resolution; + if (!resolution.active) { return false; } - flags &= ~ImageFlagBits::Rescaled; - if (!runtime->resolution.active) { + if (False(flags & ImageFlagBits::Rescaled)) { return false; } + flags &= ~ImageFlagBits::Rescaled; if (ignore) { current_texture = texture.handle; return true; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3676eaaa9..e71b87e99 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -118,6 +118,8 @@ public: void InsertUploadMemoryBarrier(); + void TransitionImageLayout(Image& image) {} + FormatProperties FormatInfo(VideoCommon::ImageType type, GLenum internal_format) const; bool HasNativeBgr() const noexcept { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 00ab47268..93773a69f 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1530,15 +1530,15 @@ bool Image::IsRescaled() const noexcept { } bool Image::ScaleUp(bool ignore) { + const auto& resolution = runtime->resolution; + if (!resolution.active) { + return false; + } if (True(flags & ImageFlagBits::Rescaled)) { return false; } ASSERT(info.type != ImageType::Linear); flags |= ImageFlagBits::Rescaled; - const auto& resolution = runtime->resolution; - if (!resolution.active) { - return false; - } has_scaled = true; if (!scaled_image) { const bool is_2d = info.type == ImageType::e2D; @@ -1567,15 +1567,15 @@ bool Image::ScaleUp(bool ignore) { } bool Image::ScaleDown(bool ignore) { + const auto& resolution = runtime->resolution; + if (!resolution.active) { + return false; + } if (False(flags & ImageFlagBits::Rescaled)) { return false; } ASSERT(info.type != ImageType::Linear); flags &= ~ImageFlagBits::Rescaled; - const auto& resolution = runtime->resolution; - if (!resolution.active) { - return false; - } current_image = *original_image; if (ignore) { return true; @@ -2013,4 +2013,32 @@ void TextureCacheRuntime::AccelerateImageUpload( ASSERT(false); } +void TextureCacheRuntime::TransitionImageLayout(Image& image) { + if (!image.ExchangeInitialization()) { + VkImageMemoryBarrier barrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_NONE, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image.Handle(), + .subresourceRange{ + .aspectMask = image.AspectMask(), + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }; + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([barrier = barrier](vk::CommandBuffer cmdbuf) { + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier); + }); + } +} + } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index d6c5a15cc..7a0807709 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -92,6 +92,8 @@ public: void InsertUploadMemoryBarrier() {} + void TransitionImageLayout(Image& image); + bool HasBrokenTextureViewFormats() const noexcept { // No known Vulkan driver has broken image views return false; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 1bdb0def5..d575c57ca 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1016,6 +1016,7 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) { if (image.info.num_samples > 1 && !runtime.CanUploadMSAA()) { LOG_WARNING(HW_GPU, "MSAA image uploads are not implemented"); + runtime.TransitionImageLayout(image); return; } if (True(image.flags & ImageFlagBits::AsynchronousDecode)) { diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 61cf00176..f2854c8ec 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -63,25 +63,15 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) { }; #pragma pack(pop) - QImage source_image = image.convertToFormat(QImage::Format_RGB32); + const QImage source_image = image.convertToFormat(QImage::Format_RGB32); + constexpr std::array<int, 7> scale_sizes{256, 128, 64, 48, 32, 24, 16}; constexpr int bytes_per_pixel = 4; - const int image_size = source_image.width() * source_image.height() * bytes_per_pixel; - - BITMAPINFOHEADER info_header{}; - info_header.biSize = sizeof(BITMAPINFOHEADER), info_header.biWidth = source_image.width(), - info_header.biHeight = source_image.height() * 2, info_header.biPlanes = 1, - info_header.biBitCount = bytes_per_pixel * 8, info_header.biCompression = BI_RGB; - - const IconDir icon_dir{.id_reserved = 0, .id_type = 1, .id_count = 1}; - const IconDirEntry icon_entry{.width = static_cast<BYTE>(source_image.width()), - .height = static_cast<BYTE>(source_image.height() * 2), - .color_count = 0, - .reserved = 0, - .planes = 1, - .bit_count = bytes_per_pixel * 8, - .bytes_in_res = - static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size), - .image_offset = sizeof(IconDir) + sizeof(IconDirEntry)}; + + const IconDir icon_dir{ + .id_reserved = 0, + .id_type = 1, + .id_count = static_cast<WORD>(scale_sizes.size()), + }; Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write, Common::FS::FileType::BinaryFile); @@ -92,20 +82,55 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) { if (!icon_file.Write(icon_dir)) { return false; } - if (!icon_file.Write(icon_entry)) { - return false; - } - if (!icon_file.Write(info_header)) { - return false; + + std::size_t image_offset = sizeof(IconDir) + (sizeof(IconDirEntry) * scale_sizes.size()); + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const int image_size = scale_sizes[i] * scale_sizes[i] * bytes_per_pixel; + const IconDirEntry icon_entry{ + .width = static_cast<BYTE>(scale_sizes[i]), + .height = static_cast<BYTE>(scale_sizes[i]), + .color_count = 0, + .reserved = 0, + .planes = 1, + .bit_count = bytes_per_pixel * 8, + .bytes_in_res = static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size), + .image_offset = static_cast<DWORD>(image_offset), + }; + image_offset += icon_entry.bytes_in_res; + if (!icon_file.Write(icon_entry)) { + return false; + } } - for (int y = 0; y < image.height(); y++) { - const auto* line = source_image.scanLine(source_image.height() - 1 - y); - std::vector<u8> line_data(source_image.width() * bytes_per_pixel); - std::memcpy(line_data.data(), line, line_data.size()); - if (!icon_file.Write(line_data)) { + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const QImage scaled_image = source_image.scaled( + scale_sizes[i], scale_sizes[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + const BITMAPINFOHEADER info_header{ + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = scaled_image.width(), + .biHeight = scaled_image.height() * 2, + .biPlanes = 1, + .biBitCount = bytes_per_pixel * 8, + .biCompression = BI_RGB, + .biSizeImage{}, + .biXPelsPerMeter{}, + .biYPelsPerMeter{}, + .biClrUsed{}, + .biClrImportant{}, + }; + + if (!icon_file.Write(info_header)) { return false; } + + for (int y = 0; y < scaled_image.height(); y++) { + const auto* line = scaled_image.scanLine(scaled_image.height() - 1 - y); + std::vector<u8> line_data(scaled_image.width() * bytes_per_pixel); + std::memcpy(line_data.data(), line, line_data.size()); + if (!icon_file.Write(line_data)) { + return false; + } + } } icon_file.Close(); |