summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.ci/scripts/windows/docker.sh5
-rw-r--r--.gitmodules6
-rw-r--r--CMakeLists.txt220
-rw-r--r--CMakeModules/GenerateSCMRev.cmake12
-rw-r--r--dist/yuzu.desktop2
-rw-r--r--dist/yuzu.xml15
-rw-r--r--externals/CMakeLists.txt16
m---------externals/SDL0
m---------externals/Vulkan-Headers0
m---------externals/ffmpeg0
-rw-r--r--externals/ffmpeg/CMakeLists.txt214
m---------externals/ffmpeg/ffmpeg0
-rw-r--r--src/common/CMakeLists.txt5
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hid/emulated_console.cpp3
-rw-r--r--src/core/hid/emulated_console.h2
-rw-r--r--src/core/hid/emulated_controller.cpp19
-rw-r--r--src/core/hid/hid_types.h7
-rw-r--r--src/core/hid/motion_input.cpp12
-rw-r--r--src/core/hid/motion_input.h5
-rw-r--r--src/core/hle/kernel/k_process.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/kernel/svc.cpp9
-rw-r--r--src/core/hle/lock.cpp9
-rw-r--r--src/core/hle/lock.h18
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp12
-rw-r--r--src/core/hle/service/bcat/backend/backend.h5
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp20
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.h10
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp7
-rw-r--r--src/core/hle/service/hid/controllers/npad.h7
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp2
-rw-r--r--src/core/loader/kip.cpp8
-rw-r--r--src/input_common/drivers/udp_client.cpp74
-rw-r--r--src/input_common/helpers/udp_protocol.h21
-rw-r--r--src/tests/CMakeLists.txt3
-rw-r--r--src/tests/input_common/calibration_configuration_job.cpp136
-rw-r--r--src/video_core/command_classes/codecs/codec.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp50
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp123
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h30
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp37
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp34
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h8
-rw-r--r--src/video_core/texture_cache/texture_cache.h15
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp31
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h13
-rw-r--r--src/yuzu/applets/qt_controller.cpp3
-rw-r--r--src/yuzu/applets/qt_error.cpp3
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp3
-rw-r--r--src/yuzu/main.cpp41
54 files changed, 738 insertions, 569 deletions
diff --git a/.ci/scripts/windows/docker.sh b/.ci/scripts/windows/docker.sh
index 155d8a5c8..584b9b39f 100755
--- a/.ci/scripts/windows/docker.sh
+++ b/.ci/scripts/windows/docker.sh
@@ -41,12 +41,11 @@ for i in package/*.exe; do
41done 41done
42 42
43pip3 install pefile 43pip3 install pefile
44python3 .ci/scripts/windows/scan_dll.py package/*.exe "package/" 44python3 .ci/scripts/windows/scan_dll.py package/*.exe package/imageformats/*.dll "package/"
45python3 .ci/scripts/windows/scan_dll.py package/imageformats/*.dll "package/"
46 45
47# copy FFmpeg libraries 46# copy FFmpeg libraries
48EXTERNALS_PATH="$(pwd)/build/externals" 47EXTERNALS_PATH="$(pwd)/build/externals"
49FFMPEG_DLL_PATH="$(find ${EXTERNALS_PATH} -maxdepth 1 -type d | grep ffmpeg)/bin" 48FFMPEG_DLL_PATH="$(find "${EXTERNALS_PATH}" -maxdepth 1 -type d | grep 'ffmpeg-')/bin"
50find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';' 49find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
51 50
52# copy libraries from yuzu.exe path 51# copy libraries from yuzu.exe path
diff --git a/.gitmodules b/.gitmodules
index dc6ed500f..a9cf9a24a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -34,12 +34,12 @@
34[submodule "opus"] 34[submodule "opus"]
35 path = externals/opus/opus 35 path = externals/opus/opus
36 url = https://github.com/xiph/opus.git 36 url = https://github.com/xiph/opus.git
37[submodule "ffmpeg"]
38 path = externals/ffmpeg
39 url = https://git.ffmpeg.org/ffmpeg.git
40[submodule "SDL"] 37[submodule "SDL"]
41 path = externals/SDL 38 path = externals/SDL
42 url = https://github.com/libsdl-org/SDL.git 39 url = https://github.com/libsdl-org/SDL.git
43[submodule "externals/cpp-httplib"] 40[submodule "externals/cpp-httplib"]
44 path = externals/cpp-httplib 41 path = externals/cpp-httplib
45 url = https://github.com/yhirose/cpp-httplib.git 42 url = https://github.com/yhirose/cpp-httplib.git
43[submodule "externals/ffmpeg/ffmpeg"]
44 path = externals/ffmpeg/ffmpeg
45 url = https://git.ffmpeg.org/ffmpeg.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a810e11c2..7d9056aa3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -508,13 +508,13 @@ set(FFmpeg_COMPONENTS
508 avutil 508 avutil
509 swscale) 509 swscale)
510 510
511if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") 511if (UNIX AND NOT APPLE)
512 Include(FindPkgConfig REQUIRED) 512 Include(FindPkgConfig REQUIRED)
513 pkg_check_modules(LIBVA libva) 513 pkg_check_modules(LIBVA libva)
514endif() 514endif()
515if (NOT YUZU_USE_BUNDLED_FFMPEG) 515if (NOT YUZU_USE_BUNDLED_FFMPEG)
516 # Use system installed FFmpeg 516 # Use system installed FFmpeg
517 find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS}) 517 find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
518 518
519 if (FFmpeg_FOUND) 519 if (FFmpeg_FOUND)
520 # Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries. 520 # Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
@@ -527,225 +527,11 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
527 set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE) 527 set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE)
528 endforeach() 528 endforeach()
529 else() 529 else()
530 message(WARNING "FFmpeg not found, falling back to externals") 530 message(WARNING "FFmpeg not found or too old, falling back to externals")
531 set(YUZU_USE_BUNDLED_FFMPEG ON) 531 set(YUZU_USE_BUNDLED_FFMPEG ON)
532 endif() 532 endif()
533endif() 533endif()
534 534
535if (YUZU_USE_BUNDLED_FFMPEG)
536 if (NOT WIN32)
537 # TODO(lat9nq): Move this to externals/ffmpeg/CMakeLists.txt (and move externals/ffmpeg to
538 # externals/ffmpeg/ffmpeg)
539
540 # Build FFmpeg from externals
541 message(STATUS "Using FFmpeg from externals")
542
543 # FFmpeg has source that requires one of nasm or yasm to assemble it.
544 # REQUIRED throws an error if not found here during configuration rather than during compilation.
545 find_program(ASSEMBLER NAMES nasm yasm)
546 if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
547 message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
548 endif()
549
550 find_program(AUTOCONF autoconf)
551 if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
552 message(FATAL_ERROR "Required program `autoconf` not found.")
553 endif()
554
555 set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg)
556 set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg)
557 set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
558 make_directory(${FFmpeg_BUILD_DIR})
559
560 # Read version string from external
561 file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
562 set(FFmpeg_FOUND NO)
563 if (NOT FFmpeg_VERSION STREQUAL "")
564 set(FFmpeg_FOUND YES)
565 endif()
566
567 unset(FFmpeg_LIBRARIES CACHE)
568 foreach(COMPONENT ${FFmpeg_COMPONENTS})
569 set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
570 set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
571 set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
572
573 set(FFmpeg_LIBRARIES
574 ${FFmpeg_LIBRARIES}
575 ${FFmpeg_${COMPONENT}_LIBRARY}
576 CACHE PATH "Paths to FFmpeg libraries" FORCE)
577 endforeach()
578
579 Include(FindPkgConfig REQUIRED)
580 pkg_check_modules(LIBVA libva)
581 pkg_check_modules(CUDA cuda)
582 pkg_check_modules(FFNVCODEC ffnvcodec)
583 pkg_check_modules(VDPAU vdpau)
584
585 set(FFmpeg_HWACCEL_LIBRARIES)
586 set(FFmpeg_HWACCEL_FLAGS)
587 set(FFmpeg_HWACCEL_INCLUDE_DIRS)
588 set(FFmpeg_HWACCEL_LDFLAGS)
589
590 if(LIBVA_FOUND)
591 pkg_check_modules(LIBDRM libdrm REQUIRED)
592 find_package(X11 REQUIRED)
593 pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
594 pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
595 list(APPEND FFmpeg_HWACCEL_LIBRARIES
596 ${LIBDRM_LIBRARIES}
597 ${X11_LIBRARIES}
598 ${LIBVA-DRM_LIBRARIES}
599 ${LIBVA-X11_LIBRARIES}
600 ${LIBVA_LIBRARIES})
601 set(FFmpeg_HWACCEL_FLAGS
602 --enable-hwaccel=h264_vaapi
603 --enable-hwaccel=vp8_vaapi
604 --enable-hwaccel=vp9_vaapi
605 --enable-libdrm)
606 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
607 ${LIBDRM_INCLUDE_DIRS}
608 ${X11_INCLUDE_DIRS}
609 ${LIBVA-DRM_INCLUDE_DIRS}
610 ${LIBVA-X11_INCLUDE_DIRS}
611 ${LIBVA_INCLUDE_DIRS}
612 )
613 message(STATUS "VA-API found")
614 else()
615 set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
616 endif()
617
618 if (FFNVCODEC_FOUND AND CUDA_FOUND)
619 list(APPEND FFmpeg_HWACCEL_FLAGS
620 --enable-cuvid
621 --enable-ffnvcodec
622 --enable-nvdec
623 --enable-hwaccel=h264_nvdec
624 --enable-hwaccel=vp8_nvdec
625 --enable-hwaccel=vp9_nvdec
626 --extra-cflags=-I${CUDA_INCLUDE_DIRS}
627 )
628 list(APPEND FFmpeg_HWACCEL_LIBRARIES
629 ${FFNVCODEC_LIBRARIES}
630 ${CUDA_LIBRARIES}
631 )
632 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
633 ${FFNVCODEC_INCLUDE_DIRS}
634 ${CUDA_INCLUDE_DIRS}
635 )
636 list(APPEND FFmpeg_HWACCEL_LDFLAGS
637 ${FFNVCODEC_LDFLAGS}
638 ${CUDA_LDFLAGS}
639 )
640 message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
641 endif()
642
643 if (VDPAU_FOUND)
644 list(APPEND FFmpeg_HWACCEL_FLAGS
645 --enable-vdpau
646 --enable-hwaccel=h264_vdpau
647 --enable-hwaccel=vp9_vdpau
648 )
649 list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
650 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
651 list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
652 message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
653 else()
654 list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
655 endif()
656
657 # `configure` parameters builds only exactly what yuzu needs from FFmpeg
658 # `--disable-vdpau` is needed to avoid linking issues
659 add_custom_command(
660 OUTPUT
661 ${FFmpeg_MAKEFILE}
662 COMMAND
663 /bin/bash ${FFmpeg_PREFIX}/configure
664 --disable-avdevice
665 --disable-avfilter
666 --disable-avformat
667 --disable-doc
668 --disable-everything
669 --disable-ffmpeg
670 --disable-ffprobe
671 --disable-network
672 --disable-postproc
673 --disable-swresample
674 --enable-decoder=h264
675 --enable-decoder=vp8
676 --enable-decoder=vp9
677 --cc="${CMAKE_C_COMPILER}"
678 --cxx="${CMAKE_CXX_COMPILER}"
679 ${FFmpeg_HWACCEL_FLAGS}
680 WORKING_DIRECTORY
681 ${FFmpeg_BUILD_DIR}
682 )
683 unset(FFmpeg_HWACCEL_FLAGS)
684
685 # Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
686 # with context of the jobserver. Also helps ninja users.
687 execute_process(
688 COMMAND
689 nproc
690 OUTPUT_VARIABLE
691 SYSTEM_THREADS)
692
693 set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
694 add_custom_command(
695 OUTPUT
696 ${FFmpeg_BUILD_LIBRARIES}
697 COMMAND
698 make -j${SYSTEM_THREADS}
699 WORKING_DIRECTORY
700 ${FFmpeg_BUILD_DIR}
701 )
702
703 set(FFmpeg_INCLUDE_DIR
704 "${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
705 CACHE PATH "Path to FFmpeg headers" FORCE)
706
707 set(FFmpeg_LDFLAGS
708 "${FFmpeg_HWACCEL_LDFLAGS}"
709 CACHE STRING "FFmpeg linker flags" FORCE)
710
711 # ALL makes this custom target build every time
712 # but it won't actually build if the DEPENDS parameter is up to date
713 add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
714 add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
715 link_libraries(${FFmpeg_LIBVA_LIBRARIES})
716 set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
717 CACHE PATH "Paths to FFmpeg libraries" FORCE)
718 unset(FFmpeg_BUILD_LIBRARIES)
719 unset(FFmpeg_HWACCEL_FLAGS)
720 unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
721 unset(FFmpeg_HWACCEL_LDFLAGS)
722 unset(FFmpeg_HWACCEL_LIBRARIES)
723
724 if (FFmpeg_FOUND)
725 message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
726 else()
727 message(FATAL_ERROR "FFmpeg not found")
728 endif()
729 else() # WIN32
730 # Use yuzu FFmpeg binaries
731 set(FFmpeg_EXT_NAME "ffmpeg-4.4")
732 set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
733 download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
734 set(FFmpeg_FOUND YES)
735 set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
736 set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
737 set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
738 set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
739 set(FFmpeg_LIBRARIES
740 ${FFmpeg_LIBRARY_DIR}/swscale.lib
741 ${FFmpeg_LIBRARY_DIR}/avcodec.lib
742 ${FFmpeg_LIBRARY_DIR}/avutil.lib
743 CACHE PATH "Paths to FFmpeg libraries" FORCE)
744 endif()
745endif()
746
747unset(FFmpeg_COMPONENTS)
748
749# Prefer the -pthread flag on Linux. 535# Prefer the -pthread flag on Linux.
750set(THREADS_PREFER_PTHREAD_FLAG ON) 536set(THREADS_PREFER_PTHREAD_FLAG ON)
751find_package(Threads REQUIRED) 537find_package(Threads REQUIRED)
diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake
index 43ca730ec..c7da2b91d 100644
--- a/CMakeModules/GenerateSCMRev.cmake
+++ b/CMakeModules/GenerateSCMRev.cmake
@@ -11,9 +11,15 @@ find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
11 11
12# generate git/build information 12# generate git/build information
13include(GetGitRevisionDescription) 13include(GetGitRevisionDescription)
14get_git_head_revision(GIT_REF_SPEC GIT_REV) 14if(NOT GIT_REF_SPEC)
15git_describe(GIT_DESC --always --long --dirty) 15 get_git_head_revision(GIT_REF_SPEC GIT_REV)
16git_branch_name(GIT_BRANCH) 16endif()
17if(NOT GIT_DESC)
18 git_describe(GIT_DESC --always --long --dirty)
19endif()
20if (NOT GIT_BRANCH)
21 git_branch_name(GIT_BRANCH)
22endif()
17get_timestamp(BUILD_DATE) 23get_timestamp(BUILD_DATE)
18 24
19# Generate cpp with Git revision from template 25# Generate cpp with Git revision from template
diff --git a/dist/yuzu.desktop b/dist/yuzu.desktop
index 105080c73..6cc0704d2 100644
--- a/dist/yuzu.desktop
+++ b/dist/yuzu.desktop
@@ -8,5 +8,5 @@ Icon=yuzu
8TryExec=yuzu 8TryExec=yuzu
9Exec=yuzu %f 9Exec=yuzu %f
10Categories=Game;Emulator;Qt; 10Categories=Game;Emulator;Qt;
11MimeType=application/x-nx-nro;application/x-nx-nso; 11MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
12Keywords=Switch;Nintendo; \ No newline at end of file 12Keywords=Switch;Nintendo; \ No newline at end of file
diff --git a/dist/yuzu.xml b/dist/yuzu.xml
index f6e408321..dd1e30a6b 100644
--- a/dist/yuzu.xml
+++ b/dist/yuzu.xml
@@ -15,4 +15,19 @@
15 <glob pattern="*.nso"/> 15 <glob pattern="*.nso"/>
16 <magic><match value="NSO" type="string" offset="0"/></magic> 16 <magic><match value="NSO" type="string" offset="0"/></magic>
17 </mime-type> 17 </mime-type>
18
19 <mime-type type="application/x-nx-nsp">
20 <comment>Nintendo Switch Package</comment>
21 <acronym>NSP</acronym>
22 <icon name="yuzu"/>
23 <glob pattern="*.nsp"/>
24 <magic><match value="PFS" type="string" offset="0"/></magic>
25 </mime-type>
26
27 <mime-type type="application/x-nx-xci">
28 <comment>Nintendo Switch Card Image</comment>
29 <acronym>XCI</acronym>
30 <icon name="yuzu"/>
31 <glob pattern="*.xci"/>
32 </mime-type>
18</mime-info> \ No newline at end of file 33</mime-info> \ No newline at end of file
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 64d1e6aec..e9095b123 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -52,11 +52,12 @@ endif()
52# SDL2 52# SDL2
53if (YUZU_USE_EXTERNAL_SDL2) 53if (YUZU_USE_EXTERNAL_SDL2)
54 if (NOT WIN32) 54 if (NOT WIN32)
55 # Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio 55 # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers
56 # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095)
56 # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) 57 # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
57 set(SDL_UNUSED_SUBSYSTEMS 58 set(SDL_UNUSED_SUBSYSTEMS
58 Atomic Render Power Threads 59 CPUinfo File Filesystem
59 File CPUinfo Filesystem Locale) 60 Locale Power Render)
60 foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) 61 foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
61 string(TOUPPER ${_SUB} _OPT) 62 string(TOUPPER ${_SUB} _OPT)
62 option(SDL_${_OPT} "" OFF) 63 option(SDL_${_OPT} "" OFF)
@@ -121,3 +122,12 @@ if (NOT opus_FOUND)
121 message(STATUS "opus 1.3 or newer not found, falling back to externals") 122 message(STATUS "opus 1.3 or newer not found, falling back to externals")
122 add_subdirectory(opus EXCLUDE_FROM_ALL) 123 add_subdirectory(opus EXCLUDE_FROM_ALL)
123endif() 124endif()
125
126# FFMpeg
127if (YUZU_USE_BUNDLED_FFMPEG)
128 add_subdirectory(ffmpeg)
129 set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
130 set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
131 set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
132 set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
133endif()
diff --git a/externals/SDL b/externals/SDL
Subproject 2e9821423a237a1206e3c09020778faacfe430b Subproject e2ade2bfc46d915cd306c63c830b81d800b2575
diff --git a/externals/Vulkan-Headers b/externals/Vulkan-Headers
Subproject 07c4a37bcf41ea50aef6e98236abdfe8089fb4c Subproject e005e1f8175d006adc3676b40ac3dd2212961a6
diff --git a/externals/ffmpeg b/externals/ffmpeg
deleted file mode 160000
Subproject 79e8d17024e6c6328a40fcee191ffd70798a9c6
diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt
new file mode 100644
index 000000000..c57b54f77
--- /dev/null
+++ b/externals/ffmpeg/CMakeLists.txt
@@ -0,0 +1,214 @@
1if (NOT WIN32)
2 # Build FFmpeg from externals
3 message(STATUS "Using FFmpeg from externals")
4
5 if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64)")
6 # FFmpeg has source that requires one of nasm or yasm to assemble it.
7 # REQUIRED throws an error if not found here during configuration rather than during compilation.
8 find_program(ASSEMBLER NAMES nasm yasm)
9 if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
10 message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
11 endif()
12 endif()
13
14 find_program(AUTOCONF autoconf)
15 if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
16 message(FATAL_ERROR "Required program `autoconf` not found.")
17 endif()
18
19 set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg/ffmpeg)
20 set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg-build)
21 set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
22 make_directory(${FFmpeg_BUILD_DIR})
23
24 # Read version string from external
25 file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
26 set(FFmpeg_FOUND NO)
27 if (NOT FFmpeg_VERSION STREQUAL "")
28 set(FFmpeg_FOUND YES)
29 endif()
30
31 unset(FFmpeg_LIBRARIES CACHE)
32 foreach(COMPONENT ${FFmpeg_COMPONENTS})
33 set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
34 set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
35 set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
36
37 set(FFmpeg_LIBRARIES
38 ${FFmpeg_LIBRARIES}
39 ${FFmpeg_${COMPONENT}_LIBRARY}
40 CACHE PATH "Paths to FFmpeg libraries" FORCE)
41 endforeach()
42
43 Include(FindPkgConfig REQUIRED)
44 pkg_check_modules(LIBVA libva)
45 pkg_check_modules(CUDA cuda)
46 pkg_check_modules(FFNVCODEC ffnvcodec)
47 pkg_check_modules(VDPAU vdpau)
48
49 set(FFmpeg_HWACCEL_LIBRARIES)
50 set(FFmpeg_HWACCEL_FLAGS)
51 set(FFmpeg_HWACCEL_INCLUDE_DIRS)
52 set(FFmpeg_HWACCEL_LDFLAGS)
53
54 if(LIBVA_FOUND)
55 pkg_check_modules(LIBDRM libdrm REQUIRED)
56 find_package(X11 REQUIRED)
57 pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
58 pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
59 list(APPEND FFmpeg_HWACCEL_LIBRARIES
60 ${LIBDRM_LIBRARIES}
61 ${X11_LIBRARIES}
62 ${LIBVA-DRM_LIBRARIES}
63 ${LIBVA-X11_LIBRARIES}
64 ${LIBVA_LIBRARIES})
65 set(FFmpeg_HWACCEL_FLAGS
66 --enable-hwaccel=h264_vaapi
67 --enable-hwaccel=vp8_vaapi
68 --enable-hwaccel=vp9_vaapi
69 --enable-libdrm)
70 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
71 ${LIBDRM_INCLUDE_DIRS}
72 ${X11_INCLUDE_DIRS}
73 ${LIBVA-DRM_INCLUDE_DIRS}
74 ${LIBVA-X11_INCLUDE_DIRS}
75 ${LIBVA_INCLUDE_DIRS}
76 )
77 message(STATUS "VA-API found")
78 else()
79 set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
80 endif()
81
82 if (FFNVCODEC_FOUND)
83 list(APPEND FFmpeg_HWACCEL_FLAGS
84 --enable-cuvid
85 --enable-ffnvcodec
86 --enable-nvdec
87 --enable-hwaccel=h264_nvdec
88 --enable-hwaccel=vp8_nvdec
89 --enable-hwaccel=vp9_nvdec
90 )
91 list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES})
92 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS})
93 list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS})
94 message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
95 # ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress
96 # here we handle the hard-linking senario where CUDA is linked during compilation
97 if (CUDA_FOUND)
98 list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
99 list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
100 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
101 list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
102 message(STATUS "CUDA libraries found, hard-linking will be performed")
103 endif(CUDA_FOUND)
104 endif()
105
106 if (VDPAU_FOUND)
107 list(APPEND FFmpeg_HWACCEL_FLAGS
108 --enable-vdpau
109 --enable-hwaccel=h264_vdpau
110 --enable-hwaccel=vp9_vdpau
111 )
112 list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
113 list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
114 list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
115 message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
116 else()
117 list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
118 endif()
119
120 # `configure` parameters builds only exactly what yuzu needs from FFmpeg
121 # `--disable-vdpau` is needed to avoid linking issues
122 add_custom_command(
123 OUTPUT
124 ${FFmpeg_MAKEFILE}
125 COMMAND
126 /bin/bash ${FFmpeg_PREFIX}/configure
127 --disable-avdevice
128 --disable-avfilter
129 --disable-avformat
130 --disable-doc
131 --disable-everything
132 --disable-ffmpeg
133 --disable-ffprobe
134 --disable-network
135 --disable-postproc
136 --disable-swresample
137 --enable-decoder=h264
138 --enable-decoder=vp8
139 --enable-decoder=vp9
140 --cc="${CMAKE_C_COMPILER}"
141 --cxx="${CMAKE_CXX_COMPILER}"
142 ${FFmpeg_HWACCEL_FLAGS}
143 WORKING_DIRECTORY
144 ${FFmpeg_BUILD_DIR}
145 )
146 unset(FFmpeg_HWACCEL_FLAGS)
147
148 # Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
149 # with context of the jobserver. Also helps ninja users.
150 execute_process(
151 COMMAND
152 nproc
153 OUTPUT_VARIABLE
154 SYSTEM_THREADS)
155
156 set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
157 add_custom_command(
158 OUTPUT
159 ${FFmpeg_BUILD_LIBRARIES}
160 COMMAND
161 make -j${SYSTEM_THREADS}
162 WORKING_DIRECTORY
163 ${FFmpeg_BUILD_DIR}
164 )
165
166 set(FFmpeg_INCLUDE_DIR
167 "${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
168 CACHE PATH "Path to FFmpeg headers" FORCE)
169
170 set(FFmpeg_LDFLAGS
171 "${FFmpeg_HWACCEL_LDFLAGS}"
172 CACHE STRING "FFmpeg linker flags" FORCE)
173
174 # ALL makes this custom target build every time
175 # but it won't actually build if the DEPENDS parameter is up to date
176 add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
177 add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
178 link_libraries(${FFmpeg_LIBVA_LIBRARIES})
179 set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
180 CACHE PATH "Paths to FFmpeg libraries" FORCE)
181 unset(FFmpeg_BUILD_LIBRARIES)
182 unset(FFmpeg_HWACCEL_FLAGS)
183 unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
184 unset(FFmpeg_HWACCEL_LDFLAGS)
185 unset(FFmpeg_HWACCEL_LIBRARIES)
186
187 if (FFmpeg_FOUND)
188 message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
189 else()
190 message(FATAL_ERROR "FFmpeg not found")
191 endif()
192else(WIN32)
193 # Use yuzu FFmpeg binaries
194 set(FFmpeg_EXT_NAME "ffmpeg-4.4")
195 set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
196 download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
197 set(FFmpeg_FOUND YES)
198 set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
199 set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
200 set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
201 set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
202 set(FFmpeg_LIBRARIES
203 ${FFmpeg_LIBRARY_DIR}/swscale.lib
204 ${FFmpeg_LIBRARY_DIR}/avcodec.lib
205 ${FFmpeg_LIBRARY_DIR}/avutil.lib
206 CACHE PATH "Paths to FFmpeg libraries" FORCE)
207 # exported variables
208 set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
209 set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
210 set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
211 set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
212endif(WIN32)
213
214unset(FFmpeg_COMPONENTS)
diff --git a/externals/ffmpeg/ffmpeg b/externals/ffmpeg/ffmpeg
new file mode 160000
Subproject dc91b913b6260e85e1304c74ff7bb3c22a8c9fb
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 919da4a53..790193b00 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -22,6 +22,11 @@ add_custom_command(OUTPUT scm_rev.cpp
22 -DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING} 22 -DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING}
23 -DBUILD_TAG=${BUILD_TAG} 23 -DBUILD_TAG=${BUILD_TAG}
24 -DBUILD_ID=${DISPLAY_VERSION} 24 -DBUILD_ID=${DISPLAY_VERSION}
25 -DGIT_REF_SPEC=${GIT_REF_SPEC}
26 -DGIT_REV=${GIT_REV}
27 -DGIT_DESC=${GIT_DESC}
28 -DGIT_BRANCH=${GIT_BRANCH}
29 -DBUILD_FULLNAME=${BUILD_FULLNAME}
25 -DGIT_EXECUTABLE=${GIT_EXECUTABLE} 30 -DGIT_EXECUTABLE=${GIT_EXECUTABLE}
26 -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake 31 -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
27 DEPENDS 32 DEPENDS
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 49bed614a..698c4f912 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -265,8 +265,6 @@ add_library(core STATIC
265 hle/kernel/svc_wrap.h 265 hle/kernel/svc_wrap.h
266 hle/kernel/time_manager.cpp 266 hle/kernel/time_manager.cpp
267 hle/kernel/time_manager.h 267 hle/kernel/time_manager.h
268 hle/lock.cpp
269 hle/lock.h
270 hle/result.h 268 hle/result.h
271 hle/service/acc/acc.cpp 269 hle/service/acc/acc.cpp
272 hle/service/acc/acc.h 270 hle/service/acc/acc.h
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 685ec080c..08f8af551 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -161,7 +161,10 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
161 motion.rotation = emulated.GetGyroscope(); 161 motion.rotation = emulated.GetGyroscope();
162 motion.orientation = emulated.GetOrientation(); 162 motion.orientation = emulated.GetOrientation();
163 motion.quaternion = emulated.GetQuaternion(); 163 motion.quaternion = emulated.GetQuaternion();
164 motion.gyro_bias = emulated.GetGyroBias();
164 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); 165 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
166 // Find what is this value
167 motion.verticalization_error = 0.0f;
165 168
166 TriggerOnChange(ConsoleTriggerType::Motion); 169 TriggerOnChange(ConsoleTriggerType::Motion);
167} 170}
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index 3afd284d5..707419102 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -50,6 +50,8 @@ struct ConsoleMotion {
50 Common::Vec3f rotation{}; 50 Common::Vec3f rotation{};
51 std::array<Common::Vec3f, 3> orientation{}; 51 std::array<Common::Vec3f, 3> orientation{};
52 Common::Quaternion<f32> quaternion{}; 52 Common::Quaternion<f32> quaternion{};
53 Common::Vec3f gyro_bias{};
54 f32 verticalization_error{};
53 bool is_at_rest{}; 55 bool is_at_rest{};
54}; 56};
55 57
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 93372445b..ff9d7a7e3 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -843,23 +843,18 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
843} 843}
844 844
845bool EmulatedController::TestVibration(std::size_t device_index) { 845bool EmulatedController::TestVibration(std::size_t device_index) {
846 if (device_index >= output_devices.size()) { 846 static constexpr VibrationValue test_vibration = {
847 return false;
848 }
849 if (!output_devices[device_index]) {
850 return false;
851 }
852
853 // Send a slight vibration to test for rumble support
854 constexpr Common::Input::VibrationStatus status = {
855 .low_amplitude = 0.001f, 847 .low_amplitude = 0.001f,
856 .low_frequency = 160.0f, 848 .low_frequency = 160.0f,
857 .high_amplitude = 0.001f, 849 .high_amplitude = 0.001f,
858 .high_frequency = 320.0f, 850 .high_frequency = 320.0f,
859 .type = Common::Input::VibrationAmplificationType::Linear,
860 }; 851 };
861 return output_devices[device_index]->SetVibration(status) == 852
862 Common::Input::VibrationError::None; 853 // Send a slight vibration to test for rumble support
854 SetVibration(device_index, test_vibration);
855
856 // Stop any vibration and return the result
857 return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
863} 858}
864 859
865void EmulatedController::SetLedPattern() { 860void EmulatedController::SetLedPattern() {
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 7c12f01fc..4eca68533 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -496,6 +496,13 @@ struct VibrationValue {
496}; 496};
497static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); 497static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
498 498
499constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
500 .low_amplitude = 0.0f,
501 .low_frequency = 160.0f,
502 .high_amplitude = 0.0f,
503 .high_frequency = 320.0f,
504};
505
499// This is nn::hid::VibrationDeviceInfo 506// This is nn::hid::VibrationDeviceInfo
500struct VibrationDeviceInfo { 507struct VibrationDeviceInfo {
501 VibrationDeviceType type{}; 508 VibrationDeviceType type{};
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp
index c25fea966..a23f192d7 100644
--- a/src/core/hid/motion_input.cpp
+++ b/src/core/hid/motion_input.cpp
@@ -23,11 +23,11 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
23} 23}
24 24
25void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { 25void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
26 gyro = gyroscope - gyro_drift; 26 gyro = gyroscope - gyro_bias;
27 27
28 // Auto adjust drift to minimize drift 28 // Auto adjust drift to minimize drift
29 if (!IsMoving(0.1f)) { 29 if (!IsMoving(0.1f)) {
30 gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f); 30 gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
31 } 31 }
32 32
33 if (gyro.Length2() < gyro_threshold) { 33 if (gyro.Length2() < gyro_threshold) {
@@ -41,8 +41,8 @@ void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
41 quat = quaternion; 41 quat = quaternion;
42} 42}
43 43
44void MotionInput::SetGyroDrift(const Common::Vec3f& drift) { 44void MotionInput::SetGyroBias(const Common::Vec3f& bias) {
45 gyro_drift = drift; 45 gyro_bias = bias;
46} 46}
47 47
48void MotionInput::SetGyroThreshold(f32 threshold) { 48void MotionInput::SetGyroThreshold(f32 threshold) {
@@ -192,6 +192,10 @@ Common::Vec3f MotionInput::GetGyroscope() const {
192 return gyro; 192 return gyro;
193} 193}
194 194
195Common::Vec3f MotionInput::GetGyroBias() const {
196 return gyro_bias;
197}
198
195Common::Quaternion<f32> MotionInput::GetQuaternion() const { 199Common::Quaternion<f32> MotionInput::GetQuaternion() const {
196 return quat; 200 return quat;
197} 201}
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h
index 5b5b420bb..bca4520fa 100644
--- a/src/core/hid/motion_input.h
+++ b/src/core/hid/motion_input.h
@@ -24,7 +24,7 @@ public:
24 void SetAcceleration(const Common::Vec3f& acceleration); 24 void SetAcceleration(const Common::Vec3f& acceleration);
25 void SetGyroscope(const Common::Vec3f& gyroscope); 25 void SetGyroscope(const Common::Vec3f& gyroscope);
26 void SetQuaternion(const Common::Quaternion<f32>& quaternion); 26 void SetQuaternion(const Common::Quaternion<f32>& quaternion);
27 void SetGyroDrift(const Common::Vec3f& drift); 27 void SetGyroBias(const Common::Vec3f& bias);
28 void SetGyroThreshold(f32 threshold); 28 void SetGyroThreshold(f32 threshold);
29 29
30 void EnableReset(bool reset); 30 void EnableReset(bool reset);
@@ -36,6 +36,7 @@ public:
36 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; 36 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
37 [[nodiscard]] Common::Vec3f GetAcceleration() const; 37 [[nodiscard]] Common::Vec3f GetAcceleration() const;
38 [[nodiscard]] Common::Vec3f GetGyroscope() const; 38 [[nodiscard]] Common::Vec3f GetGyroscope() const;
39 [[nodiscard]] Common::Vec3f GetGyroBias() const;
39 [[nodiscard]] Common::Vec3f GetRotations() const; 40 [[nodiscard]] Common::Vec3f GetRotations() const;
40 [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; 41 [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
41 42
@@ -69,7 +70,7 @@ private:
69 Common::Vec3f gyro; 70 Common::Vec3f gyro;
70 71
71 // Vector to be substracted from gyro measurements 72 // Vector to be substracted from gyro measurements
72 Common::Vec3f gyro_drift; 73 Common::Vec3f gyro_bias;
73 74
74 // Minimum gyro amplitude to detect if the device is moving 75 // Minimum gyro amplitude to detect if the device is moving
75 f32 gyro_threshold = 0.0f; 76 f32 gyro_threshold = 0.0f;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 90dda40dc..aee313995 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -28,7 +28,6 @@
28#include "core/hle/kernel/k_thread.h" 28#include "core/hle/kernel/k_thread.h"
29#include "core/hle/kernel/kernel.h" 29#include "core/hle/kernel/kernel.h"
30#include "core/hle/kernel/svc_results.h" 30#include "core/hle/kernel/svc_results.h"
31#include "core/hle/lock.h"
32#include "core/memory.h" 31#include "core/memory.h"
33 32
34namespace Kernel { 33namespace Kernel {
@@ -543,7 +542,6 @@ void KProcess::FreeTLSRegion(VAddr tls_address) {
543} 542}
544 543
545void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { 544void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
546 std::lock_guard lock{HLE::g_hle_lock};
547 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 545 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
548 KMemoryPermission permission) { 546 KMemoryPermission permission) {
549 page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); 547 page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 2e4e4cb1c..1225e1fba 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -182,7 +182,10 @@ struct KernelCore::Impl {
182 // Shutdown all processes. 182 // Shutdown all processes.
183 if (current_process) { 183 if (current_process) {
184 current_process->Finalize(); 184 current_process->Finalize();
185 current_process->Close(); 185 // current_process->Close();
186 // TODO: The current process should be destroyed based on accurate ref counting after
187 // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
188 current_process->Destroy();
186 current_process = nullptr; 189 current_process = nullptr;
187 } 190 }
188 191
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index a9f7438ea..bb9475c56 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -41,7 +41,6 @@
41#include "core/hle/kernel/svc_results.h" 41#include "core/hle/kernel/svc_results.h"
42#include "core/hle/kernel/svc_types.h" 42#include "core/hle/kernel/svc_types.h"
43#include "core/hle/kernel/svc_wrap.h" 43#include "core/hle/kernel/svc_wrap.h"
44#include "core/hle/lock.h"
45#include "core/hle/result.h" 44#include "core/hle/result.h"
46#include "core/memory.h" 45#include "core/memory.h"
47#include "core/reporter.h" 46#include "core/reporter.h"
@@ -137,7 +136,6 @@ enum class ResourceLimitValueType {
137 136
138/// Set the process heap to a given Size. It can both extend and shrink the heap. 137/// Set the process heap to a given Size. It can both extend and shrink the heap.
139static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { 138static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
140 std::lock_guard lock{HLE::g_hle_lock};
141 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); 139 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
142 140
143 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. 141 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB.
@@ -168,7 +166,6 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
168 166
169static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 167static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
170 u32 attribute) { 168 u32 attribute) {
171 std::lock_guard lock{HLE::g_hle_lock};
172 LOG_DEBUG(Kernel_SVC, 169 LOG_DEBUG(Kernel_SVC,
173 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, 170 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
174 size, mask, attribute); 171 size, mask, attribute);
@@ -212,7 +209,6 @@ static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 si
212 209
213/// Maps a memory range into a different range. 210/// Maps a memory range into a different range.
214static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 211static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
215 std::lock_guard lock{HLE::g_hle_lock};
216 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 212 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
217 src_addr, size); 213 src_addr, size);
218 214
@@ -232,7 +228,6 @@ static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr,
232 228
233/// Unmaps a region that was previously mapped with svcMapMemory 229/// Unmaps a region that was previously mapped with svcMapMemory
234static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 230static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
235 std::lock_guard lock{HLE::g_hle_lock};
236 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 231 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
237 src_addr, size); 232 src_addr, size);
238 233
@@ -642,7 +637,6 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) {
642/// Gets system/memory information for the current process 637/// Gets system/memory information for the current process
643static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, 638static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle,
644 u64 info_sub_id) { 639 u64 info_sub_id) {
645 std::lock_guard lock{HLE::g_hle_lock};
646 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, 640 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
647 info_sub_id, handle); 641 info_sub_id, handle);
648 642
@@ -924,7 +918,6 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h
924 918
925/// Maps memory at a desired address 919/// Maps memory at a desired address
926static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 920static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
927 std::lock_guard lock{HLE::g_hle_lock};
928 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 921 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
929 922
930 if (!Common::Is4KBAligned(addr)) { 923 if (!Common::Is4KBAligned(addr)) {
@@ -978,7 +971,6 @@ static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size)
978 971
979/// Unmaps memory previously mapped via MapPhysicalMemory 972/// Unmaps memory previously mapped via MapPhysicalMemory
980static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 973static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
981 std::lock_guard lock{HLE::g_hle_lock};
982 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 974 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
983 975
984 if (!Common::Is4KBAligned(addr)) { 976 if (!Common::Is4KBAligned(addr)) {
@@ -1520,7 +1512,6 @@ static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_han
1520static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1512static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
1521 VAddr page_info_address, Handle process_handle, 1513 VAddr page_info_address, Handle process_handle,
1522 VAddr address) { 1514 VAddr address) {
1523 std::lock_guard lock{HLE::g_hle_lock};
1524 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); 1515 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
1525 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1516 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1526 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); 1517 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
diff --git a/src/core/hle/lock.cpp b/src/core/hle/lock.cpp
deleted file mode 100644
index be4bfce3b..000000000
--- a/src/core/hle/lock.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <core/hle/lock.h>
6
7namespace HLE {
8std::recursive_mutex g_hle_lock;
9}
diff --git a/src/core/hle/lock.h b/src/core/hle/lock.h
deleted file mode 100644
index 5c99fe996..000000000
--- a/src/core/hle/lock.h
+++ /dev/null
@@ -1,18 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <mutex>
8
9namespace HLE {
10/*
11 * Synchronizes access to the internal HLE kernel structures, it is acquired when a guest
12 * application thread performs a syscall. It should be acquired by any host threads that read or
13 * modify the HLE kernel state. Note: Any operation that directly or indirectly reads from or writes
14 * to the emulated memory is not protected by this mutex, and should be avoided in any threads other
15 * than the CPU thread.
16 */
17extern std::recursive_mutex g_hle_lock;
18} // namespace HLE
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index 4c7d3bb6e..ee49edbb9 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -6,7 +6,6 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/kernel/k_event.h" 8#include "core/hle/kernel/k_event.h"
9#include "core/hle/lock.h"
10#include "core/hle/service/bcat/backend/backend.h" 9#include "core/hle/service/bcat/backend/backend.h"
11 10
12namespace Service::BCAT { 11namespace Service::BCAT {
@@ -29,10 +28,6 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
29 return impl; 28 return impl;
30} 29}
31 30
32void ProgressServiceBackend::SetNeedHLELock(bool need) {
33 need_hle_lock = need;
34}
35
36void ProgressServiceBackend::SetTotalSize(u64 size) { 31void ProgressServiceBackend::SetTotalSize(u64 size) {
37 impl.total_bytes = size; 32 impl.total_bytes = size;
38 SignalUpdate(); 33 SignalUpdate();
@@ -88,12 +83,7 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
88} 83}
89 84
90void ProgressServiceBackend::SignalUpdate() { 85void ProgressServiceBackend::SignalUpdate() {
91 if (need_hle_lock) { 86 update_event->GetWritableEvent().Signal();
92 std::lock_guard lock(HLE::g_hle_lock);
93 update_event->GetWritableEvent().Signal();
94 } else {
95 update_event->GetWritableEvent().Signal();
96 }
97} 87}
98 88
99Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} 89Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {}
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h
index 59c6d4740..63833c927 100644
--- a/src/core/hle/service/bcat/backend/backend.h
+++ b/src/core/hle/service/bcat/backend/backend.h
@@ -71,10 +71,6 @@ class ProgressServiceBackend {
71public: 71public:
72 ~ProgressServiceBackend(); 72 ~ProgressServiceBackend();
73 73
74 // Clients should call this with true if any of the functions are going to be called from a
75 // non-HLE thread and this class need to lock the hle mutex. (default is false)
76 void SetNeedHLELock(bool need);
77
78 // Sets the number of bytes total in the entire download. 74 // Sets the number of bytes total in the entire download.
79 void SetTotalSize(u64 size); 75 void SetTotalSize(u64 size);
80 76
@@ -109,7 +105,6 @@ private:
109 105
110 DeliveryCacheProgressImpl impl{}; 106 DeliveryCacheProgressImpl impl{};
111 Kernel::KEvent* update_event; 107 Kernel::KEvent* update_event;
112 bool need_hle_lock = false;
113}; 108};
114 109
115// A class representing an abstract backend for BCAT functionality. 110// A class representing an abstract backend for BCAT functionality.
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index f0f3105dc..a727b3582 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -33,15 +33,14 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
33 const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; 33 const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
34 next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; 34 next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
35 35
36 // Try to read sixaxis sensor states
37 const auto motion_status = console->GetMotion(); 36 const auto motion_status = console->GetMotion();
37 last_global_timestamp = core_timing.GetGlobalTimeNs().count();
38 38
39 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; 39 // This value increments every time the switch goes to sleep
40 40 next_seven_sixaxis_state.unknown = 1;
41 next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp;
41 next_seven_sixaxis_state.accel = motion_status.accel; 42 next_seven_sixaxis_state.accel = motion_status.accel;
42 // Zero gyro values as they just mess up with the camera 43 next_seven_sixaxis_state.gyro = motion_status.gyro;
43 // Note: Probably a correct sensivity setting must be set
44 next_seven_sixaxis_state.gyro = {};
45 next_seven_sixaxis_state.quaternion = { 44 next_seven_sixaxis_state.quaternion = {
46 { 45 {
47 motion_status.quaternion.xyz.y, 46 motion_status.quaternion.xyz.y,
@@ -52,9 +51,9 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
52 }; 51 };
53 52
54 console_six_axis.sampling_number++; 53 console_six_axis.sampling_number++;
55 // TODO(German77): Find the purpose of those values 54 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
56 console_six_axis.verticalization_error = 0.0f; 55 console_six_axis.verticalization_error = motion_status.verticalization_error;
57 console_six_axis.gyro_bias = {0.0f, 0.0f, 0.0f}; 56 console_six_axis.gyro_bias = motion_status.gyro_bias;
58 57
59 // Update console six axis shared memory 58 // Update console six axis shared memory
60 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); 59 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
@@ -69,7 +68,6 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
69} 68}
70 69
71void Controller_ConsoleSixAxis::ResetTimestamp() { 70void Controller_ConsoleSixAxis::ResetTimestamp() {
72 seven_sixaxis_lifo.buffer_count = 0; 71 last_saved_timestamp = last_global_timestamp;
73 seven_sixaxis_lifo.buffer_tail = 0;
74} 72}
75} // namespace Service::HID 73} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 279241858..26d153f0c 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -39,8 +39,9 @@ public:
39 39
40private: 40private:
41 struct SevenSixAxisState { 41 struct SevenSixAxisState {
42 INSERT_PADDING_WORDS(4); // unused 42 INSERT_PADDING_WORDS(2); // unused
43 s64 sampling_number{}; 43 u64 timestamp{};
44 u64 sampling_number{};
44 u64 unknown{}; 45 u64 unknown{};
45 Common::Vec3f accel{}; 46 Common::Vec3f accel{};
46 Common::Vec3f gyro{}; 47 Common::Vec3f gyro{};
@@ -52,9 +53,10 @@ private:
52 struct ConsoleSharedMemory { 53 struct ConsoleSharedMemory {
53 u64 sampling_number{}; 54 u64 sampling_number{};
54 bool is_seven_six_axis_sensor_at_rest{}; 55 bool is_seven_six_axis_sensor_at_rest{};
55 INSERT_PADDING_BYTES(4); // padding 56 INSERT_PADDING_BYTES(3); // padding
56 f32 verticalization_error{}; 57 f32 verticalization_error{};
57 Common::Vec3f gyro_bias{}; 58 Common::Vec3f gyro_bias{};
59 INSERT_PADDING_BYTES(4); // padding
58 }; 60 };
59 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); 61 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
60 62
@@ -64,6 +66,8 @@ private:
64 Core::HID::EmulatedConsole* console; 66 Core::HID::EmulatedConsole* console;
65 u8* transfer_memory = nullptr; 67 u8* transfer_memory = nullptr;
66 bool is_transfer_memory_set = false; 68 bool is_transfer_memory_set = false;
69 u64 last_saved_timestamp{};
70 u64 last_global_timestamp{};
67 ConsoleSharedMemory console_six_axis{}; 71 ConsoleSharedMemory console_six_axis{};
68 SevenSixAxisState next_seven_sixaxis_state{}; 72 SevenSixAxisState next_seven_sixaxis_state{};
69}; 73};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 2705e9dcb..e5c951e06 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -66,9 +66,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
66 auto& controller = controller_data[i]; 66 auto& controller = controller_data[i];
67 controller.device = hid_core.GetEmulatedControllerByIndex(i); 67 controller.device = hid_core.GetEmulatedControllerByIndex(i);
68 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = 68 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
69 DEFAULT_VIBRATION_VALUE; 69 Core::HID::DEFAULT_VIBRATION_VALUE;
70 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value = 70 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
71 DEFAULT_VIBRATION_VALUE; 71 Core::HID::DEFAULT_VIBRATION_VALUE;
72 Core::HID::ControllerUpdateCallback engine_callback{ 72 Core::HID::ControllerUpdateCallback engine_callback{
73 .on_change = [this, 73 .on_change = [this,
74 i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, 74 i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@@ -781,7 +781,8 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
781 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; 781 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
782 controller.device->SetVibration(device_index, vibration); 782 controller.device->SetVibration(device_index, vibration);
783 // Then reset the vibration value to its default value. 783 // Then reset the vibration value to its default value.
784 controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE; 784 controller.vibration[device_index].latest_vibration_value =
785 Core::HID::DEFAULT_VIBRATION_VALUE;
785 } 786 }
786 787
787 return false; 788 return false;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 63281cb35..6b2872bad 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -90,13 +90,6 @@ public:
90 Default = 3, 90 Default = 3,
91 }; 91 };
92 92
93 static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
94 .low_amplitude = 0.0f,
95 .low_frequency = 160.0f,
96 .high_amplitude = 0.0f,
97 .high_frequency = 320.0f,
98 };
99
100 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); 93 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
101 Core::HID::NpadStyleTag GetSupportedStyleSet() const; 94 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
102 95
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 7163e1a4e..6e12381fb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1404,7 +1404,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1404 .high_frequency = 0.0f, 1404 .high_frequency = 0.0f,
1405 }; 1405 };
1406 default: 1406 default:
1407 return Controller_NPad::DEFAULT_VIBRATION_VALUE; 1407 return Core::HID::DEFAULT_VIBRATION_VALUE;
1408 } 1408 }
1409 }(); 1409 }();
1410 1410
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 693ffc71a..761d0d3c6 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -9,7 +9,6 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/k_event.h" 11#include "core/hle/kernel/k_event.h"
12#include "core/hle/lock.h"
13#include "core/hle/service/nfp/nfp.h" 12#include "core/hle/service/nfp/nfp.h"
14#include "core/hle/service/nfp/nfp_user.h" 13#include "core/hle/service/nfp/nfp_user.h"
15 14
@@ -337,7 +336,6 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
337} 336}
338 337
339bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { 338bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
340 std::lock_guard lock{HLE::g_hle_lock};
341 if (buffer.size() < sizeof(AmiiboFile)) { 339 if (buffer.size() < sizeof(AmiiboFile)) {
342 return false; 340 return false;
343 } 341 }
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
index 3ae9e6e0e..99ed34b00 100644
--- a/src/core/loader/kip.cpp
+++ b/src/core/loader/kip.cpp
@@ -71,7 +71,6 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
71 kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000, 71 kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000,
72 kip->GetKernelCapabilities()); 72 kip->GetKernelCapabilities());
73 73
74 const VAddr base_address = process.PageTable().GetCodeRegionStart();
75 Kernel::CodeSet codeset; 74 Kernel::CodeSet codeset;
76 Kernel::PhysicalMemory program_image; 75 Kernel::PhysicalMemory program_image;
77 76
@@ -91,7 +90,14 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
91 program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize()); 90 program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
92 codeset.DataSegment().size += kip->GetBSSSize(); 91 codeset.DataSegment().size += kip->GetBSSSize();
93 92
93 // Setup the process code layout
94 if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
95 .IsError()) {
96 return {ResultStatus::ErrorNotInitialized, {}};
97 }
98
94 codeset.memory = std::move(program_image); 99 codeset.memory = std::move(program_image);
100 const VAddr base_address = process.PageTable().GetCodeRegionStart();
95 process.LoadModule(std::move(codeset), base_address); 101 process.LoadModule(std::move(codeset), base_address);
96 102
97 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); 103 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 4ab991a7d..a1ce4525d 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -536,42 +536,46 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
536 std::function<void(u16, u16, u16, u16)> data_callback) { 536 std::function<void(u16, u16, u16, u16)> data_callback) {
537 537
538 std::thread([=, this] { 538 std::thread([=, this] {
539 u16 min_x{UINT16_MAX};
540 u16 min_y{UINT16_MAX};
541 u16 max_x{};
542 u16 max_y{};
543
539 Status current_status{Status::Initialized}; 544 Status current_status{Status::Initialized};
540 SocketCallback callback{ 545 SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
541 [](Response::Version) {}, [](Response::PortInfo) {}, 546 [&](Response::PadData data) {
542 [&](Response::PadData data) { 547 constexpr u16 CALIBRATION_THRESHOLD = 100;
543 static constexpr u16 CALIBRATION_THRESHOLD = 100; 548
544 static constexpr u16 MAX_VALUE = UINT16_MAX; 549 if (current_status == Status::Initialized) {
545 550 // Receiving data means the communication is ready now
546 if (current_status == Status::Initialized) { 551 current_status = Status::Ready;
547 // Receiving data means the communication is ready now 552 status_callback(current_status);
548 current_status = Status::Ready; 553 }
549 status_callback(current_status); 554 if (data.touch[0].is_active == 0) {
550 } 555 return;
551 const auto& touchpad_0 = data.touch[0]; 556 }
552 if (touchpad_0.is_active == 0) { 557 LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x,
553 return; 558 data.touch[0].y);
554 } 559 min_x = std::min(min_x, static_cast<u16>(data.touch[0].x));
555 LOG_DEBUG(Input, "Current touch: {} {}", touchpad_0.x, touchpad_0.y); 560 min_y = std::min(min_y, static_cast<u16>(data.touch[0].y));
556 const u16 min_x = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.x)); 561 if (current_status == Status::Ready) {
557 const u16 min_y = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.y)); 562 // First touch - min data (min_x/min_y)
558 if (current_status == Status::Ready) { 563 current_status = Status::Stage1Completed;
559 // First touch - min data (min_x/min_y) 564 status_callback(current_status);
560 current_status = Status::Stage1Completed; 565 }
561 status_callback(current_status); 566 if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
562 } 567 data.touch[0].y - min_y > CALIBRATION_THRESHOLD) {
563 if (touchpad_0.x - min_x > CALIBRATION_THRESHOLD && 568 // Set the current position as max value and finishes
564 touchpad_0.y - min_y > CALIBRATION_THRESHOLD) { 569 // configuration
565 // Set the current position as max value and finishes configuration 570 max_x = data.touch[0].x;
566 const u16 max_x = touchpad_0.x; 571 max_y = data.touch[0].y;
567 const u16 max_y = touchpad_0.y; 572 current_status = Status::Completed;
568 current_status = Status::Completed; 573 data_callback(min_x, min_y, max_x, max_y);
569 data_callback(min_x, min_y, max_x, max_y); 574 status_callback(current_status);
570 status_callback(current_status); 575
571 576 complete_event.Set();
572 complete_event.Set(); 577 }
573 } 578 }};
574 }};
575 Socket socket{host, port, std::move(callback)}; 579 Socket socket{host, port, std::move(callback)};
576 std::thread worker_thread{SocketLoop, &socket}; 580 std::thread worker_thread{SocketLoop, &socket};
577 complete_event.Wait(); 581 complete_event.Wait();
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index bcba12c58..2d5d54ddb 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -54,6 +54,18 @@ struct Message {
54template <typename T> 54template <typename T>
55constexpr Type GetMessageType(); 55constexpr Type GetMessageType();
56 56
57template <typename T>
58Message<T> CreateMessage(const u32 magic, const T data, const u32 sender_id) {
59 boost::crc_32_type crc;
60 Header header{
61 magic, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, sender_id, GetMessageType<T>(),
62 };
63 Message<T> message{header, data};
64 crc.process_bytes(&message, sizeof(Message<T>));
65 message.header.crc = crc.checksum();
66 return message;
67}
68
57namespace Request { 69namespace Request {
58 70
59enum RegisterFlags : u8 { 71enum RegisterFlags : u8 {
@@ -101,14 +113,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
101 */ 113 */
102template <typename T> 114template <typename T>
103Message<T> Create(const T data, const u32 client_id = 0) { 115Message<T> Create(const T data, const u32 client_id = 0) {
104 boost::crc_32_type crc; 116 return CreateMessage(CLIENT_MAGIC, data, client_id);
105 Header header{
106 CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType<T>(),
107 };
108 Message<T> message{header, data};
109 crc.process_bytes(&message, sizeof(Message<T>));
110 message.header.crc = crc.checksum();
111 return message;
112} 117}
113} // namespace Request 118} // namespace Request
114 119
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index c4c012f3d..4a20c0768 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -10,11 +10,12 @@ add_executable(tests
10 core/network/network.cpp 10 core/network/network.cpp
11 tests.cpp 11 tests.cpp
12 video_core/buffer_base.cpp 12 video_core/buffer_base.cpp
13 input_common/calibration_configuration_job.cpp
13) 14)
14 15
15create_target_directory_groups(tests) 16create_target_directory_groups(tests)
16 17
17target_link_libraries(tests PRIVATE common core) 18target_link_libraries(tests PRIVATE common core input_common)
18target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads) 19target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads)
19 20
20add_test(NAME tests COMMAND tests) 21add_test(NAME tests COMMAND tests)
diff --git a/src/tests/input_common/calibration_configuration_job.cpp b/src/tests/input_common/calibration_configuration_job.cpp
new file mode 100644
index 000000000..8c77d81e9
--- /dev/null
+++ b/src/tests/input_common/calibration_configuration_job.cpp
@@ -0,0 +1,136 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <string>
7#include <thread>
8#include <boost/asio.hpp>
9#include <boost/crc.hpp>
10#include <catch2/catch.hpp>
11
12#include "input_common/drivers/udp_client.h"
13#include "input_common/helpers/udp_protocol.h"
14
15class FakeCemuhookServer {
16public:
17 FakeCemuhookServer()
18 : socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
19
20 ~FakeCemuhookServer() {
21 is_running = false;
22 boost::system::error_code error_code;
23 socket.shutdown(boost::asio::socket_base::shutdown_both, error_code);
24 socket.close();
25 if (handler.joinable()) {
26 handler.join();
27 }
28 }
29
30 u16 GetPort() {
31 return socket.local_endpoint().port();
32 }
33
34 std::string GetHost() {
35 return socket.local_endpoint().address().to_string();
36 }
37
38 void Run(const std::vector<InputCommon::CemuhookUDP::Response::TouchPad> touch_movement_path) {
39 constexpr size_t HeaderSize = sizeof(InputCommon::CemuhookUDP::Header);
40 constexpr size_t PadDataSize =
41 sizeof(InputCommon::CemuhookUDP::Message<InputCommon::CemuhookUDP::Response::PadData>);
42
43 REQUIRE(touch_movement_path.size() > 0);
44 is_running = true;
45 handler = std::thread([touch_movement_path, this]() {
46 auto current_touch_position = touch_movement_path.begin();
47 while (is_running) {
48 boost::asio::ip::udp::endpoint sender_endpoint;
49 boost::system::error_code error_code;
50 auto received_size = socket.receive_from(boost::asio::buffer(receive_buffer),
51 sender_endpoint, 0, error_code);
52
53 if (received_size < HeaderSize) {
54 continue;
55 }
56
57 InputCommon::CemuhookUDP::Header header{};
58 std::memcpy(&header, receive_buffer.data(), HeaderSize);
59 switch (header.type) {
60 case InputCommon::CemuhookUDP::Type::PadData: {
61 InputCommon::CemuhookUDP::Response::PadData pad_data{};
62 pad_data.touch[0] = *current_touch_position;
63 const auto pad_message = InputCommon::CemuhookUDP::CreateMessage(
64 InputCommon::CemuhookUDP::SERVER_MAGIC, pad_data, 0);
65 std::memcpy(send_buffer.data(), &pad_message, PadDataSize);
66 socket.send_to(boost::asio::buffer(send_buffer, PadDataSize), sender_endpoint,
67 0, error_code);
68
69 bool can_advance =
70 std::next(current_touch_position) != touch_movement_path.end();
71 if (can_advance) {
72 std::advance(current_touch_position, 1);
73 }
74 break;
75 }
76 case InputCommon::CemuhookUDP::Type::PortInfo:
77 case InputCommon::CemuhookUDP::Type::Version:
78 default:
79 break;
80 }
81 }
82 });
83 }
84
85private:
86 boost::asio::io_service io_service;
87 boost::asio::ip::udp::socket socket;
88 std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer;
89 std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer;
90 bool is_running = false;
91 std::thread handler;
92};
93
94TEST_CASE("CalibrationConfigurationJob completed", "[input_common]") {
95 Common::Event complete_event;
96 FakeCemuhookServer server;
97 server.Run({{
98 .is_active = 1,
99 .x = 0,
100 .y = 0,
101 },
102 {
103 .is_active = 1,
104 .x = 200,
105 .y = 200,
106 }});
107
108 InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status{};
109 u16 min_x{};
110 u16 min_y{};
111 u16 max_x{};
112 u16 max_y{};
113 InputCommon::CemuhookUDP::CalibrationConfigurationJob job(
114 server.GetHost(), server.GetPort(),
115 [&status,
116 &complete_event](InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status_) {
117 status = status_;
118 if (status ==
119 InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed) {
120 complete_event.Set();
121 }
122 },
123 [&](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) {
124 min_x = min_x_;
125 min_y = min_y_;
126 max_x = max_x_;
127 max_y = max_y_;
128 });
129
130 complete_event.WaitUntil(std::chrono::system_clock::now() + std::chrono::seconds(10));
131 REQUIRE(status == InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed);
132 REQUIRE(min_x == 0);
133 REQUIRE(min_y == 0);
134 REQUIRE(max_x == 200);
135 REQUIRE(max_y == 200);
136}
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp
index 2a532b883..04d0f3a2f 100644
--- a/src/video_core/command_classes/codecs/codec.cpp
+++ b/src/video_core/command_classes/codecs/codec.cpp
@@ -32,7 +32,7 @@ constexpr std::array PREFERRED_GPU_DECODERS = {
32#ifdef _WIN32 32#ifdef _WIN32
33 AV_HWDEVICE_TYPE_D3D11VA, 33 AV_HWDEVICE_TYPE_D3D11VA,
34 AV_HWDEVICE_TYPE_DXVA2, 34 AV_HWDEVICE_TYPE_DXVA2,
35#elif defined(__linux__) 35#elif defined(__unix__)
36 AV_HWDEVICE_TYPE_VAAPI, 36 AV_HWDEVICE_TYPE_VAAPI,
37 AV_HWDEVICE_TYPE_VDPAU, 37 AV_HWDEVICE_TYPE_VDPAU,
38#endif 38#endif
@@ -130,6 +130,12 @@ bool Codec::CreateGpuAvDevice() {
130 } 130 }
131 if (config->methods & HW_CONFIG_METHOD && config->device_type == type) { 131 if (config->methods & HW_CONFIG_METHOD && config->device_type == type) {
132 av_codec_ctx->pix_fmt = config->pix_fmt; 132 av_codec_ctx->pix_fmt = config->pix_fmt;
133 if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
134 // skip zero-copy decoders, we don't currently support them
135 LOG_DEBUG(Service_NVDRV, "Skipping decoder {} with unsupported capability {}.",
136 av_hwdevice_get_type_name(type), config->methods);
137 continue;
138 }
133 LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type)); 139 LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type));
134 return true; 140 return true;
135 } 141 }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 37d5e6a6b..dbf1df79c 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -92,7 +92,7 @@ public:
92 92
93 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 93 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
94 94
95 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { 95 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
96 UNIMPLEMENTED(); 96 UNIMPLEMENTED();
97 } 97 }
98 98
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 28daacd82..f81c1b233 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -437,39 +437,29 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
437 437
438 glBindTextureUnit(0, fxaa_texture.handle); 438 glBindTextureUnit(0, fxaa_texture.handle);
439 } 439 }
440
441 // Set projection matrix
442 const std::array ortho_matrix = 440 const std::array ortho_matrix =
443 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); 441 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
444 442
445 GLuint fragment_handle; 443 const auto fragment_handle = [this]() {
446 const auto filter = Settings::values.scaling_filter.GetValue(); 444 switch (Settings::values.scaling_filter.GetValue()) {
447 switch (filter) { 445 case Settings::ScalingFilter::NearestNeighbor:
448 case Settings::ScalingFilter::NearestNeighbor: 446 case Settings::ScalingFilter::Bilinear:
449 fragment_handle = present_bilinear_fragment.handle; 447 return present_bilinear_fragment.handle;
450 break; 448 case Settings::ScalingFilter::Bicubic:
451 case Settings::ScalingFilter::Bilinear: 449 return present_bicubic_fragment.handle;
452 fragment_handle = present_bilinear_fragment.handle; 450 case Settings::ScalingFilter::Gaussian:
453 break; 451 return present_gaussian_fragment.handle;
454 case Settings::ScalingFilter::Bicubic: 452 case Settings::ScalingFilter::ScaleForce:
455 fragment_handle = present_bicubic_fragment.handle; 453 return present_scaleforce_fragment.handle;
456 break; 454 case Settings::ScalingFilter::Fsr:
457 case Settings::ScalingFilter::Gaussian: 455 LOG_WARNING(
458 fragment_handle = present_gaussian_fragment.handle; 456 Render_OpenGL,
459 break; 457 "FidelityFX Super Resolution is not supported in OpenGL, changing to ScaleForce");
460 case Settings::ScalingFilter::ScaleForce: 458 return present_scaleforce_fragment.handle;
461 fragment_handle = present_scaleforce_fragment.handle; 459 default:
462 break; 460 return present_bilinear_fragment.handle;
463 case Settings::ScalingFilter::Fsr: 461 }
464 LOG_WARNING( 462 }();
465 Render_OpenGL,
466 "FidelityFX FSR Super Sampling is not supported in OpenGL, changing to ScaleForce");
467 fragment_handle = present_scaleforce_fragment.handle;
468 break;
469 default:
470 fragment_handle = present_bilinear_fragment.handle;
471 break;
472 }
473 program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); 463 program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
474 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, 464 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
475 ortho_matrix.data()); 465 ortho_matrix.data());
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index 9a38b6b34..cd5995897 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -4,6 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6 6
7#include "common/settings.h"
7#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" 8#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
8#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" 9#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
9#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" 10#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
@@ -335,6 +336,17 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
335 cmdbuf.SetScissor(0, scissor); 336 cmdbuf.SetScissor(0, scissor);
336 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); 337 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
337} 338}
339
340VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
341 const auto& resolution = Settings::values.resolution_info;
342 const bool is_rescaled = src_image_view.IsRescaled();
343 u32 width = src_image_view.size.width;
344 u32 height = src_image_view.size.height;
345 return VkExtent2D{
346 .width = is_rescaled ? resolution.ScaleUp(width) : width,
347 .height = is_rescaled ? resolution.ScaleUp(height) : height,
348 };
349}
338} // Anonymous namespace 350} // Anonymous namespace
339 351
340BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, 352BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
@@ -425,61 +437,52 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
425} 437}
426 438
427void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, 439void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
428 const ImageView& src_image_view, u32 up_scale, 440 const ImageView& src_image_view) {
429 u32 down_shift) {
430 ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); 441 ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass());
431 Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 442 Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view);
432} 443}
433 444
434void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, 445void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer,
435 const ImageView& src_image_view, u32 up_scale, 446 const ImageView& src_image_view) {
436 u32 down_shift) {
437 ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); 447 ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass());
438 Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 448 Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
439} 449}
440 450
441void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, 451void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer,
442 const ImageView& src_image_view, u32 up_scale, 452 const ImageView& src_image_view) {
443 u32 down_shift) {
444 ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); 453 ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass());
445 Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 454 Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view);
446} 455}
447 456
448void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, 457void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
449 const ImageView& src_image_view, u32 up_scale, 458 const ImageView& src_image_view) {
450 u32 down_shift) {
451 ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); 459 ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass());
452 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 460 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
453} 461}
454 462
455void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, 463void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
456 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 464 const ImageView& src_image_view) {
457 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), 465 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
458 convert_abgr8_to_d24s8_frag, true); 466 convert_abgr8_to_d24s8_frag);
459 ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, 467 Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view);
460 down_shift);
461} 468}
462 469
463void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, 470void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
464 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 471 ImageView& src_image_view) {
465 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), 472 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
466 convert_d24s8_to_abgr8_frag, false); 473 convert_d24s8_to_abgr8_frag);
467 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale, 474 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
468 down_shift);
469} 475}
470 476
471void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 477void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
472 const ImageView& src_image_view, u32 up_scale, u32 down_shift) { 478 const ImageView& src_image_view) {
473 const VkPipelineLayout layout = *one_texture_pipeline_layout; 479 const VkPipelineLayout layout = *one_texture_pipeline_layout;
474 const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); 480 const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
475 const VkSampler sampler = *nearest_sampler; 481 const VkSampler sampler = *nearest_sampler;
476 const VkExtent2D extent{ 482 const VkExtent2D extent = GetConversionExtent(src_image_view);
477 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), 483
478 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
479 };
480 scheduler.RequestRenderpass(dst_framebuffer); 484 scheduler.RequestRenderpass(dst_framebuffer);
481 scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift, 485 scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) {
482 this](vk::CommandBuffer cmdbuf) {
483 const VkOffset2D offset{ 486 const VkOffset2D offset{
484 .x = 0, 487 .x = 0,
485 .y = 0, 488 .y = 0,
@@ -563,18 +566,16 @@ void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_f
563} 566}
564 567
565void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 568void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
566 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 569 ImageView& src_image_view) {
567 const VkPipelineLayout layout = *two_textures_pipeline_layout; 570 const VkPipelineLayout layout = *two_textures_pipeline_layout;
568 const VkImageView src_depth_view = src_image_view.DepthView(); 571 const VkImageView src_depth_view = src_image_view.DepthView();
569 const VkImageView src_stencil_view = src_image_view.StencilView(); 572 const VkImageView src_stencil_view = src_image_view.StencilView();
570 const VkSampler sampler = *nearest_sampler; 573 const VkSampler sampler = *nearest_sampler;
571 const VkExtent2D extent{ 574 const VkExtent2D extent = GetConversionExtent(src_image_view);
572 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), 575
573 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
574 };
575 scheduler.RequestRenderpass(dst_framebuffer); 576 scheduler.RequestRenderpass(dst_framebuffer);
576 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale, 577 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent,
577 down_shift, this](vk::CommandBuffer cmdbuf) { 578 this](vk::CommandBuffer cmdbuf) {
578 const VkOffset2D offset{ 579 const VkOffset2D offset{
579 .x = 0, 580 .x = 0,
580 .y = 0, 581 .y = 0,
@@ -695,11 +696,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
695 return *blit_depth_stencil_pipelines.back(); 696 return *blit_depth_stencil_pipelines.back();
696} 697}
697 698
698void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { 699void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass,
700 bool is_target_depth) {
699 if (pipeline) { 701 if (pipeline) {
700 return; 702 return;
701 } 703 }
702 const std::array stages = MakeStages(*full_screen_vert, *convert_depth_to_float_frag); 704 VkShaderModule frag_shader =
705 is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
706 const std::array stages = MakeStages(*full_screen_vert, frag_shader);
703 pipeline = device.GetLogical().CreateGraphicsPipeline({ 707 pipeline = device.GetLogical().CreateGraphicsPipeline({
704 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 708 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
705 .pNext = nullptr, 709 .pNext = nullptr,
@@ -712,8 +716,9 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
712 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, 716 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
713 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 717 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
714 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 718 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
715 .pDepthStencilState = nullptr, 719 .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
716 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, 720 .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO
721 : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
717 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, 722 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
718 .layout = *one_texture_pipeline_layout, 723 .layout = *one_texture_pipeline_layout,
719 .renderPass = renderpass, 724 .renderPass = renderpass,
@@ -723,37 +728,17 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
723 }); 728 });
724} 729}
725 730
731void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
732 ConvertPipeline(pipeline, renderpass, false);
733}
734
726void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { 735void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
727 if (pipeline) { 736 ConvertPipeline(pipeline, renderpass, true);
728 return;
729 }
730 const std::array stages = MakeStages(*full_screen_vert, *convert_float_to_depth_frag);
731 pipeline = device.GetLogical().CreateGraphicsPipeline({
732 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
733 .pNext = nullptr,
734 .flags = 0,
735 .stageCount = static_cast<u32>(stages.size()),
736 .pStages = stages.data(),
737 .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
738 .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
739 .pTessellationState = nullptr,
740 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
741 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
742 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
743 .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
744 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
745 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
746 .layout = *one_texture_pipeline_layout,
747 .renderPass = renderpass,
748 .subpass = 0,
749 .basePipelineHandle = VK_NULL_HANDLE,
750 .basePipelineIndex = 0,
751 });
752} 737}
753 738
754void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 739void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
755 vk::ShaderModule& module, bool is_target_depth, 740 vk::ShaderModule& module, bool single_texture,
756 bool single_texture) { 741 bool is_target_depth) {
757 if (pipeline) { 742 if (pipeline) {
758 return; 743 return;
759 } 744 }
@@ -782,13 +767,13 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
782} 767}
783 768
784void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 769void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
785 vk::ShaderModule& module, bool single_texture) { 770 vk::ShaderModule& module) {
786 ConvertPipelineEx(pipeline, renderpass, module, false, single_texture); 771 ConvertPipelineEx(pipeline, renderpass, module, false, false);
787} 772}
788 773
789void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 774void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
790 vk::ShaderModule& module, bool single_texture) { 775 vk::ShaderModule& module) {
791 ConvertPipelineEx(pipeline, renderpass, module, true, single_texture); 776 ConvertPipelineEx(pipeline, renderpass, module, true, true);
792} 777}
793 778
794} // namespace Vulkan 779} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index b1a717090..1d9f61a52 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -44,50 +44,46 @@ public:
44 const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, 44 const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter,
45 Tegra::Engines::Fermi2D::Operation operation); 45 Tegra::Engines::Fermi2D::Operation operation);
46 46
47 void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 47 void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
48 u32 up_scale, u32 down_shift);
49 48
50 void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 49 void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
51 u32 up_scale, u32 down_shift);
52 50
53 void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 51 void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
54 u32 up_scale, u32 down_shift);
55 52
56 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 53 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
57 u32 up_scale, u32 down_shift);
58 54
59 void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, 55 void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
60 u32 up_scale, u32 down_shift);
61 56
62 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, 57 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
63 u32 up_scale, u32 down_shift);
64 58
65private: 59private:
66 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 60 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
67 const ImageView& src_image_view, u32 up_scale, u32 down_shift); 61 const ImageView& src_image_view);
68 62
69 void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 63 void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
70 ImageView& src_image_view, u32 up_scale, u32 down_shift); 64 ImageView& src_image_view, u32 up_scale, u32 down_shift);
71 65
72 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 66 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
73 ImageView& src_image_view, u32 up_scale, u32 down_shift); 67 ImageView& src_image_view);
74 68
75 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); 69 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
76 70
77 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); 71 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
78 72
73 void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth);
74
79 void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 75 void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
80 76
81 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 77 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
82 78
83 void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 79 void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
84 vk::ShaderModule& module, bool is_target_depth, bool single_texture); 80 vk::ShaderModule& module, bool single_texture, bool is_target_depth);
85 81
86 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 82 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
87 vk::ShaderModule& module, bool single_texture); 83 vk::ShaderModule& module);
88 84
89 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 85 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
90 vk::ShaderModule& module, bool single_texture); 86 vk::ShaderModule& module);
91 87
92 const Device& device; 88 const Device& device;
93 VKScheduler& scheduler; 89 VKScheduler& scheduler;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 1e447e621..c71a1f44d 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -391,28 +391,23 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
391 .offset = {0, 0}, 391 .offset = {0, 0},
392 .extent = size, 392 .extent = size,
393 }; 393 };
394 const auto filter = Settings::values.scaling_filter.GetValue();
395 cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); 394 cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
396 switch (filter) { 395 auto graphics_pipeline = [this]() {
397 case Settings::ScalingFilter::NearestNeighbor: 396 switch (Settings::values.scaling_filter.GetValue()) {
398 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); 397 case Settings::ScalingFilter::NearestNeighbor:
399 break; 398 case Settings::ScalingFilter::Bilinear:
400 case Settings::ScalingFilter::Bilinear: 399 return *bilinear_pipeline;
401 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); 400 case Settings::ScalingFilter::Bicubic:
402 break; 401 return *bicubic_pipeline;
403 case Settings::ScalingFilter::Bicubic: 402 case Settings::ScalingFilter::Gaussian:
404 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline); 403 return *gaussian_pipeline;
405 break; 404 case Settings::ScalingFilter::ScaleForce:
406 case Settings::ScalingFilter::Gaussian: 405 return *scaleforce_pipeline;
407 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline); 406 default:
408 break; 407 return *bilinear_pipeline;
409 case Settings::ScalingFilter::ScaleForce: 408 }
410 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline); 409 }();
411 break; 410 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline);
412 default:
413 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
414 break;
415 }
416 cmdbuf.SetViewport(0, viewport); 411 cmdbuf.SetViewport(0, viewport);
417 cmdbuf.SetScissor(0, scissor); 412 cmdbuf.SetScissor(0, scissor);
418 413
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 616a7b457..d514b71d0 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -605,7 +605,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
605 .flags = 0, 605 .flags = 0,
606 .topology = input_assembly_topology, 606 .topology = input_assembly_topology,
607 .primitiveRestartEnable = key.state.primitive_restart_enable != 0 && 607 .primitiveRestartEnable = key.state.primitive_restart_enable != 0 &&
608 SupportsPrimitiveRestart(input_assembly_topology), 608 ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
609 device.IsTopologyListPrimitiveRestartSupported()) ||
610 SupportsPrimitiveRestart(input_assembly_topology) ||
611 (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
612 device.IsPatchListPrimitiveRestartSupported())),
609 }; 613 };
610 const VkPipelineTessellationStateCreateInfo tessellation_ci{ 614 const VkPipelineTessellationStateCreateInfo tessellation_ci{
611 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 615 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
@@ -613,7 +617,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
613 .flags = 0, 617 .flags = 0,
614 .patchControlPoints = key.state.patch_control_points_minus_one.Value() + 1, 618 .patchControlPoints = key.state.patch_control_points_minus_one.Value() + 1,
615 }; 619 };
616
617 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles; 620 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
618 std::ranges::transform(key.state.viewport_swizzles, swizzles.begin(), UnpackViewportSwizzle); 621 std::ranges::transform(key.state.viewport_swizzles, swizzles.begin(), UnpackViewportSwizzle);
619 const VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{ 622 const VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
@@ -748,8 +751,8 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
748 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 751 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
749 .pNext = nullptr, 752 .pNext = nullptr,
750 .flags = 0, 753 .flags = 0,
751 .logicOpEnable = VK_FALSE, 754 .logicOpEnable = key.state.logic_op_enable != 0,
752 .logicOp = VK_LOGIC_OP_COPY, 755 .logicOp = static_cast<VkLogicOp>(key.state.logic_op.Value()),
753 .attachmentCount = static_cast<u32>(cb_attachments.size()), 756 .attachmentCount = static_cast<u32>(cb_attachments.size()),
754 .pAttachments = cb_attachments.data(), 757 .pAttachments = cb_attachments.data(),
755 .blendConstants = {}, 758 .blendConstants = {},
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 197cba8e3..1941170cb 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1057,37 +1057,37 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
1057 }); 1057 });
1058} 1058}
1059 1059
1060void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, 1060void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
1061 bool rescaled) {
1062 const u32 up_scale = rescaled ? resolution.up_scale : 1;
1063 const u32 down_shift = rescaled ? resolution.down_shift : 0;
1064 switch (dst_view.format) { 1061 switch (dst_view.format) {
1065 case PixelFormat::R16_UNORM: 1062 case PixelFormat::R16_UNORM:
1066 if (src_view.format == PixelFormat::D16_UNORM) { 1063 if (src_view.format == PixelFormat::D16_UNORM) {
1067 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); 1064 return blit_image_helper.ConvertD16ToR16(dst, src_view);
1068 } 1065 }
1069 break; 1066 break;
1070 case PixelFormat::A8B8G8R8_UNORM: 1067 case PixelFormat::A8B8G8R8_UNORM:
1071 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { 1068 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1072 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift); 1069 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view);
1073 } 1070 }
1074 break; 1071 break;
1075 case PixelFormat::R32_FLOAT: 1072 case PixelFormat::R32_FLOAT:
1076 if (src_view.format == PixelFormat::D32_FLOAT) { 1073 if (src_view.format == PixelFormat::D32_FLOAT) {
1077 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); 1074 return blit_image_helper.ConvertD32ToR32(dst, src_view);
1078 } 1075 }
1079 break; 1076 break;
1080 case PixelFormat::D16_UNORM: 1077 case PixelFormat::D16_UNORM:
1081 if (src_view.format == PixelFormat::R16_UNORM) { 1078 if (src_view.format == PixelFormat::R16_UNORM) {
1082 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); 1079 return blit_image_helper.ConvertR16ToD16(dst, src_view);
1083 } 1080 }
1084 break; 1081 break;
1085 case PixelFormat::S8_UINT_D24_UNORM: 1082 case PixelFormat::S8_UINT_D24_UNORM:
1086 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift); 1083 if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||
1084 src_view.format == PixelFormat::B8G8R8A8_UNORM) {
1085 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view);
1086 }
1087 break; 1087 break;
1088 case PixelFormat::D32_FLOAT: 1088 case PixelFormat::D32_FLOAT:
1089 if (src_view.format == PixelFormat::R32_FLOAT) { 1089 if (src_view.format == PixelFormat::R32_FLOAT) {
1090 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); 1090 return blit_image_helper.ConvertR32ToD32(dst, src_view);
1091 } 1091 }
1092 break; 1092 break;
1093 default: 1093 default:
@@ -1329,6 +1329,10 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm
1329 } 1329 }
1330} 1330}
1331 1331
1332bool Image::IsRescaled() const noexcept {
1333 return True(flags & ImageFlagBits::Rescaled);
1334}
1335
1332bool Image::ScaleUp(bool ignore) { 1336bool Image::ScaleUp(bool ignore) {
1333 if (True(flags & ImageFlagBits::Rescaled)) { 1337 if (True(flags & ImageFlagBits::Rescaled)) {
1334 return false; 1338 return false;
@@ -1469,7 +1473,8 @@ bool Image::BlitScaleHelper(bool scale_up) {
1469ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, 1473ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
1470 ImageId image_id_, Image& image) 1474 ImageId image_id_, Image& image)
1471 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, 1475 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
1472 image_handle{image.Handle()}, samples{ConvertSampleCount(image.info.num_samples)} { 1476 src_image{&image}, image_handle{image.Handle()},
1477 samples(ConvertSampleCount(image.info.num_samples)) {
1473 using Shader::TextureType; 1478 using Shader::TextureType;
1474 1479
1475 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); 1480 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1607,6 +1612,13 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
1607 return *view; 1612 return *view;
1608} 1613}
1609 1614
1615bool ImageView::IsRescaled() const noexcept {
1616 if (!src_image) {
1617 return false;
1618 }
1619 return src_image->IsRescaled();
1620}
1621
1610vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { 1622vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {
1611 return device->GetLogical().CreateImageView({ 1623 return device->GetLogical().CreateImageView({
1612 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 1624 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 753e3e8a1..c592f2666 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -65,7 +65,7 @@ public:
65 65
66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
67 67
68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); 68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
69 69
70 bool CanAccelerateImageUpload(Image&) const noexcept { 70 bool CanAccelerateImageUpload(Image&) const noexcept {
71 return false; 71 return false;
@@ -139,6 +139,8 @@ public:
139 return std::exchange(initialized, true); 139 return std::exchange(initialized, true);
140 } 140 }
141 141
142 bool IsRescaled() const noexcept;
143
142 bool ScaleUp(bool ignore = false); 144 bool ScaleUp(bool ignore = false);
143 145
144 bool ScaleDown(bool ignore = false); 146 bool ScaleDown(bool ignore = false);
@@ -189,6 +191,8 @@ public:
189 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, 191 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
190 Shader::ImageFormat image_format); 192 Shader::ImageFormat image_format);
191 193
194 [[nodiscard]] bool IsRescaled() const noexcept;
195
192 [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { 196 [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept {
193 return *image_views[static_cast<size_t>(texture_type)]; 197 return *image_views[static_cast<size_t>(texture_type)];
194 } 198 }
@@ -222,6 +226,8 @@ private:
222 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); 226 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
223 227
224 const Device* device = nullptr; 228 const Device* device = nullptr;
229 const Image* src_image{};
230
225 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; 231 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
226 std::unique_ptr<StorageViews> storage_views; 232 std::unique_ptr<StorageViews> storage_views;
227 vk::ImageView depth_view; 233 vk::ImageView depth_view;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 5aaeb16ca..2e19fced2 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1855,9 +1855,20 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1855 .height = std::min(dst_view.size.height, src_view.size.height), 1855 .height = std::min(dst_view.size.height, src_view.size.height),
1856 .depth = std::min(dst_view.size.depth, src_view.size.depth), 1856 .depth = std::min(dst_view.size.depth, src_view.size.depth),
1857 }; 1857 };
1858 UNIMPLEMENTED_IF(copy.extent != expected_size); 1858 const Extent3D scaled_extent = [is_rescaled, expected_size]() {
1859 if (!is_rescaled) {
1860 return expected_size;
1861 }
1862 const auto& resolution = Settings::values.resolution_info;
1863 return Extent3D{
1864 .width = resolution.ScaleUp(expected_size.width),
1865 .height = resolution.ScaleUp(expected_size.height),
1866 .depth = expected_size.depth,
1867 };
1868 }();
1869 UNIMPLEMENTED_IF(copy.extent != scaled_extent);
1859 1870
1860 runtime.ConvertImage(dst_framebuffer, dst_view, src_view, is_rescaled); 1871 runtime.ConvertImage(dst_framebuffer, dst_view, src_view);
1861 } 1872 }
1862} 1873}
1863 1874
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 7bf5b6578..9862b815b 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -271,7 +271,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
271 .tessellationShader = true, 271 .tessellationShader = true,
272 .sampleRateShading = true, 272 .sampleRateShading = true,
273 .dualSrcBlend = true, 273 .dualSrcBlend = true,
274 .logicOp = false, 274 .logicOp = true,
275 .multiDrawIndirect = false, 275 .multiDrawIndirect = false,
276 .drawIndirectFirstInstance = false, 276 .drawIndirectFirstInstance = false,
277 .depthClamp = true, 277 .depthClamp = true,
@@ -433,6 +433,19 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
433 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes"); 433 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
434 } 434 }
435 435
436 VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT primitive_topology_list_restart;
437 if (is_topology_list_restart_supported || is_patch_list_restart_supported) {
438 primitive_topology_list_restart = {
439 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT,
440 .pNext = nullptr,
441 .primitiveTopologyListRestart = is_topology_list_restart_supported,
442 .primitiveTopologyPatchListRestart = is_patch_list_restart_supported,
443 };
444 SetNext(next, primitive_topology_list_restart);
445 } else {
446 LOG_INFO(Render_Vulkan, "Device doesn't support list topology primitive restart");
447 }
448
436 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback; 449 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback;
437 if (ext_transform_feedback) { 450 if (ext_transform_feedback) {
438 transform_feedback = { 451 transform_feedback = {
@@ -891,6 +904,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
891 bool has_ext_provoking_vertex{}; 904 bool has_ext_provoking_vertex{};
892 bool has_ext_vertex_input_dynamic_state{}; 905 bool has_ext_vertex_input_dynamic_state{};
893 bool has_ext_line_rasterization{}; 906 bool has_ext_line_rasterization{};
907 bool has_ext_primitive_topology_list_restart{};
894 for (const std::string& extension : supported_extensions) { 908 for (const std::string& extension : supported_extensions) {
895 const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name, 909 const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name,
896 bool push) { 910 bool push) {
@@ -915,6 +929,8 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
915 test(has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false); 929 test(has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
916 test(ext_depth_range_unrestricted, VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true); 930 test(ext_depth_range_unrestricted, VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true);
917 test(ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true); 931 test(ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
932 test(has_ext_primitive_topology_list_restart,
933 VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME, true);
918 test(ext_sampler_filter_minmax, VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, true); 934 test(ext_sampler_filter_minmax, VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, true);
919 test(ext_shader_viewport_index_layer, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, 935 test(ext_shader_viewport_index_layer, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME,
920 true); 936 true);
@@ -1113,6 +1129,19 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
1113 khr_pipeline_executable_properties = true; 1129 khr_pipeline_executable_properties = true;
1114 } 1130 }
1115 } 1131 }
1132 if (has_ext_primitive_topology_list_restart) {
1133 VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT primitive_topology_list_restart{};
1134 primitive_topology_list_restart.sType =
1135 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT;
1136 primitive_topology_list_restart.pNext = nullptr;
1137 features.pNext = &primitive_topology_list_restart;
1138 physical.GetFeatures2KHR(features);
1139
1140 is_topology_list_restart_supported =
1141 primitive_topology_list_restart.primitiveTopologyListRestart;
1142 is_patch_list_restart_supported =
1143 primitive_topology_list_restart.primitiveTopologyPatchListRestart;
1144 }
1116 if (has_khr_image_format_list && has_khr_swapchain_mutable_format) { 1145 if (has_khr_image_format_list && has_khr_swapchain_mutable_format) {
1117 extensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME); 1146 extensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
1118 extensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME); 1147 extensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME);
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 10653ac6b..4c9d86aad 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -238,6 +238,16 @@ public:
238 return khr_workgroup_memory_explicit_layout; 238 return khr_workgroup_memory_explicit_layout;
239 } 239 }
240 240
241 /// Returns true if the device supports VK_EXT_primitive_topology_list_restart.
242 bool IsTopologyListPrimitiveRestartSupported() const {
243 return is_topology_list_restart_supported;
244 }
245
246 /// Returns true if the device supports VK_EXT_primitive_topology_list_restart.
247 bool IsPatchListPrimitiveRestartSupported() const {
248 return is_patch_list_restart_supported;
249 }
250
241 /// Returns true if the device supports VK_EXT_index_type_uint8. 251 /// Returns true if the device supports VK_EXT_index_type_uint8.
242 bool IsExtIndexTypeUint8Supported() const { 252 bool IsExtIndexTypeUint8Supported() const {
243 return ext_index_type_uint8; 253 return ext_index_type_uint8;
@@ -401,6 +411,9 @@ private:
401 bool is_shader_int16_supported{}; ///< Support for int16. 411 bool is_shader_int16_supported{}; ///< Support for int16.
402 bool is_shader_storage_image_multisample{}; ///< Support for image operations on MSAA images. 412 bool is_shader_storage_image_multisample{}; ///< Support for image operations on MSAA images.
403 bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil. 413 bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
414 bool is_topology_list_restart_supported{}; ///< Support for primitive restart with list
415 ///< topologies.
416 bool is_patch_list_restart_supported{}; ///< Support for primitive restart with list patch.
404 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. 417 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
405 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. 418 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2.
406 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough. 419 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough.
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index c5685db2e..c6222b571 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -12,7 +12,6 @@
12#include "core/hid/emulated_controller.h" 12#include "core/hid/emulated_controller.h"
13#include "core/hid/hid_core.h" 13#include "core/hid/hid_core.h"
14#include "core/hid/hid_types.h" 14#include "core/hid/hid_types.h"
15#include "core/hle/lock.h"
16#include "core/hle/service/hid/controllers/npad.h" 15#include "core/hle/service/hid/controllers/npad.h"
17#include "core/hle/service/hid/hid.h" 16#include "core/hle/service/hid/hid.h"
18#include "core/hle/service/sm/sm.h" 17#include "core/hle/service/sm/sm.h"
@@ -664,7 +663,5 @@ void QtControllerSelector::ReconfigureControllers(
664} 663}
665 664
666void QtControllerSelector::MainWindowReconfigureFinished() { 665void QtControllerSelector::MainWindowReconfigureFinished() {
667 // Acquire the HLE mutex
668 std::lock_guard lock(HLE::g_hle_lock);
669 callback(); 666 callback();
670} 667}
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp
index 45cf64603..879e73660 100644
--- a/src/yuzu/applets/qt_error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QDateTime> 5#include <QDateTime>
6#include "core/hle/lock.h"
7#include "yuzu/applets/qt_error.h" 6#include "yuzu/applets/qt_error.h"
8#include "yuzu/main.h" 7#include "yuzu/main.h"
9 8
@@ -57,7 +56,5 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
57} 56}
58 57
59void QtErrorDisplay::MainWindowFinishedError() { 58void QtErrorDisplay::MainWindowFinishedError() {
60 // Acquire the HLE mutex
61 std::lock_guard lock{HLE::g_hle_lock};
62 callback(); 59 callback();
63} 60}
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 7b19f1f8d..5b32da923 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -14,7 +14,6 @@
14#include "common/fs/path_util.h" 14#include "common/fs/path_util.h"
15#include "common/string_util.h" 15#include "common/string_util.h"
16#include "core/constants.h" 16#include "core/constants.h"
17#include "core/hle/lock.h"
18#include "yuzu/applets/qt_profile_select.h" 17#include "yuzu/applets/qt_profile_select.h"
19#include "yuzu/main.h" 18#include "yuzu/main.h"
20#include "yuzu/util/controller_navigation.h" 19#include "yuzu/util/controller_navigation.h"
@@ -170,7 +169,5 @@ void QtProfileSelector::SelectProfile(
170} 169}
171 170
172void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) { 171void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
173 // Acquire the HLE mutex
174 std::lock_guard lock{HLE::g_hle_lock};
175 callback(uuid); 172 callback(uuid);
176} 173}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b7bb43348..a7271e075 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2546,39 +2546,30 @@ void GMainWindow::ToggleFullscreen() {
2546} 2546}
2547 2547
2548void GMainWindow::ShowFullscreen() { 2548void GMainWindow::ShowFullscreen() {
2549 const auto show_fullscreen = [](QWidget* window) {
2550 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
2551 window->showFullScreen();
2552 return;
2553 }
2554 window->hide();
2555 window->setWindowFlags(window->windowFlags() | Qt::FramelessWindowHint);
2556 const auto screen_geometry = QApplication::desktop()->screenGeometry(window);
2557 window->setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2558 screen_geometry.height() + 1);
2559 window->raise();
2560 window->showNormal();
2561 };
2562
2549 if (ui->action_Single_Window_Mode->isChecked()) { 2563 if (ui->action_Single_Window_Mode->isChecked()) {
2550 UISettings::values.geometry = saveGeometry(); 2564 UISettings::values.geometry = saveGeometry();
2551 2565
2552 ui->menubar->hide(); 2566 ui->menubar->hide();
2553 statusBar()->hide(); 2567 statusBar()->hide();
2554 2568
2555 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { 2569 show_fullscreen(this);
2556 showFullScreen();
2557 return;
2558 }
2559
2560 hide();
2561 setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2562 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2563 setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2564 screen_geometry.height() + 1);
2565 raise();
2566 showNormal();
2567 } else { 2570 } else {
2568 UISettings::values.renderwindow_geometry = render_window->saveGeometry(); 2571 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
2569 2572 show_fullscreen(render_window);
2570 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
2571 render_window->showFullScreen();
2572 return;
2573 }
2574
2575 render_window->hide();
2576 render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2577 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2578 render_window->setGeometry(screen_geometry.x(), screen_geometry.y(),
2579 screen_geometry.width(), screen_geometry.height() + 1);
2580 render_window->raise();
2581 render_window->showNormal();
2582 } 2573 }
2583} 2574}
2584 2575