early-access version 3927

main
pineappleEA 2023-10-12 19:22:22 +02:00
parent 91ade31ddd
commit 7fe7262395
29 changed files with 330 additions and 106 deletions

View File

@ -53,7 +53,7 @@ option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android"
CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF) CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF) CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}") option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
@ -179,9 +179,6 @@ if (YUZU_USE_BUNDLED_VCPKG)
if (YUZU_TESTS) if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests") list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
endif() endif()
if (YUZU_CRASH_DUMPS)
list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp")
endif()
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
list(APPEND VCPKG_MANIFEST_FEATURES "web-service") list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
endif() endif()
@ -587,6 +584,18 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
endif() endif()
if (WIN32 AND YUZU_CRASH_DUMPS)
set(BREAKPAD_VER "breakpad-c89f9dd")
download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX)
set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include")
set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib")
add_library(libbreakpad_client INTERFACE IMPORTED)
target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}")
target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}")
endif()
# Prefer the -pthread flag on Linux. # Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@ -606,13 +615,6 @@ elseif (WIN32)
# PSAPI is the Process Status API # PSAPI is the Process Status API
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version) set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
endif() endif()
if (YUZU_CRASH_DUMPS)
find_library(DBGHELP_LIBRARY dbghelp)
if ("${DBGHELP_LIBRARY}" STREQUAL "DBGHELP_LIBRARY-NOTFOUND")
message(FATAL_ERROR "YUZU_CRASH_DUMPS enabled but dbghelp library not found")
endif()
endif()
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$") elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
set(PLATFORM_LIBRARIES rt) set(PLATFORM_LIBRARIES rt)
endif() endif()

View File

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3926. This is the source code for early-access 3927.
## Legal Notice ## Legal Notice

View File

@ -185,3 +185,105 @@ if (ANDROID)
add_subdirectory(libadrenotools) add_subdirectory(libadrenotools)
endif() endif()
endif() endif()
# Breakpad
# https://github.com/microsoft/vcpkg/blob/master/ports/breakpad/CMakeLists.txt
if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
set(BREAKPAD_WIN32_DEFINES
NOMINMAX
UNICODE
WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
)
# libbreakpad
add_library(libbreakpad STATIC)
file(GLOB_RECURSE LIBBREAKPAD_SOURCES breakpad/src/processor/*.cc)
file(GLOB_RECURSE LIBDISASM_SOURCES breakpad/src/third_party/libdisasm/*.c)
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "_unittest|_selftest|synth_minidump|/tests|/testdata|/solaris|microdump_stackwalk|minidump_dump|minidump_stackwalk")
if (WIN32)
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/mac|/android")
target_compile_definitions(libbreakpad PRIVATE ${BREAKPAD_WIN32_DEFINES})
target_include_directories(libbreakpad PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include")
elseif (APPLE)
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/windows|/android")
else()
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/mac|/windows|/android")
endif()
target_sources(libbreakpad PRIVATE ${LIBBREAKPAD_SOURCES} ${LIBDISASM_SOURCES})
target_include_directories(libbreakpad
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src
${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/third_party/libdisasm
)
# libbreakpad_client
add_library(libbreakpad_client STATIC)
file(GLOB LIBBREAKPAD_COMMON_SOURCES breakpad/src/common/*.cc breakpad/src/common/*.c breakpad/src/client/*.cc)
if (WIN32)
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/windows/*.cc breakpad/src/common/windows/*.cc)
list(FILTER LIBBREAKPAD_COMMON_SOURCES EXCLUDE REGEX "language.cc|path_helper.cc|stabs_to_module.cc|stabs_reader.cc|minidump_file_writer.cc")
target_include_directories(libbreakpad_client PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include")
target_compile_definitions(libbreakpad_client PRIVATE ${BREAKPAD_WIN32_DEFINES})
elseif (APPLE)
target_compile_definitions(libbreakpad_client PRIVATE HAVE_MACH_O_NLIST_H)
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/mac/*.cc breakpad/src/common/mac/*.cc)
list(APPEND LIBBREAKPAD_CLIENT_SOURCES breakpad/src/common/mac/MachIPC.mm)
else()
target_compile_definitions(libbreakpad_client PUBLIC -DHAVE_A_OUT_H)
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/linux/*.cc breakpad/src/common/linux/*.cc)
endif()
list(APPEND LIBBREAKPAD_CLIENT_SOURCES ${LIBBREAKPAD_COMMON_SOURCES})
list(FILTER LIBBREAKPAD_CLIENT_SOURCES EXCLUDE REGEX "/sender|/tests|/unittests|/testcases|_unittest|_test")
target_sources(libbreakpad_client PRIVATE ${LIBBREAKPAD_CLIENT_SOURCES})
target_include_directories(libbreakpad_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src)
if (WIN32)
target_link_libraries(libbreakpad_client PRIVATE wininet.lib)
elseif (APPLE)
find_library(CoreFoundation_FRAMEWORK CoreFoundation)
target_link_libraries(libbreakpad_client PRIVATE ${CoreFoundation_FRAMEWORK})
else()
find_library(PTHREAD_LIBRARIES pthread)
target_compile_definitions(libbreakpad_client PRIVATE HAVE_GETCONTEXT=1)
if (PTHREAD_LIBRARIES)
target_link_libraries(libbreakpad_client PRIVATE ${PTHREAD_LIBRARIES})
endif()
endif()
# Host tools for symbol processing
if (LINUX)
find_package(ZLIB REQUIRED)
add_executable(minidump_stackwalk breakpad/src/processor/minidump_stackwalk.cc)
target_link_libraries(minidump_stackwalk PRIVATE libbreakpad libbreakpad_client)
add_executable(dump_syms
breakpad/src/common/dwarf_cfi_to_module.cc
breakpad/src/common/dwarf_cu_to_module.cc
breakpad/src/common/dwarf_line_to_module.cc
breakpad/src/common/dwarf_range_list_handler.cc
breakpad/src/common/language.cc
breakpad/src/common/module.cc
breakpad/src/common/path_helper.cc
breakpad/src/common/stabs_reader.cc
breakpad/src/common/stabs_to_module.cc
breakpad/src/common/dwarf/bytereader.cc
breakpad/src/common/dwarf/dwarf2diehandler.cc
breakpad/src/common/dwarf/dwarf2reader.cc
breakpad/src/common/dwarf/elf_reader.cc
breakpad/src/common/linux/crc32.cc
breakpad/src/common/linux/dump_symbols.cc
breakpad/src/common/linux/elf_symbols_to_module.cc
breakpad/src/common/linux/elfutils.cc
breakpad/src/common/linux/file_id.cc
breakpad/src/common/linux/linux_libc_support.cc
breakpad/src/common/linux/memory_mapped_file.cc
breakpad/src/common/linux/safe_readlink.cc
breakpad/src/tools/linux/dump_syms/dump_syms.cc)
target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB)
endif()
endif()

View File

@ -39,8 +39,12 @@
#define Crash() exit(1) #define Crash() exit(1)
#endif #endif
#define LTO_NOINLINE __attribute__((noinline))
#else // _MSC_VER #else // _MSC_VER
#define LTO_NOINLINE
// Locale Cross-Compatibility // Locale Cross-Compatibility
#define locale_t _locale_t #define locale_t _locale_t

View File

@ -211,6 +211,11 @@ struct Elf64_Rela {
Elf64_Sxword r_addend; /* Addend */ Elf64_Sxword r_addend; /* Addend */
}; };
/* RELR relocation table entry */
using Elf32_Relr = Elf32_Word;
using Elf64_Relr = Elf64_Xword;
/* How to extract and insert information held in the r_info field. */ /* How to extract and insert information held in the r_info field. */
static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { static inline u32 Elf32RelSymIndex(Elf32_Word r_info) {
@ -328,6 +333,9 @@ constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */
constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */
constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */
constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */
constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */
constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */
constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */
} // namespace ELF } // namespace ELF
} // namespace Common } // namespace Common

View File

@ -13,6 +13,7 @@
#define AMIIBO_DIR "amiibo" #define AMIIBO_DIR "amiibo"
#define CACHE_DIR "cache" #define CACHE_DIR "cache"
#define CONFIG_DIR "config" #define CONFIG_DIR "config"
#define CRASH_DUMPS_DIR "crash_dumps"
#define DUMP_DIR "dump" #define DUMP_DIR "dump"
#define KEYS_DIR "keys" #define KEYS_DIR "keys"
#define LOAD_DIR "load" #define LOAD_DIR "load"

View File

@ -119,6 +119,7 @@ public:
GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR); GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR);
GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache);
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config);
GenerateYuzuPath(YuzuPath::CrashDumpsDir, yuzu_path / CRASH_DUMPS_DIR);
GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR);
GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR); GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR);
GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);

View File

@ -15,6 +15,7 @@ enum class YuzuPath {
AmiiboDir, // Where Amiibo backups are stored. AmiiboDir, // Where Amiibo backups are stored.
CacheDir, // Where cached filesystem data is stored. CacheDir, // Where cached filesystem data is stored.
ConfigDir, // Where config files are stored. ConfigDir, // Where config files are stored.
CrashDumpsDir, // Where crash dumps are stored.
DumpDir, // Where dumped data is stored. DumpDir, // Where dumped data is stored.
KeysDir, // Where key files are stored. KeysDir, // Where key files are stored.
LoadDir, // Where cheat/mod files are stored. LoadDir, // Where cheat/mod files are stored.

View File

@ -502,7 +502,6 @@ struct Values {
linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false}; linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false};
Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers", Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
Category::Debugging}; Category::Debugging};
Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging};
Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging}; Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
// Miscellaneous // Miscellaneous

View File

@ -373,7 +373,7 @@ struct KernelCore::Impl {
static inline thread_local u8 host_thread_id = UINT8_MAX; static inline thread_local u8 host_thread_id = UINT8_MAX;
/// Sets the host thread ID for the caller. /// 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. // This should only be called during core init.
ASSERT(host_thread_id == UINT8_MAX); ASSERT(host_thread_id == UINT8_MAX);
@ -384,13 +384,13 @@ struct KernelCore::Impl {
} }
/// Gets the host thread ID for the caller /// Gets the host thread ID for the caller
u32 GetHostThreadId() const { LTO_NOINLINE u32 GetHostThreadId() const {
return host_thread_id; return host_thread_id;
} }
// Gets the dummy KThread for the caller, allocating a new one if this is the first time // Gets the dummy KThread for the caller, allocating a new one if this is the first time
KThread* GetHostDummyThread(KThread* existing_thread) { LTO_NOINLINE KThread* GetHostDummyThread(KThread* existing_thread) {
const auto initialize{[](KThread* thread) { const auto initialize{[](KThread* thread) LTO_NOINLINE {
ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
return thread; return thread;
}}; }};
@ -424,11 +424,11 @@ struct KernelCore::Impl {
static inline thread_local bool is_phantom_mode_for_singlecore{false}; 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; return is_phantom_mode_for_singlecore;
} }
void SetIsPhantomModeForSingleCore(bool value) { LTO_NOINLINE void SetIsPhantomModeForSingleCore(bool value) {
ASSERT(!is_multicore); ASSERT(!is_multicore);
is_phantom_mode_for_singlecore = value; is_phantom_mode_for_singlecore = value;
} }
@ -439,14 +439,14 @@ struct KernelCore::Impl {
static inline thread_local KThread* current_thread{nullptr}; static inline thread_local KThread* current_thread{nullptr};
KThread* GetCurrentEmuThread() { LTO_NOINLINE KThread* GetCurrentEmuThread() {
if (!current_thread) { if (!current_thread) {
current_thread = GetHostDummyThread(nullptr); current_thread = GetHostDummyThread(nullptr);
} }
return current_thread; return current_thread;
} }
void SetCurrentEmuThread(KThread* thread) { LTO_NOINLINE void SetCurrentEmuThread(KThread* thread) {
current_thread = thread; current_thread = thread;
} }

View File

@ -87,7 +87,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time, ContentType contex_type, s64 start_posix_time,
s64 end_posix_time, u64 aruid) { s64 end_posix_time, u64 aruid) const {
if (!is_mounted) { if (!is_mounted) {
return ResultIsNotMounted; return ResultIsNotMounted;
} }
@ -115,7 +115,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date, ContentType contex_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid) { AlbumFileDateTime end_date, u64 aruid) const {
if (!is_mounted) { if (!is_mounted) {
return ResultIsNotMounted; return ResultIsNotMounted;
} }

View File

@ -46,10 +46,10 @@ public:
u8 flags) const; u8 flags) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time, s64 end_posix_time, ContentType contex_type, s64 start_posix_time, s64 end_posix_time,
u64 aruid); u64 aruid) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date, ContentType contex_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid); AlbumFileDateTime end_date, u64 aruid) const;
Result GetAutoSavingStorage(bool& out_is_autosaving) const; Result GetAutoSavingStorage(bool& out_is_autosaving) const;
Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output, Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,
std::vector<u8>& out_image, const AlbumFileId& file_id, std::vector<u8>& out_image, const AlbumFileId& file_id,

View File

@ -156,6 +156,8 @@ public:
bool LoadNRO(std::span<const u8> data) { bool LoadNRO(std::span<const u8> data) {
local_memory.clear(); local_memory.clear();
relocbase = local_memory.size();
local_memory.insert(local_memory.end(), data.begin(), data.end()); local_memory.insert(local_memory.end(), data.begin(), data.end());
if (FixupRelocations()) { if (FixupRelocations()) {
@ -181,8 +183,8 @@ public:
// https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html
// https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html
VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)};
VAddr rela_dyn = 0; VAddr rela_dyn = 0, relr_dyn = 0;
size_t num_rela = 0; size_t num_rela = 0, num_relr = 0;
while (true) { while (true) {
const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)}; const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)};
dynamic_offset += sizeof(Elf64_Dyn); dynamic_offset += sizeof(Elf64_Dyn);
@ -196,6 +198,12 @@ public:
if (dyn.d_tag == ElfDtRelasz) { if (dyn.d_tag == ElfDtRelasz) {
num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela); num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela);
} }
if (dyn.d_tag == ElfDtRelr) {
relr_dyn = dyn.d_un.d_ptr;
}
if (dyn.d_tag == ElfDtRelrsz) {
num_relr = dyn.d_un.d_val / sizeof(Elf64_Relr);
}
} }
for (size_t i = 0; i < num_rela; i++) { for (size_t i = 0; i < num_rela; i++) {
@ -207,6 +215,29 @@ public:
callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend); callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend);
} }
VAddr relr_where = 0;
for (size_t i = 0; i < num_relr; i++) {
const auto relr{callbacks->ReadMemory<Elf64_Relr>(relr_dyn + i * sizeof(Elf64_Relr))};
const auto incr{[&](VAddr where) {
callbacks->MemoryWrite64(where, callbacks->MemoryRead64(where) + relocbase);
}};
if ((relr & 1) == 0) {
// where pointer
relr_where = relocbase + relr;
incr(relr_where);
relr_where += sizeof(Elf64_Addr);
} else {
// bitmap
for (int bit = 1; bit < 64; bit++) {
if ((relr & (1ULL << bit)) != 0) {
incr(relr_where + i * sizeof(Elf64_Addr));
}
}
relr_where += 63 * sizeof(Elf64_Addr);
}
}
return true; return true;
} }
@ -313,6 +344,7 @@ public:
Core::Memory::Memory& memory; Core::Memory::Memory& memory;
VAddr top_of_stack; VAddr top_of_stack;
VAddr heap_pointer; VAddr heap_pointer;
VAddr relocbase;
}; };
void DynarmicCallbacks64::CallSVC(u32 swi) { void DynarmicCallbacks64::CallSVC(u32 swi) {

View File

@ -62,7 +62,11 @@ using BufferId = SlotId;
using VideoCore::Surface::PixelFormat; using VideoCore::Surface::PixelFormat;
using namespace Common::Literals; using namespace Common::Literals;
#ifdef __APPLE__
constexpr u32 NUM_VERTEX_BUFFERS = 16;
#else
constexpr u32 NUM_VERTEX_BUFFERS = 32; constexpr u32 NUM_VERTEX_BUFFERS = 32;
#endif
constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;

View File

@ -3,16 +3,16 @@
#version 450 #version 450
precision mediump int;
precision highp float;
layout(binding = 0) uniform sampler2D depth_tex; layout(binding = 0) uniform sampler2D depth_tex;
layout(binding = 1) uniform isampler2D stencil_tex; layout(binding = 1) uniform usampler2D stencil_tex;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
void main() { void main() {
ivec2 coord = ivec2(gl_FragCoord.xy); ivec2 coord = ivec2(gl_FragCoord.xy);
uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
highp uint depth_val = highp uint depth_val =
uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0)); uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0));
lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r; lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r;

View File

@ -3,16 +3,16 @@
#version 450 #version 450
precision mediump int;
precision highp float;
layout(binding = 0) uniform sampler2D depth_tex; layout(binding = 0) uniform sampler2D depth_tex;
layout(binding = 1) uniform isampler2D stencil_tex; layout(binding = 1) uniform usampler2D stencil_tex;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
void main() { void main() {
ivec2 coord = ivec2(gl_FragCoord.xy); ivec2 coord = ivec2(gl_FragCoord.xy);
uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
highp uint depth_val = highp uint depth_val =
uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0)); uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0));
lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r; lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r;

View File

@ -1436,6 +1436,7 @@ void QueryCacheRuntime::Barriers(bool is_prebarrier) {
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
}; };
impl->scheduler.RequestOutsideRenderPassOperationContext();
if (is_prebarrier) { if (is_prebarrier) {
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,

View File

@ -975,6 +975,19 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
if (!state_tracker.TouchScissors()) { if (!state_tracker.TouchScissors()) {
return; return;
} }
if (!regs.viewport_scale_offset_enabled) {
const auto x = static_cast<float>(regs.surface_clip.x);
const auto y = static_cast<float>(regs.surface_clip.y);
const auto width = static_cast<float>(regs.surface_clip.width);
const auto height = static_cast<float>(regs.surface_clip.height);
VkRect2D scissor;
scissor.offset.x = static_cast<u32>(x);
scissor.offset.y = static_cast<u32>(y);
scissor.extent.width = static_cast<u32>(width != 0.0f ? width : 1.0f);
scissor.extent.height = static_cast<u32>(height != 0.0f ? height : 1.0f);
scheduler.Record([scissor](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissor); });
return;
}
u32 up_scale = 1; u32 up_scale = 1;
u32 down_shift = 0; u32 down_shift = 0;
if (texture_cache.IsRescaling()) { if (texture_cache.IsRescaling()) {

View File

@ -19,7 +19,7 @@ VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat
VkSampleCountFlagBits samples) { VkSampleCountFlagBits samples) {
using MaxwellToVK::SurfaceFormat; using MaxwellToVK::SurfaceFormat;
return { return {
.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, .flags = {},
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format, .format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
.samples = samples, .samples = samples,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,

View File

@ -10,19 +10,23 @@
#include "video_core/texture_cache/image_info.h" #include "video_core/texture_cache/image_info.h"
#include "video_core/texture_cache/image_view_base.h" #include "video_core/texture_cache/image_view_base.h"
#include "video_core/texture_cache/render_targets.h" #include "video_core/texture_cache/render_targets.h"
#include "video_core/texture_cache/samples_helper.h"
namespace VideoCommon { namespace VideoCommon {
std::string Name(const ImageBase& image) { std::string Name(const ImageBase& image) {
const GPUVAddr gpu_addr = image.gpu_addr; const GPUVAddr gpu_addr = image.gpu_addr;
const ImageInfo& info = image.info; const ImageInfo& info = image.info;
const u32 width = info.size.width; u32 width = info.size.width;
const u32 height = info.size.height; u32 height = info.size.height;
const u32 depth = info.size.depth; const u32 depth = info.size.depth;
const u32 num_layers = image.info.resources.layers; const u32 num_layers = image.info.resources.layers;
const u32 num_levels = image.info.resources.levels; const u32 num_levels = image.info.resources.levels;
std::string resource; std::string resource;
if (image.info.num_samples > 1) { if (image.info.num_samples > 1) {
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(image.info.num_samples);
width >>= samples_x;
height >>= samples_y;
resource += fmt::format(":{}xMSAA", image.info.num_samples); resource += fmt::format(":{}xMSAA", image.info.num_samples);
} }
if (num_layers > 1) { if (num_layers > 1) {

View File

@ -24,7 +24,7 @@ namespace VideoCommon {
return {2, 2}; return {2, 2};
} }
ASSERT_MSG(false, "Invalid number of samples={}", num_samples); ASSERT_MSG(false, "Invalid number of samples={}", num_samples);
return {1, 1}; return {0, 0};
} }
[[nodiscard]] inline int NumSamples(Tegra::Texture::MsaaMode msaa_mode) { [[nodiscard]] inline int NumSamples(Tegra::Texture::MsaaMode msaa_mode) {

View File

@ -68,7 +68,6 @@ struct LevelInfo {
Extent2D tile_size; Extent2D tile_size;
u32 bpp_log2; u32 bpp_log2;
u32 tile_width_spacing; u32 tile_width_spacing;
u32 num_levels;
}; };
[[nodiscard]] constexpr u32 AdjustTileSize(u32 shift, u32 unit_factor, u32 dimension) { [[nodiscard]] constexpr u32 AdjustTileSize(u32 shift, u32 unit_factor, u32 dimension) {
@ -119,11 +118,11 @@ template <u32 GOB_EXTENT>
} }
[[nodiscard]] constexpr Extent3D AdjustMipBlockSize(Extent3D num_tiles, Extent3D block_size, [[nodiscard]] constexpr Extent3D AdjustMipBlockSize(Extent3D num_tiles, Extent3D block_size,
u32 level, u32 num_levels) { u32 level) {
return { return {
.width = AdjustMipBlockSize<GOB_SIZE_X>(num_tiles.width, block_size.width, level), .width = AdjustMipBlockSize<GOB_SIZE_X>(num_tiles.width, block_size.width, level),
.height = AdjustMipBlockSize<GOB_SIZE_Y>(num_tiles.height, block_size.height, level), .height = AdjustMipBlockSize<GOB_SIZE_Y>(num_tiles.height, block_size.height, level),
.depth = level == 0 && num_levels == 1 .depth = level == 0
? block_size.depth ? block_size.depth
: AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level), : AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level),
}; };
@ -167,6 +166,13 @@ template <u32 GOB_EXTENT>
} }
[[nodiscard]] constexpr Extent3D TileShift(const LevelInfo& info, u32 level) { [[nodiscard]] constexpr Extent3D TileShift(const LevelInfo& info, u32 level) {
if (level == 0) {
return Extent3D{
.width = info.block.width,
.height = info.block.height,
.depth = info.block.depth,
};
}
const Extent3D blocks = NumLevelBlocks(info, level); const Extent3D blocks = NumLevelBlocks(info, level);
return Extent3D{ return Extent3D{
.width = AdjustTileSize(info.block.width, GOB_SIZE_X, blocks.width), .width = AdjustTileSize(info.block.width, GOB_SIZE_X, blocks.width),
@ -251,7 +257,7 @@ template <u32 GOB_EXTENT>
} }
[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
u32 tile_width_spacing, u32 num_levels) { u32 tile_width_spacing) {
const u32 bytes_per_block = BytesPerBlock(format); const u32 bytes_per_block = BytesPerBlock(format);
return { return {
.size = .size =
@ -264,18 +270,16 @@ template <u32 GOB_EXTENT>
.tile_size = DefaultBlockSize(format), .tile_size = DefaultBlockSize(format),
.bpp_log2 = BytesPerBlockLog2(bytes_per_block), .bpp_log2 = BytesPerBlockLog2(bytes_per_block),
.tile_width_spacing = tile_width_spacing, .tile_width_spacing = tile_width_spacing,
.num_levels = num_levels,
}; };
} }
[[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) { [[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) {
return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing, return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing);
info.resources.levels);
} }
[[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block, [[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block,
u32 tile_width_spacing, u32 level) { u32 tile_width_spacing, u32 level) {
const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing, level); const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing);
u32 offset = 0; u32 offset = 0;
for (u32 current_level = 0; current_level < level; ++current_level) { for (u32 current_level = 0; current_level < level; ++current_level) {
offset += CalculateLevelSize(info, current_level); offset += CalculateLevelSize(info, current_level);
@ -462,7 +466,7 @@ template <u32 GOB_EXTENT>
}; };
const u32 bpp_log2 = BytesPerBlockLog2(info.format); const u32 bpp_log2 = BytesPerBlockLog2(info.format);
const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing); const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing);
const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0, info.resources.levels); const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0);
return Extent3D{ return Extent3D{
.width = Common::AlignUpLog2(num_tiles.width, alignment), .width = Common::AlignUpLog2(num_tiles.width, alignment),
.height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height), .height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height),
@ -529,8 +533,7 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
UNIMPLEMENTED_IF(copy.image_extent != level_size); UNIMPLEMENTED_IF(copy.image_extent != level_size);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
size_t host_offset = copy.buffer_offset; size_t host_offset = copy.buffer_offset;
@ -695,7 +698,7 @@ u32 CalculateLevelStrideAlignment(const ImageInfo& info, u32 level) {
const Extent2D tile_size = DefaultBlockSize(info.format); const Extent2D tile_size = DefaultBlockSize(info.format);
const Extent3D level_size = AdjustMipSize(info.size, level); const Extent3D level_size = AdjustMipSize(info.size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level, info.resources.levels); const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level);
const u32 bpp_log2 = BytesPerBlockLog2(info.format); const u32 bpp_log2 = BytesPerBlockLog2(info.format);
return StrideAlignment(num_tiles, block, bpp_log2, info.tile_width_spacing); return StrideAlignment(num_tiles, block, bpp_log2, info.tile_width_spacing);
} }
@ -884,8 +887,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
.image_extent = level_size, .image_extent = level_size,
}; };
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2); const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2);
size_t guest_layer_offset = 0; size_t guest_layer_offset = 0;
@ -1039,7 +1041,7 @@ Extent3D MipBlockSize(const ImageInfo& info, u32 level) {
const Extent2D tile_size = DefaultBlockSize(info.format); const Extent2D tile_size = DefaultBlockSize(info.format);
const Extent3D level_size = AdjustMipSize(info.size, level); const Extent3D level_size = AdjustMipSize(info.size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
return AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); return AdjustMipBlockSize(num_tiles, level_info.block, level);
} }
boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const ImageInfo& info) { boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const ImageInfo& info) {
@ -1061,8 +1063,7 @@ boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const I
for (s32 level = 0; level < num_levels; ++level) { for (s32 level = 0; level < num_levels; ++level) {
const Extent3D level_size = AdjustMipSize(size, level); const Extent3D level_size = AdjustMipSize(size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
params[level] = SwizzleParameters{ params[level] = SwizzleParameters{
.num_tiles = num_tiles, .num_tiles = num_tiles,
.block = block, .block = block,
@ -1291,11 +1292,11 @@ u32 MapSizeBytes(const ImageBase& image) {
} }
} }
static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0, 1}, 0) == static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0}, 0) ==
0x7f8000); 0x7f8000);
static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0, 1}, 0) == 0x4000); static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x40000);
static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0, 1}, 0) == 0x4000); static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0}, 0) == 0x40000);
static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) == static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) ==
0x2afc00); 0x2afc00);

View File

@ -227,14 +227,14 @@ add_executable(yuzu
yuzu.rc yuzu.rc
) )
if (WIN32 AND YUZU_CRASH_DUMPS) if (YUZU_CRASH_DUMPS)
target_sources(yuzu PRIVATE target_sources(yuzu PRIVATE
mini_dump.cpp breakpad.cpp
mini_dump.h breakpad.h
) )
target_link_libraries(yuzu PRIVATE ${DBGHELP_LIBRARY}) target_link_libraries(yuzu PRIVATE libbreakpad_client)
target_compile_definitions(yuzu PRIVATE -DYUZU_DBGHELP) target_compile_definitions(yuzu PRIVATE YUZU_CRASH_DUMPS)
endif() endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")

77
src/yuzu/breakpad.cpp Executable file
View File

@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <ranges>
#if defined(_WIN32)
#include <client/windows/handler/exception_handler.h>
#elif defined(__linux__)
#include <client/linux/handler/exception_handler.h>
#else
#error Minidump creation not supported on this platform
#endif
#include "common/fs/fs_paths.h"
#include "common/fs/path_util.h"
#include "yuzu/breakpad.h"
namespace Breakpad {
static void PruneDumpDirectory(const std::filesystem::path& dump_path) {
// Code in this function should be exception-safe.
struct Entry {
std::filesystem::path path;
std::filesystem::file_time_type last_write_time;
};
std::vector<Entry> existing_dumps;
// Get existing entries.
std::error_code ec;
std::filesystem::directory_iterator dir(dump_path, ec);
for (auto& entry : dir) {
if (entry.is_regular_file()) {
existing_dumps.push_back(Entry{
.path = entry.path(),
.last_write_time = entry.last_write_time(ec),
});
}
}
// Sort descending by creation date.
std::ranges::stable_sort(existing_dumps, [](const auto& a, const auto& b) {
return a.last_write_time > b.last_write_time;
});
// Delete older dumps.
for (size_t i = 5; i < existing_dumps.size(); i++) {
std::filesystem::remove(existing_dumps[i].path, ec);
}
}
#if defined(__linux__)
[[noreturn]] bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context,
bool succeeded) {
// Prevent time- and space-consuming core dumps from being generated, as we have
// already generated a minidump and a core file will not be useful anyway.
_exit(1);
}
#endif
void InstallCrashHandler() {
// Write crash dumps to profile directory.
const auto dump_path = GetYuzuPath(Common::FS::YuzuPath::CrashDumpsDir);
PruneDumpDirectory(dump_path);
#if defined(_WIN32)
// TODO: If we switch to MinGW builds for Windows, this needs to be wrapped in a C API.
static google_breakpad::ExceptionHandler eh{dump_path, nullptr, nullptr, nullptr,
google_breakpad::ExceptionHandler::HANDLER_ALL};
#elif defined(__linux__)
static google_breakpad::MinidumpDescriptor descriptor{dump_path};
static google_breakpad::ExceptionHandler eh{descriptor, nullptr, DumpCallback,
nullptr, true, -1};
#endif
}
} // namespace Breakpad

10
src/yuzu/breakpad.h Executable file
View File

@ -0,0 +1,10 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace Breakpad {
void InstallCrashHandler();
}

View File

@ -27,16 +27,6 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
connect(ui->toggle_gdbstub, &QCheckBox::toggled, connect(ui->toggle_gdbstub, &QCheckBox::toggled,
[&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); }); [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); });
connect(ui->create_crash_dumps, &QCheckBox::stateChanged, [&](int) {
if (crash_dump_warning_shown) {
return;
}
QMessageBox::warning(this, tr("Restart Required"),
tr("yuzu is required to restart in order to apply this setting."),
QMessageBox::Ok, QMessageBox::Ok);
crash_dump_warning_shown = true;
});
} }
ConfigureDebug::~ConfigureDebug() = default; ConfigureDebug::~ConfigureDebug() = default;
@ -91,13 +81,6 @@ void ConfigureDebug::SetConfiguration() {
ui->disable_web_applet->setEnabled(false); ui->disable_web_applet->setEnabled(false);
ui->disable_web_applet->setText(tr("Web applet not compiled")); ui->disable_web_applet->setText(tr("Web applet not compiled"));
#endif #endif
#ifdef YUZU_DBGHELP
ui->create_crash_dumps->setChecked(Settings::values.create_crash_dumps.GetValue());
#else
ui->create_crash_dumps->setEnabled(false);
ui->create_crash_dumps->setText(tr("MiniDump creation not compiled"));
#endif
} }
void ConfigureDebug::ApplyConfiguration() { void ConfigureDebug::ApplyConfiguration() {
@ -109,7 +92,6 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked(); Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked();
Settings::values.reporting_services = ui->reporting_services->isChecked(); Settings::values.reporting_services = ui->reporting_services->isChecked();
Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked(); Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked();
Settings::values.create_crash_dumps = ui->create_crash_dumps->isChecked();
Settings::values.quest_flag = ui->quest_flag->isChecked(); Settings::values.quest_flag = ui->quest_flag->isChecked();
Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();

View File

@ -481,13 +481,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="create_crash_dumps">
<property name="text">
<string>Create Minidump After Crash</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="dump_audio_commands"> <widget class="QCheckBox" name="dump_audio_commands">
<property name="toolTip"> <property name="toolTip">

View File

@ -157,8 +157,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/util/clickable_label.h" #include "yuzu/util/clickable_label.h"
#include "yuzu/vk_device_info.h" #include "yuzu/vk_device_info.h"
#ifdef YUZU_DBGHELP #ifdef YUZU_CRASH_DUMPS
#include "yuzu/mini_dump.h" #include "yuzu/breakpad.h"
#endif #endif
using namespace Common::Literals; using namespace Common::Literals;
@ -5146,22 +5146,15 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
#ifdef YUZU_DBGHELP
PROCESS_INFORMATION pi;
if (!is_child && Settings::values.create_crash_dumps.GetValue() &&
MiniDump::SpawnDebuggee(argv[0], pi)) {
// Delete the config object so that it doesn't save when the program exits
config.reset(nullptr);
MiniDump::DebugDebuggee(pi);
return 0;
}
#endif
if (StartupChecks(argv[0], &has_broken_vulkan, if (StartupChecks(argv[0], &has_broken_vulkan,
Settings::values.perform_vulkan_check.GetValue())) { Settings::values.perform_vulkan_check.GetValue())) {
return 0; return 0;
} }
#ifdef YUZU_CRASH_DUMPS
Breakpad::InstallCrashHandler();
#endif
Common::DetachedTasks detached_tasks; Common::DetachedTasks detached_tasks;
MicroProfileOnThreadCreate("Frontend"); MicroProfileOnThreadCreate("Frontend");
SCOPE_EXIT({ MicroProfileShutdown(); }); SCOPE_EXIT({ MicroProfileShutdown(); });

View File

@ -33,10 +33,6 @@
"description": "Compile tests", "description": "Compile tests",
"dependencies": [ "catch2" ] "dependencies": [ "catch2" ]
}, },
"dbghelp": {
"description": "Compile Windows crash dump (Minidump) support",
"dependencies": [ "dbghelp" ]
},
"web-service": { "web-service": {
"description": "Enable web services (telemetry, etc.)", "description": "Enable web services (telemetry, etc.)",
"dependencies": [ "dependencies": [