early-access version 2321

main
pineappleEA 2021-12-18 02:10:41 +01:00
parent 669d9a246c
commit 994096ad3a
41 changed files with 598 additions and 424 deletions

View File

@ -514,7 +514,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
endif() endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG) if (NOT YUZU_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg # Use system installed FFmpeg
find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS}) find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
if (FFmpeg_FOUND) if (FFmpeg_FOUND)
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries. # Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
@ -527,225 +527,11 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE) set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE)
endforeach() endforeach()
else() else()
message(WARNING "FFmpeg not found, falling back to externals") message(WARNING "FFmpeg not found or too old, falling back to externals")
set(YUZU_USE_BUNDLED_FFMPEG ON) set(YUZU_USE_BUNDLED_FFMPEG ON)
endif() endif()
endif() endif()
if (YUZU_USE_BUNDLED_FFMPEG)
if (NOT WIN32)
# TODO(lat9nq): Move this to externals/ffmpeg/CMakeLists.txt (and move externals/ffmpeg to
# externals/ffmpeg/ffmpeg)
# Build FFmpeg from externals
message(STATUS "Using FFmpeg from externals")
# FFmpeg has source that requires one of nasm or yasm to assemble it.
# REQUIRED throws an error if not found here during configuration rather than during compilation.
find_program(ASSEMBLER NAMES nasm yasm)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg)
set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg)
set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
make_directory(${FFmpeg_BUILD_DIR})
# Read version string from external
file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
set(FFmpeg_FOUND NO)
if (NOT FFmpeg_VERSION STREQUAL "")
set(FFmpeg_FOUND YES)
endif()
unset(FFmpeg_LIBRARIES CACHE)
foreach(COMPONENT ${FFmpeg_COMPONENTS})
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARIES}
${FFmpeg_${COMPONENT}_LIBRARY}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND AND CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
--extra-cflags=-I${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${FFNVCODEC_LIBRARIES}
${CUDA_LIBRARIES}
)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${FFNVCODEC_INCLUDE_DIRS}
${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LDFLAGS
${FFNVCODEC_LDFLAGS}
${CUDA_LDFLAGS}
)
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
add_custom_command(
OUTPUT
${FFmpeg_MAKEFILE}
COMMAND
/bin/bash ${FFmpeg_PREFIX}/configure
--disable-avdevice
--disable-avfilter
--disable-avformat
--disable-doc
--disable-everything
--disable-ffmpeg
--disable-ffprobe
--disable-network
--disable-postproc
--disable-swresample
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
# with context of the jobserver. Also helps ninja users.
execute_process(
COMMAND
nproc
OUTPUT_VARIABLE
SYSTEM_THREADS)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# ALL makes this custom target build every time
# but it won't actually build if the DEPENDS parameter is up to date
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else() # WIN32
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
set(FFmpeg_FOUND YES)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARY_DIR}/swscale.lib
${FFmpeg_LIBRARY_DIR}/avcodec.lib
${FFmpeg_LIBRARY_DIR}/avutil.lib
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endif()
endif()
unset(FFmpeg_COMPONENTS)
# Prefer the -pthread flag on Linux. # Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)

View File

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

View File

@ -121,3 +121,12 @@ if (NOT opus_FOUND)
message(STATUS "opus 1.3 or newer not found, falling back to externals") message(STATUS "opus 1.3 or newer not found, falling back to externals")
add_subdirectory(opus EXCLUDE_FROM_ALL) add_subdirectory(opus EXCLUDE_FROM_ALL)
endif() endif()
# FFMpeg
if (YUZU_USE_BUNDLED_FFMPEG)
add_subdirectory(ffmpeg)
set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
endif()

214
externals/ffmpeg/CMakeLists.txt vendored Executable file
View File

@ -0,0 +1,214 @@
if (NOT WIN32)
# Build FFmpeg from externals
message(STATUS "Using FFmpeg from externals")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64)")
# FFmpeg has source that requires one of nasm or yasm to assemble it.
# REQUIRED throws an error if not found here during configuration rather than during compilation.
find_program(ASSEMBLER NAMES nasm yasm)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg/ffmpeg)
set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg-build)
set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
make_directory(${FFmpeg_BUILD_DIR})
# Read version string from external
file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
set(FFmpeg_FOUND NO)
if (NOT FFmpeg_VERSION STREQUAL "")
set(FFmpeg_FOUND YES)
endif()
unset(FFmpeg_LIBRARIES CACHE)
foreach(COMPONENT ${FFmpeg_COMPONENTS})
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARIES}
${FFmpeg_${COMPONENT}_LIBRARY}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS})
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
# ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress
# here we handle the hard-linking senario where CUDA is linked during compilation
if (CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
message(STATUS "CUDA libraries found, hard-linking will be performed")
endif(CUDA_FOUND)
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
add_custom_command(
OUTPUT
${FFmpeg_MAKEFILE}
COMMAND
/bin/bash ${FFmpeg_PREFIX}/configure
--disable-avdevice
--disable-avfilter
--disable-avformat
--disable-doc
--disable-everything
--disable-ffmpeg
--disable-ffprobe
--disable-network
--disable-postproc
--disable-swresample
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
# with context of the jobserver. Also helps ninja users.
execute_process(
COMMAND
nproc
OUTPUT_VARIABLE
SYSTEM_THREADS)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# ALL makes this custom target build every time
# but it won't actually build if the DEPENDS parameter is up to date
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else(WIN32)
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
set(FFmpeg_FOUND YES)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARY_DIR}/swscale.lib
${FFmpeg_LIBRARY_DIR}/avcodec.lib
${FFmpeg_LIBRARY_DIR}/avutil.lib
CACHE PATH "Paths to FFmpeg libraries" FORCE)
# exported variables
set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
endif(WIN32)
unset(FFmpeg_COMPONENTS)

View File

@ -265,8 +265,6 @@ add_library(core STATIC
hle/kernel/svc_wrap.h hle/kernel/svc_wrap.h
hle/kernel/time_manager.cpp hle/kernel/time_manager.cpp
hle/kernel/time_manager.h hle/kernel/time_manager.h
hle/lock.cpp
hle/lock.h
hle/result.h hle/result.h
hle/service/acc/acc.cpp hle/service/acc/acc.cpp
hle/service/acc/acc.h hle/service/acc/acc.h

View File

@ -161,7 +161,10 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
motion.rotation = emulated.GetGyroscope(); motion.rotation = emulated.GetGyroscope();
motion.orientation = emulated.GetOrientation(); motion.orientation = emulated.GetOrientation();
motion.quaternion = emulated.GetQuaternion(); motion.quaternion = emulated.GetQuaternion();
motion.gyro_bias = emulated.GetGyroBias();
motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
// Find what is this value
motion.verticalization_error = 0.0f;
TriggerOnChange(ConsoleTriggerType::Motion); TriggerOnChange(ConsoleTriggerType::Motion);
} }

View File

@ -50,6 +50,8 @@ struct ConsoleMotion {
Common::Vec3f rotation{}; Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{}; std::array<Common::Vec3f, 3> orientation{};
Common::Quaternion<f32> quaternion{}; Common::Quaternion<f32> quaternion{};
Common::Vec3f gyro_bias{};
f32 verticalization_error{};
bool is_at_rest{}; bool is_at_rest{};
}; };

View File

@ -843,23 +843,18 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
} }
bool EmulatedController::TestVibration(std::size_t device_index) { bool EmulatedController::TestVibration(std::size_t device_index) {
if (device_index >= output_devices.size()) { static constexpr VibrationValue test_vibration = {
return false;
}
if (!output_devices[device_index]) {
return false;
}
// Send a slight vibration to test for rumble support
constexpr Common::Input::VibrationStatus status = {
.low_amplitude = 0.001f, .low_amplitude = 0.001f,
.low_frequency = 160.0f, .low_frequency = 160.0f,
.high_amplitude = 0.001f, .high_amplitude = 0.001f,
.high_frequency = 320.0f, .high_frequency = 320.0f,
.type = Common::Input::VibrationAmplificationType::Linear,
}; };
return output_devices[device_index]->SetVibration(status) ==
Common::Input::VibrationError::None; // Send a slight vibration to test for rumble support
SetVibration(device_index, test_vibration);
// Stop any vibration and return the result
return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
} }
void EmulatedController::SetLedPattern() { void EmulatedController::SetLedPattern() {

View File

@ -496,6 +496,13 @@ struct VibrationValue {
}; };
static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
.low_amplitude = 0.0f,
.low_frequency = 160.0f,
.high_amplitude = 0.0f,
.high_frequency = 320.0f,
};
// This is nn::hid::VibrationDeviceInfo // This is nn::hid::VibrationDeviceInfo
struct VibrationDeviceInfo { struct VibrationDeviceInfo {
VibrationDeviceType type{}; VibrationDeviceType type{};

View File

@ -23,11 +23,11 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
} }
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
gyro = gyroscope - gyro_drift; gyro = gyroscope - gyro_bias;
// Auto adjust drift to minimize drift // Auto adjust drift to minimize drift
if (!IsMoving(0.1f)) { if (!IsMoving(0.1f)) {
gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f); gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
} }
if (gyro.Length2() < gyro_threshold) { if (gyro.Length2() < gyro_threshold) {
@ -41,8 +41,8 @@ void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
quat = quaternion; quat = quaternion;
} }
void MotionInput::SetGyroDrift(const Common::Vec3f& drift) { void MotionInput::SetGyroBias(const Common::Vec3f& bias) {
gyro_drift = drift; gyro_bias = bias;
} }
void MotionInput::SetGyroThreshold(f32 threshold) { void MotionInput::SetGyroThreshold(f32 threshold) {
@ -192,6 +192,10 @@ Common::Vec3f MotionInput::GetGyroscope() const {
return gyro; return gyro;
} }
Common::Vec3f MotionInput::GetGyroBias() const {
return gyro_bias;
}
Common::Quaternion<f32> MotionInput::GetQuaternion() const { Common::Quaternion<f32> MotionInput::GetQuaternion() const {
return quat; return quat;
} }

View File

@ -24,7 +24,7 @@ public:
void SetAcceleration(const Common::Vec3f& acceleration); void SetAcceleration(const Common::Vec3f& acceleration);
void SetGyroscope(const Common::Vec3f& gyroscope); void SetGyroscope(const Common::Vec3f& gyroscope);
void SetQuaternion(const Common::Quaternion<f32>& quaternion); void SetQuaternion(const Common::Quaternion<f32>& quaternion);
void SetGyroDrift(const Common::Vec3f& drift); void SetGyroBias(const Common::Vec3f& bias);
void SetGyroThreshold(f32 threshold); void SetGyroThreshold(f32 threshold);
void EnableReset(bool reset); void EnableReset(bool reset);
@ -36,6 +36,7 @@ public:
[[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
[[nodiscard]] Common::Vec3f GetAcceleration() const; [[nodiscard]] Common::Vec3f GetAcceleration() const;
[[nodiscard]] Common::Vec3f GetGyroscope() const; [[nodiscard]] Common::Vec3f GetGyroscope() const;
[[nodiscard]] Common::Vec3f GetGyroBias() const;
[[nodiscard]] Common::Vec3f GetRotations() const; [[nodiscard]] Common::Vec3f GetRotations() const;
[[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
@ -69,7 +70,7 @@ private:
Common::Vec3f gyro; Common::Vec3f gyro;
// Vector to be substracted from gyro measurements // Vector to be substracted from gyro measurements
Common::Vec3f gyro_drift; Common::Vec3f gyro_bias;
// Minimum gyro amplitude to detect if the device is moving // Minimum gyro amplitude to detect if the device is moving
f32 gyro_threshold = 0.0f; f32 gyro_threshold = 0.0f;

View File

@ -28,7 +28,6 @@
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h" #include "core/memory.h"
namespace Kernel { namespace Kernel {
@ -543,7 +542,6 @@ void KProcess::FreeTLSRegion(VAddr tls_address) {
} }
void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
std::lock_guard lock{HLE::g_hle_lock};
const auto ReprotectSegment = [&](const CodeSet::Segment& segment, const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
KMemoryPermission permission) { KMemoryPermission permission) {
page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);

View File

@ -41,7 +41,6 @@
#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/svc_types.h"
#include "core/hle/kernel/svc_wrap.h" #include "core/hle/kernel/svc_wrap.h"
#include "core/hle/lock.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/reporter.h" #include "core/reporter.h"
@ -137,7 +136,6 @@ enum class ResourceLimitValueType {
/// Set the process heap to a given Size. It can both extend and shrink the heap. /// Set the process heap to a given Size. It can both extend and shrink the heap.
static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
// Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. // 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
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
u32 attribute) { u32 attribute) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC, LOG_DEBUG(Kernel_SVC,
"called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
size, mask, attribute); size, mask, attribute);
@ -212,7 +209,6 @@ static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 si
/// Maps a memory range into a different range. /// Maps a memory range into a different range.
static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size); src_addr, size);
@ -232,7 +228,6 @@ static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr,
/// Unmaps a region that was previously mapped with svcMapMemory /// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size); src_addr, size);
@ -642,7 +637,6 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) {
/// Gets system/memory information for the current process /// Gets system/memory information for the current process
static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle,
u64 info_sub_id) { u64 info_sub_id) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle); info_sub_id, handle);
@ -924,7 +918,6 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h
/// Maps memory at a desired address /// Maps memory at a desired address
static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) { if (!Common::Is4KBAligned(addr)) {
@ -978,7 +971,6 @@ static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size)
/// Unmaps memory previously mapped via MapPhysicalMemory /// Unmaps memory previously mapped via MapPhysicalMemory
static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) { if (!Common::Is4KBAligned(addr)) {
@ -1520,7 +1512,6 @@ static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_han
static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
VAddr page_info_address, Handle process_handle, VAddr page_info_address, Handle process_handle,
VAddr address) { VAddr address) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);

View File

@ -6,7 +6,6 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/bcat/backend/backend.h" #include "core/hle/service/bcat/backend/backend.h"
namespace Service::BCAT { namespace Service::BCAT {
@ -29,10 +28,6 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
return impl; return impl;
} }
void ProgressServiceBackend::SetNeedHLELock(bool need) {
need_hle_lock = need;
}
void ProgressServiceBackend::SetTotalSize(u64 size) { void ProgressServiceBackend::SetTotalSize(u64 size) {
impl.total_bytes = size; impl.total_bytes = size;
SignalUpdate(); SignalUpdate();
@ -88,12 +83,7 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
} }
void ProgressServiceBackend::SignalUpdate() { void ProgressServiceBackend::SignalUpdate() {
if (need_hle_lock) { update_event->GetWritableEvent().Signal();
std::lock_guard lock(HLE::g_hle_lock);
update_event->GetWritableEvent().Signal();
} else {
update_event->GetWritableEvent().Signal();
}
} }
Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {}

View File

@ -71,10 +71,6 @@ class ProgressServiceBackend {
public: public:
~ProgressServiceBackend(); ~ProgressServiceBackend();
// Clients should call this with true if any of the functions are going to be called from a
// non-HLE thread and this class need to lock the hle mutex. (default is false)
void SetNeedHLELock(bool need);
// Sets the number of bytes total in the entire download. // Sets the number of bytes total in the entire download.
void SetTotalSize(u64 size); void SetTotalSize(u64 size);
@ -109,7 +105,6 @@ private:
DeliveryCacheProgressImpl impl{}; DeliveryCacheProgressImpl impl{};
Kernel::KEvent* update_event; Kernel::KEvent* update_event;
bool need_hle_lock = false;
}; };
// A class representing an abstract backend for BCAT functionality. // A class representing an abstract backend for BCAT functionality.

View File

@ -33,15 +33,14 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
// Try to read sixaxis sensor states
const auto motion_status = console->GetMotion(); const auto motion_status = console->GetMotion();
last_global_timestamp = core_timing.GetGlobalTimeNs().count();
console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; // This value increments every time the switch goes to sleep
next_seven_sixaxis_state.unknown = 1;
next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp;
next_seven_sixaxis_state.accel = motion_status.accel; next_seven_sixaxis_state.accel = motion_status.accel;
// Zero gyro values as they just mess up with the camera next_seven_sixaxis_state.gyro = motion_status.gyro;
// Note: Probably a correct sensivity setting must be set
next_seven_sixaxis_state.gyro = {};
next_seven_sixaxis_state.quaternion = { next_seven_sixaxis_state.quaternion = {
{ {
motion_status.quaternion.xyz.y, motion_status.quaternion.xyz.y,
@ -52,9 +51,9 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
}; };
console_six_axis.sampling_number++; console_six_axis.sampling_number++;
// TODO(German77): Find the purpose of those values console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
console_six_axis.verticalization_error = 0.0f; console_six_axis.verticalization_error = motion_status.verticalization_error;
console_six_axis.gyro_bias = {0.0f, 0.0f, 0.0f}; console_six_axis.gyro_bias = motion_status.gyro_bias;
// Update console six axis shared memory // Update console six axis shared memory
std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
@ -69,7 +68,6 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
} }
void Controller_ConsoleSixAxis::ResetTimestamp() { void Controller_ConsoleSixAxis::ResetTimestamp() {
seven_sixaxis_lifo.buffer_count = 0; last_saved_timestamp = last_global_timestamp;
seven_sixaxis_lifo.buffer_tail = 0;
} }
} // namespace Service::HID } // namespace Service::HID

View File

@ -39,8 +39,9 @@ public:
private: private:
struct SevenSixAxisState { struct SevenSixAxisState {
INSERT_PADDING_WORDS(4); // unused INSERT_PADDING_WORDS(2); // unused
s64 sampling_number{}; u64 timestamp{};
u64 sampling_number{};
u64 unknown{}; u64 unknown{};
Common::Vec3f accel{}; Common::Vec3f accel{};
Common::Vec3f gyro{}; Common::Vec3f gyro{};
@ -52,9 +53,10 @@ private:
struct ConsoleSharedMemory { struct ConsoleSharedMemory {
u64 sampling_number{}; u64 sampling_number{};
bool is_seven_six_axis_sensor_at_rest{}; bool is_seven_six_axis_sensor_at_rest{};
INSERT_PADDING_BYTES(4); // padding INSERT_PADDING_BYTES(3); // padding
f32 verticalization_error{}; f32 verticalization_error{};
Common::Vec3f gyro_bias{}; Common::Vec3f gyro_bias{};
INSERT_PADDING_BYTES(4); // padding
}; };
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
@ -64,6 +66,8 @@ private:
Core::HID::EmulatedConsole* console; Core::HID::EmulatedConsole* console;
u8* transfer_memory = nullptr; u8* transfer_memory = nullptr;
bool is_transfer_memory_set = false; bool is_transfer_memory_set = false;
u64 last_saved_timestamp{};
u64 last_global_timestamp{};
ConsoleSharedMemory console_six_axis{}; ConsoleSharedMemory console_six_axis{};
SevenSixAxisState next_seven_sixaxis_state{}; SevenSixAxisState next_seven_sixaxis_state{};
}; };

View File

@ -66,9 +66,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
auto& controller = controller_data[i]; auto& controller = controller_data[i];
controller.device = hid_core.GetEmulatedControllerByIndex(i); controller.device = hid_core.GetEmulatedControllerByIndex(i);
controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE; Core::HID::DEFAULT_VIBRATION_VALUE;
controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value = controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE; Core::HID::DEFAULT_VIBRATION_VALUE;
Core::HID::ControllerUpdateCallback engine_callback{ Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this, .on_change = [this,
i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@ -781,7 +781,8 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
controller.device->SetVibration(device_index, vibration); controller.device->SetVibration(device_index, vibration);
// Then reset the vibration value to its default value. // Then reset the vibration value to its default value.
controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE; controller.vibration[device_index].latest_vibration_value =
Core::HID::DEFAULT_VIBRATION_VALUE;
} }
return false; return false;

View File

@ -90,13 +90,6 @@ public:
Default = 3, Default = 3,
}; };
static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
.low_amplitude = 0.0f,
.low_frequency = 160.0f,
.high_amplitude = 0.0f,
.high_frequency = 320.0f,
};
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const; Core::HID::NpadStyleTag GetSupportedStyleSet() const;

View File

@ -1404,7 +1404,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
.high_frequency = 0.0f, .high_frequency = 0.0f,
}; };
default: default:
return Controller_NPad::DEFAULT_VIBRATION_VALUE; return Core::HID::DEFAULT_VIBRATION_VALUE;
} }
}(); }();

View File

@ -9,7 +9,6 @@
#include "core/core.h" #include "core/core.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/nfp/nfp.h" #include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h" #include "core/hle/service/nfp/nfp_user.h"
@ -337,7 +336,6 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
} }
bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
std::lock_guard lock{HLE::g_hle_lock};
if (buffer.size() < sizeof(AmiiboFile)) { if (buffer.size() < sizeof(AmiiboFile)) {
return false; return false;
} }

View File

@ -176,7 +176,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
} }
std::string GlslVersionSpecifier(const EmitContext& ctx) { std::string GlslVersionSpecifier(const EmitContext& ctx) {
if (ctx.uses_y_direction) { if (ctx.uses_y_direction || ctx.info.stores.Legacy() || ctx.info.loads.Legacy()) {
return " compatibility"; return " compatibility";
} }
return ""; return "";

View File

@ -98,6 +98,10 @@ void GetCbuf16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const
GetCbuf(ctx, ret, binding, offset, 16, cast, bit_offset); GetCbuf(ctx, ret, binding, offset, 16, cast, bit_offset);
} }
} }
u32 TexCoordIndex(IR::Attribute attr) {
return (static_cast<u32>(attr) - static_cast<u32>(IR::Attribute::FixedFncTexture0S)) / 4;
}
} // Anonymous namespace } // Anonymous namespace
void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
@ -186,6 +190,18 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
ctx.AddF32("{}=in_attr{}{}.{};", inst, index, InputVertexIndex(ctx, vertex), swizzle); ctx.AddF32("{}=in_attr{}{}.{};", inst, index, InputVertexIndex(ctx, vertex), swizzle);
return; return;
} }
// GLSL only exposes 8 legacy texcoords
if (attr >= IR::Attribute::FixedFncTexture8S && attr <= IR::Attribute::FixedFncTexture9Q) {
LOG_WARNING(Shader_GLSL, "GLSL does not allow access to gl_TexCoord[{}]",
TexCoordIndex(attr));
ctx.AddF32("{}=0.f;", inst);
return;
}
if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture7Q) {
const u32 index{TexCoordIndex(attr)};
ctx.AddF32("{}=gl_TexCoord[{}].{};", inst, index, swizzle);
return;
}
switch (attr) { switch (attr) {
case IR::Attribute::PrimitiveId: case IR::Attribute::PrimitiveId:
ctx.AddF32("{}=itof(gl_PrimitiveID);", inst); ctx.AddF32("{}=itof(gl_PrimitiveID);", inst);
@ -199,6 +215,16 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
ctx.AddF32("{}={}{}.{};", inst, input_decorator, ctx.position_name, swizzle); ctx.AddF32("{}={}{}.{};", inst, input_decorator, ctx.position_name, swizzle);
break; break;
} }
case IR::Attribute::ColorFrontDiffuseR:
case IR::Attribute::ColorFrontDiffuseG:
case IR::Attribute::ColorFrontDiffuseB:
case IR::Attribute::ColorFrontDiffuseA:
if (ctx.stage == Stage::Fragment) {
ctx.AddF32("{}=gl_Color.{};", inst, swizzle);
} else {
ctx.AddF32("{}=gl_FrontColor.{};", inst, swizzle);
}
break;
case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteS:
case IR::Attribute::PointSpriteT: case IR::Attribute::PointSpriteT:
ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle); ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle);
@ -238,6 +264,17 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
} }
const u32 element{static_cast<u32>(attr) % 4}; const u32 element{static_cast<u32>(attr) % 4};
const char swizzle{"xyzw"[element]}; const char swizzle{"xyzw"[element]};
// GLSL only exposes 8 legacy texcoords
if (attr >= IR::Attribute::FixedFncTexture8S && attr <= IR::Attribute::FixedFncTexture9Q) {
LOG_WARNING(Shader_GLSL, "GLSL does not allow access to gl_TexCoord[{}]",
TexCoordIndex(attr));
return;
}
if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture7Q) {
const u32 index{TexCoordIndex(attr)};
ctx.Add("gl_TexCoord[{}].{}={};", index, swizzle, value);
return;
}
switch (attr) { switch (attr) {
case IR::Attribute::Layer: case IR::Attribute::Layer:
if (ctx.stage != Stage::Geometry && if (ctx.stage != Stage::Geometry &&
@ -275,6 +312,33 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
case IR::Attribute::PositionW: case IR::Attribute::PositionW:
ctx.Add("gl_Position.{}={};", swizzle, value); ctx.Add("gl_Position.{}={};", swizzle, value);
break; break;
case IR::Attribute::ColorFrontDiffuseR:
case IR::Attribute::ColorFrontDiffuseG:
case IR::Attribute::ColorFrontDiffuseB:
case IR::Attribute::ColorFrontDiffuseA:
ctx.Add("gl_FrontColor.{}={};", swizzle, value);
break;
case IR::Attribute::ColorFrontSpecularR:
case IR::Attribute::ColorFrontSpecularG:
case IR::Attribute::ColorFrontSpecularB:
case IR::Attribute::ColorFrontSpecularA:
ctx.Add("gl_FrontSecondaryColor.{}={};", swizzle, value);
break;
case IR::Attribute::ColorBackDiffuseR:
case IR::Attribute::ColorBackDiffuseG:
case IR::Attribute::ColorBackDiffuseB:
case IR::Attribute::ColorBackDiffuseA:
ctx.Add("gl_BackColor.{}={};", swizzle, value);
break;
case IR::Attribute::ColorBackSpecularR:
case IR::Attribute::ColorBackSpecularG:
case IR::Attribute::ColorBackSpecularB:
case IR::Attribute::ColorBackSpecularA:
ctx.Add("gl_BackSecondaryColor.{}={};", swizzle, value);
break;
case IR::Attribute::FogCoordinate:
ctx.Add("gl_FogFragCoord={};", value);
break;
case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance0:
case IR::Attribute::ClipDistance1: case IR::Attribute::ClipDistance1:
case IR::Attribute::ClipDistance2: case IR::Attribute::ClipDistance2:

View File

@ -211,6 +211,27 @@ std::string_view OutputPrimitive(OutputTopology topology) {
throw InvalidArgument("Invalid output topology {}", topology); throw InvalidArgument("Invalid output topology {}", topology);
} }
void SetupLegacyOutPerVertex(EmitContext& ctx, std::string& header) {
if (!ctx.info.stores.Legacy()) {
return;
}
if (ctx.info.stores.FixedFunctionTexture()) {
header += "vec4 gl_TexCoord[8];";
}
if (ctx.info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) {
header += "vec4 gl_FrontColor;";
}
if (ctx.info.stores.AnyComponent(IR::Attribute::ColorFrontSpecularR)) {
header += "vec4 gl_FrontSecondaryColor;";
}
if (ctx.info.stores.AnyComponent(IR::Attribute::ColorBackDiffuseR)) {
header += "vec4 gl_BackColor;";
}
if (ctx.info.stores.AnyComponent(IR::Attribute::ColorBackSpecularR)) {
header += "vec4 gl_BackSecondaryColor;";
}
}
void SetupOutPerVertex(EmitContext& ctx, std::string& header) { void SetupOutPerVertex(EmitContext& ctx, std::string& header) {
if (!StoresPerVertexAttributes(ctx.stage)) { if (!StoresPerVertexAttributes(ctx.stage)) {
return; return;
@ -229,6 +250,7 @@ void SetupOutPerVertex(EmitContext& ctx, std::string& header) {
ctx.profile.support_viewport_index_layer_non_geometry && ctx.stage != Stage::Geometry) { ctx.profile.support_viewport_index_layer_non_geometry && ctx.stage != Stage::Geometry) {
header += "int gl_ViewportIndex;"; header += "int gl_ViewportIndex;";
} }
SetupLegacyOutPerVertex(ctx, header);
header += "};"; header += "};";
if (ctx.info.stores[IR::Attribute::ViewportIndex] && ctx.stage == Stage::Geometry) { if (ctx.info.stores[IR::Attribute::ViewportIndex] && ctx.stage == Stage::Geometry) {
header += "out int gl_ViewportIndex;"; header += "out int gl_ViewportIndex;";
@ -261,6 +283,20 @@ void SetupInPerVertex(EmitContext& ctx, std::string& header) {
header += "}gl_in[gl_MaxPatchVertices];"; header += "}gl_in[gl_MaxPatchVertices];";
} }
void SetupLegacyInPerFragment(EmitContext& ctx, std::string& header) {
if (!ctx.info.loads.Legacy()) {
return;
}
header += "in gl_PerFragment{";
if (ctx.info.loads.FixedFunctionTexture()) {
header += "vec4 gl_TexCoord[8];";
}
if (ctx.info.loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) {
header += "vec4 gl_Color;";
}
header += "};";
}
} // Anonymous namespace } // Anonymous namespace
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@ -325,6 +361,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
} }
SetupOutPerVertex(*this, header); SetupOutPerVertex(*this, header);
SetupInPerVertex(*this, header); SetupInPerVertex(*this, header);
SetupLegacyInPerFragment(*this, header);
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) { if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) {

View File

@ -44,6 +44,14 @@ Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&...
} }
} }
bool IsLegacyAttribute(IR::Attribute attribute) {
return (attribute >= IR::Attribute::ColorFrontDiffuseR &&
attribute <= IR::Attribute::ColorBackSpecularA) ||
attribute == IR::Attribute::FogCoordinate ||
(attribute >= IR::Attribute::FixedFncTexture0S &&
attribute <= IR::Attribute::FixedFncTexture9Q);
}
template <typename... Args> template <typename... Args>
Id OutputAccessChain(EmitContext& ctx, Id result_type, Id base, Args&&... args) { Id OutputAccessChain(EmitContext& ctx, Id result_type, Id base, Args&&... args) {
if (ctx.stage == Stage::TessellationControl) { if (ctx.stage == Stage::TessellationControl) {
@ -75,6 +83,17 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id);
} }
} }
if (IsLegacyAttribute(attr)) {
if (attr == IR::Attribute::FogCoordinate) {
return OutputAccessChain(ctx, ctx.output_f32, ctx.OutputLegacyAttribute(attr),
ctx.Const(0u));
} else {
const u32 element{static_cast<u32>(attr) % 4};
const Id element_id{ctx.Const(element)};
return OutputAccessChain(ctx, ctx.output_f32, ctx.OutputLegacyAttribute(attr),
element_id);
}
}
switch (attr) { switch (attr) {
case IR::Attribute::PointSize: case IR::Attribute::PointSize:
return ctx.output_point_size; return ctx.output_point_size;
@ -308,6 +327,18 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
const Id value{ctx.OpLoad(type->id, pointer)}; const Id value{ctx.OpLoad(type->id, pointer)};
return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
} }
if (IsLegacyAttribute(attr)) {
if (attr == IR::Attribute::FogCoordinate) {
const Id attr_ptr{AttrPointer(ctx, ctx.input_f32, vertex,
ctx.InputLegacyAttribute(attr), ctx.Const(0u))};
return ctx.OpLoad(ctx.F32[1], attr_ptr);
} else {
const Id element_id{ctx.Const(element)};
const Id attr_ptr{AttrPointer(ctx, ctx.input_f32, vertex,
ctx.InputLegacyAttribute(attr), element_id)};
return ctx.OpLoad(ctx.F32[1], attr_ptr);
}
}
switch (attr) { switch (attr) {
case IR::Attribute::PrimitiveId: case IR::Attribute::PrimitiveId:
return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.primitive_id)); return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.primitive_id));

View File

@ -18,6 +18,8 @@
namespace Shader::Backend::SPIRV { namespace Shader::Backend::SPIRV {
namespace { namespace {
constexpr size_t NUM_FIXEDFNCTEXTURE = 10;
enum class Operation { enum class Operation {
Increment, Increment,
Decrement, Decrement,
@ -430,6 +432,34 @@ Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) {
return pointer_type; return pointer_type;
} }
} }
size_t FindAndSetNextUnusedLocation(std::bitset<IR::NUM_GENERICS>& used_locations,
size_t& start_offset) {
for (size_t location = start_offset; location < used_locations.size(); ++location) {
if (!used_locations.test(location)) {
start_offset = location;
used_locations.set(location);
return location;
}
}
throw RuntimeError("Unable to get an unused location for legacy attribute");
}
Id DefineLegacyInput(EmitContext& ctx, std::bitset<IR::NUM_GENERICS>& used_locations,
size_t& start_offset) {
const Id id{DefineInput(ctx, ctx.F32[4], true)};
const size_t location = FindAndSetNextUnusedLocation(used_locations, start_offset);
ctx.Decorate(id, spv::Decoration::Location, location);
return id;
}
Id DefineLegacyOutput(EmitContext& ctx, std::bitset<IR::NUM_GENERICS>& used_locations,
size_t& start_offset, std::optional<u32> invocations) {
const Id id{DefineOutput(ctx, ctx.F32[4], invocations)};
const size_t location = FindAndSetNextUnusedLocation(used_locations, start_offset);
ctx.Decorate(id, spv::Decoration::Location, location);
return id;
}
} // Anonymous namespace } // Anonymous namespace
void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
@ -513,6 +543,64 @@ Id EmitContext::BitOffset16(const IR::Value& offset) {
return OpBitwiseAnd(U32[1], OpShiftLeftLogical(U32[1], Def(offset), Const(3u)), Const(16u)); return OpBitwiseAnd(U32[1], OpShiftLeftLogical(U32[1], Def(offset), Const(3u)), Const(16u));
} }
Id EmitContext::InputLegacyAttribute(IR::Attribute attribute) {
if (attribute >= IR::Attribute::ColorFrontDiffuseR &&
attribute <= IR::Attribute::ColorFrontDiffuseA) {
return input_front_color;
}
if (attribute >= IR::Attribute::ColorFrontSpecularR &&
attribute <= IR::Attribute::ColorFrontSpecularA) {
return input_front_secondary_color;
}
if (attribute >= IR::Attribute::ColorBackDiffuseR &&
attribute <= IR::Attribute::ColorBackDiffuseA) {
return input_back_color;
}
if (attribute >= IR::Attribute::ColorBackSpecularR &&
attribute <= IR::Attribute::ColorBackSpecularA) {
return input_back_secondary_color;
}
if (attribute == IR::Attribute::FogCoordinate) {
return input_fog_frag_coord;
}
if (attribute >= IR::Attribute::FixedFncTexture0S &&
attribute <= IR::Attribute::FixedFncTexture9Q) {
u32 index =
(static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::FixedFncTexture0S)) / 4;
return input_fixed_fnc_textures[index];
}
throw InvalidArgument("Attribute is not legacy attribute {}", attribute);
}
Id EmitContext::OutputLegacyAttribute(IR::Attribute attribute) {
if (attribute >= IR::Attribute::ColorFrontDiffuseR &&
attribute <= IR::Attribute::ColorFrontDiffuseA) {
return output_front_color;
}
if (attribute >= IR::Attribute::ColorFrontSpecularR &&
attribute <= IR::Attribute::ColorFrontSpecularA) {
return output_front_secondary_color;
}
if (attribute >= IR::Attribute::ColorBackDiffuseR &&
attribute <= IR::Attribute::ColorBackDiffuseA) {
return output_back_color;
}
if (attribute >= IR::Attribute::ColorBackSpecularR &&
attribute <= IR::Attribute::ColorBackSpecularA) {
return output_back_secondary_color;
}
if (attribute == IR::Attribute::FogCoordinate) {
return output_fog_frag_coord;
}
if (attribute >= IR::Attribute::FixedFncTexture0S &&
attribute <= IR::Attribute::FixedFncTexture9Q) {
u32 index =
(static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::FixedFncTexture0S)) / 4;
return output_fixed_fnc_textures[index];
}
throw InvalidArgument("Attribute is not legacy attribute {}", attribute);
}
void EmitContext::DefineCommonTypes(const Info& info) { void EmitContext::DefineCommonTypes(const Info& info) {
void_id = TypeVoid(); void_id = TypeVoid();
@ -1301,6 +1389,7 @@ void EmitContext::DefineInputs(const IR::Program& program) {
loads[IR::Attribute::TessellationEvaluationPointV]) { loads[IR::Attribute::TessellationEvaluationPointV]) {
tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord);
} }
std::bitset<IR::NUM_GENERICS> used_locations{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
const AttributeType input_type{runtime_info.generic_input_types[index]}; const AttributeType input_type{runtime_info.generic_input_types[index]};
if (!runtime_info.previous_stage_stores.Generic(index)) { if (!runtime_info.previous_stage_stores.Generic(index)) {
@ -1312,6 +1401,7 @@ void EmitContext::DefineInputs(const IR::Program& program) {
if (input_type == AttributeType::Disabled) { if (input_type == AttributeType::Disabled) {
continue; continue;
} }
used_locations.set(index);
const Id type{GetAttributeType(*this, input_type)}; const Id type{GetAttributeType(*this, input_type)};
const Id id{DefineInput(*this, type, true)}; const Id id{DefineInput(*this, type, true)};
Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
@ -1337,6 +1427,30 @@ void EmitContext::DefineInputs(const IR::Program& program) {
break; break;
} }
} }
size_t previous_unused_location = 0;
if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) {
input_front_color = DefineLegacyInput(*this, used_locations, previous_unused_location);
}
if (loads.AnyComponent(IR::Attribute::ColorFrontSpecularR)) {
input_front_secondary_color =
DefineLegacyInput(*this, used_locations, previous_unused_location);
}
if (loads.AnyComponent(IR::Attribute::ColorBackDiffuseR)) {
input_back_color = DefineLegacyInput(*this, used_locations, previous_unused_location);
}
if (loads.AnyComponent(IR::Attribute::ColorBackSpecularR)) {
input_back_secondary_color =
DefineLegacyInput(*this, used_locations, previous_unused_location);
}
if (loads.AnyComponent(IR::Attribute::FogCoordinate)) {
input_fog_frag_coord = DefineLegacyInput(*this, used_locations, previous_unused_location);
}
for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) {
if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) {
input_fixed_fnc_textures[index] =
DefineLegacyInput(*this, used_locations, previous_unused_location);
}
}
if (stage == Stage::TessellationEval) { if (stage == Stage::TessellationEval) {
for (size_t index = 0; index < info.uses_patches.size(); ++index) { for (size_t index = 0; index < info.uses_patches.size(); ++index) {
if (!info.uses_patches[index]) { if (!info.uses_patches[index]) {
@ -1387,9 +1501,38 @@ void EmitContext::DefineOutputs(const IR::Program& program) {
viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt,
spv::BuiltIn::ViewportMaskNV); spv::BuiltIn::ViewportMaskNV);
} }
std::bitset<IR::NUM_GENERICS> used_locations{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (info.stores.Generic(index)) { if (info.stores.Generic(index)) {
DefineGenericOutput(*this, index, invocations); DefineGenericOutput(*this, index, invocations);
used_locations.set(index);
}
}
size_t previous_unused_location = 0;
if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) {
output_front_color =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
}
if (info.stores.AnyComponent(IR::Attribute::ColorFrontSpecularR)) {
output_front_secondary_color =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
}
if (info.stores.AnyComponent(IR::Attribute::ColorBackDiffuseR)) {
output_back_color =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
}
if (info.stores.AnyComponent(IR::Attribute::ColorBackSpecularR)) {
output_back_secondary_color =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
}
if (info.stores.AnyComponent(IR::Attribute::FogCoordinate)) {
output_fog_frag_coord =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
}
for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) {
if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) {
output_fixed_fnc_textures[index] =
DefineLegacyOutput(*this, used_locations, previous_unused_location, invocations);
} }
} }
switch (stage) { switch (stage) {

View File

@ -113,6 +113,9 @@ public:
[[nodiscard]] Id BitOffset8(const IR::Value& offset); [[nodiscard]] Id BitOffset8(const IR::Value& offset);
[[nodiscard]] Id BitOffset16(const IR::Value& offset); [[nodiscard]] Id BitOffset16(const IR::Value& offset);
Id InputLegacyAttribute(IR::Attribute attribute);
Id OutputLegacyAttribute(IR::Attribute attribute);
Id Const(u32 value) { Id Const(u32 value) {
return Constant(U32[1], value); return Constant(U32[1], value);
} }
@ -278,10 +281,22 @@ public:
Id write_global_func_u32x4{}; Id write_global_func_u32x4{};
Id input_position{}; Id input_position{};
Id input_front_color{};
Id input_front_secondary_color{};
Id input_back_color{};
Id input_back_secondary_color{};
Id input_fog_frag_coord{};
std::array<Id, 10> input_fixed_fnc_textures{};
std::array<Id, 32> input_generics{}; std::array<Id, 32> input_generics{};
Id output_point_size{}; Id output_point_size{};
Id output_position{}; Id output_position{};
Id output_front_color{};
Id output_front_secondary_color{};
Id output_back_color{};
Id output_back_secondary_color{};
Id output_fog_frag_coord{};
std::array<Id, 10> output_fixed_fnc_textures{};
std::array<std::array<GenericElementInfo, 4>, 32> output_generics{}; std::array<std::array<GenericElementInfo, 4>, 32> output_generics{};
Id output_tess_level_outer{}; Id output_tess_level_outer{};

View File

@ -224,8 +224,6 @@ enum class Attribute : u64 {
constexpr size_t NUM_GENERICS = 32; constexpr size_t NUM_GENERICS = 32;
constexpr size_t NUM_FIXEDFNCTEXTURE = 10;
[[nodiscard]] bool IsGeneric(Attribute attribute) noexcept; [[nodiscard]] bool IsGeneric(Attribute attribute) noexcept;
[[nodiscard]] u32 GenericAttributeIndex(Attribute attribute); [[nodiscard]] u32 GenericAttributeIndex(Attribute attribute);

View File

@ -5,7 +5,6 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <queue>
#include "common/settings.h" #include "common/settings.h"
#include "shader_recompiler/exception.h" #include "shader_recompiler/exception.h"
@ -128,42 +127,6 @@ void AddNVNStorageBuffers(IR::Program& program) {
}); });
} }
} }
bool IsLegacyAttribute(IR::Attribute attribute) {
return (attribute >= IR::Attribute::ColorFrontDiffuseR &&
attribute <= IR::Attribute::ColorBackSpecularA) ||
attribute == IR::Attribute::FogCoordinate ||
(attribute >= IR::Attribute::FixedFncTexture0S &&
attribute <= IR::Attribute::FixedFncTexture9Q);
}
std::map<IR::Attribute, IR::Attribute> GenerateLegacyToGenericMappings(
const VaryingState& state, std::queue<IR::Attribute> ununsed_generics) {
std::map<IR::Attribute, IR::Attribute> mapping;
for (size_t index = 0; index < 4; ++index) {
auto attr = IR::Attribute::ColorFrontDiffuseR + index * 4;
if (state.AnyComponent(attr)) {
for (size_t i = 0; i < 4; ++i) {
mapping.insert({attr + i, ununsed_generics.front() + i});
}
ununsed_generics.pop();
}
}
if (state[IR::Attribute::FogCoordinate]) {
mapping.insert({IR::Attribute::FogCoordinate, ununsed_generics.front()});
ununsed_generics.pop();
}
for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) {
auto attr = IR::Attribute::FixedFncTexture0S + index * 4;
if (state.AnyComponent(attr)) {
for (size_t i = 0; i < 4; ++i) {
mapping.insert({attr + i, ununsed_generics.front() + i});
}
ununsed_generics.pop();
}
}
return mapping;
}
} // Anonymous namespace } // Anonymous namespace
IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool,
@ -263,62 +226,4 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b
return result; return result;
} }
void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
auto& stores = program.info.stores;
if (stores.Legacy()) {
std::queue<IR::Attribute> ununsed_output_generics{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (!stores.Generic(index)) {
ununsed_output_generics.push(IR::Attribute::Generic0X + index * 4);
}
}
auto mappings = GenerateLegacyToGenericMappings(stores, ununsed_output_generics);
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
switch (inst.GetOpcode()) {
case IR::Opcode::SetAttribute: {
const auto attr = inst.Arg(0).Attribute();
if (IsLegacyAttribute(attr)) {
stores.Set(mappings[attr], true);
inst.SetArg(0, Shader::IR::Value(mappings[attr]));
}
break;
}
default:
break;
}
}
}
}
auto& loads = program.info.loads;
if (loads.Legacy()) {
std::queue<IR::Attribute> ununsed_input_generics{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
const AttributeType input_type{runtime_info.generic_input_types[index]};
if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
input_type == AttributeType::Disabled) {
ununsed_input_generics.push(IR::Attribute::Generic0X + index * 4);
}
}
auto mappings = GenerateLegacyToGenericMappings(loads, ununsed_input_generics);
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
switch (inst.GetOpcode()) {
case IR::Opcode::GetAttribute: {
const auto attr = inst.Arg(0).Attribute();
if (IsLegacyAttribute(attr)) {
loads.Set(mappings[attr], true);
inst.SetArg(0, Shader::IR::Value(mappings[attr]));
}
break;
}
default:
break;
}
}
}
}
}
} // namespace Shader::Maxwell } // namespace Shader::Maxwell

View File

@ -10,7 +10,6 @@
#include "shader_recompiler/frontend/maxwell/control_flow.h" #include "shader_recompiler/frontend/maxwell/control_flow.h"
#include "shader_recompiler/host_translate_info.h" #include "shader_recompiler/host_translate_info.h"
#include "shader_recompiler/object_pool.h" #include "shader_recompiler/object_pool.h"
#include "shader_recompiler/runtime_info.h"
namespace Shader::Maxwell { namespace Shader::Maxwell {
@ -21,7 +20,4 @@ namespace Shader::Maxwell {
[[nodiscard]] IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b, [[nodiscard]] IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b,
Environment& env_vertex_b); Environment& env_vertex_b);
[[nodiscard]] void ConvertLegacyToGeneric(IR::Program& program,
const Shader::RuntimeInfo& runtime_info);
} // namespace Shader::Maxwell } // namespace Shader::Maxwell

View File

@ -53,8 +53,7 @@ struct VaryingState {
return AnyComponent(IR::Attribute::ColorFrontDiffuseR) || return AnyComponent(IR::Attribute::ColorFrontDiffuseR) ||
AnyComponent(IR::Attribute::ColorFrontSpecularR) || AnyComponent(IR::Attribute::ColorFrontSpecularR) ||
AnyComponent(IR::Attribute::ColorBackDiffuseR) || AnyComponent(IR::Attribute::ColorBackDiffuseR) ||
AnyComponent(IR::Attribute::ColorBackSpecularR) || FixedFunctionTexture() || AnyComponent(IR::Attribute::ColorBackSpecularR) || FixedFunctionTexture();
mask[static_cast<size_t>(IR::Attribute::FogCoordinate)];
} }
[[nodiscard]] bool FixedFunctionTexture() const noexcept { [[nodiscard]] bool FixedFunctionTexture() const noexcept {

View File

@ -130,6 +130,12 @@ bool Codec::CreateGpuAvDevice() {
} }
if (config->methods & HW_CONFIG_METHOD && config->device_type == type) { if (config->methods & HW_CONFIG_METHOD && config->device_type == type) {
av_codec_ctx->pix_fmt = config->pix_fmt; av_codec_ctx->pix_fmt = config->pix_fmt;
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
// skip zero-copy decoders, we don't currently support them
LOG_DEBUG(Service_NVDRV, "Skipping decoder {} with unsupported capability {}.",
av_hwdevice_get_type_name(type), config->methods);
continue;
}
LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type)); LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type));
return true; return true;
} }

View File

@ -42,7 +42,6 @@ namespace {
using Shader::Backend::GLASM::EmitGLASM; using Shader::Backend::GLASM::EmitGLASM;
using Shader::Backend::GLSL::EmitGLSL; using Shader::Backend::GLSL::EmitGLSL;
using Shader::Backend::SPIRV::EmitSPIRV; using Shader::Backend::SPIRV::EmitSPIRV;
using Shader::Maxwell::ConvertLegacyToGeneric;
using Shader::Maxwell::MergeDualVertexPrograms; using Shader::Maxwell::MergeDualVertexPrograms;
using Shader::Maxwell::TranslateProgram; using Shader::Maxwell::TranslateProgram;
using VideoCommon::ComputeEnvironment; using VideoCommon::ComputeEnvironment;
@ -468,14 +467,12 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)}; MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)};
switch (device.GetShaderBackend()) { switch (device.GetShaderBackend()) {
case Settings::ShaderBackend::GLSL: case Settings::ShaderBackend::GLSL:
ConvertLegacyToGeneric(program, runtime_info);
sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding);
break; break;
case Settings::ShaderBackend::GLASM: case Settings::ShaderBackend::GLASM:
sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding);
break; break;
case Settings::ShaderBackend::SPIRV: case Settings::ShaderBackend::SPIRV:
ConvertLegacyToGeneric(program, runtime_info);
sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding); sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding);
break; break;
} }

View File

@ -48,7 +48,6 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache);
namespace { namespace {
using Shader::Backend::SPIRV::EmitSPIRV; using Shader::Backend::SPIRV::EmitSPIRV;
using Shader::Maxwell::ConvertLegacyToGeneric;
using Shader::Maxwell::MergeDualVertexPrograms; using Shader::Maxwell::MergeDualVertexPrograms;
using Shader::Maxwell::TranslateProgram; using Shader::Maxwell::TranslateProgram;
using VideoCommon::ComputeEnvironment; using VideoCommon::ComputeEnvironment;
@ -547,7 +546,6 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
infos[stage_index] = &program.info; infos[stage_index] = &program.info;
const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)}; const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)};
ConvertLegacyToGeneric(program, runtime_info);
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)}; const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)};
device.SaveShader(code); device.SaveShader(code);
modules[stage_index] = BuildShader(device, code); modules[stage_index] = BuildShader(device, code);

View File

@ -12,7 +12,6 @@
#include "core/hid/emulated_controller.h" #include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h" #include "core/hid/hid_core.h"
#include "core/hid/hid_types.h" #include "core/hid/hid_types.h"
#include "core/hle/lock.h"
#include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/hid.h" #include "core/hle/service/hid/hid.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
@ -664,7 +663,5 @@ void QtControllerSelector::ReconfigureControllers(
} }
void QtControllerSelector::MainWindowReconfigureFinished() { void QtControllerSelector::MainWindowReconfigureFinished() {
// Acquire the HLE mutex
std::lock_guard lock(HLE::g_hle_lock);
callback(); callback();
} }

View File

@ -3,7 +3,6 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <QDateTime> #include <QDateTime>
#include "core/hle/lock.h"
#include "yuzu/applets/qt_error.h" #include "yuzu/applets/qt_error.h"
#include "yuzu/main.h" #include "yuzu/main.h"
@ -57,7 +56,5 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
} }
void QtErrorDisplay::MainWindowFinishedError() { void QtErrorDisplay::MainWindowFinishedError() {
// Acquire the HLE mutex
std::lock_guard lock{HLE::g_hle_lock};
callback(); callback();
} }

View File

@ -14,7 +14,6 @@
#include "common/fs/path_util.h" #include "common/fs/path_util.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/constants.h" #include "core/constants.h"
#include "core/hle/lock.h"
#include "yuzu/applets/qt_profile_select.h" #include "yuzu/applets/qt_profile_select.h"
#include "yuzu/main.h" #include "yuzu/main.h"
#include "yuzu/util/controller_navigation.h" #include "yuzu/util/controller_navigation.h"
@ -170,7 +169,5 @@ void QtProfileSelector::SelectProfile(
} }
void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) { void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
// Acquire the HLE mutex
std::lock_guard lock{HLE::g_hle_lock};
callback(uuid); callback(uuid);
} }

View File

@ -776,6 +776,7 @@ void Config::ReadUIGamelistValues() {
ReadBasicSetting(UISettings::values.row_1_text_id); ReadBasicSetting(UISettings::values.row_1_text_id);
ReadBasicSetting(UISettings::values.row_2_text_id); ReadBasicSetting(UISettings::values.row_2_text_id);
ReadBasicSetting(UISettings::values.cache_game_list); ReadBasicSetting(UISettings::values.cache_game_list);
ReadBasicSetting(UISettings::values.favorites_expanded);
const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
for (int i = 0; i < favorites_size; i++) { for (int i = 0; i < favorites_size; i++) {
qt_config->setArrayIndex(i); qt_config->setArrayIndex(i);
@ -1300,6 +1301,7 @@ void Config::SaveUIGamelistValues() {
WriteBasicSetting(UISettings::values.row_1_text_id); WriteBasicSetting(UISettings::values.row_1_text_id);
WriteBasicSetting(UISettings::values.row_2_text_id); WriteBasicSetting(UISettings::values.row_2_text_id);
WriteBasicSetting(UISettings::values.cache_game_list); WriteBasicSetting(UISettings::values.cache_game_list);
WriteBasicSetting(UISettings::values.favorites_expanded);
qt_config->beginWriteArray(QStringLiteral("favorites")); qt_config->beginWriteArray(QStringLiteral("favorites"));
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
qt_config->setArrayIndex(i); qt_config->setArrayIndex(i);

View File

@ -173,13 +173,17 @@ void GameList::OnItemExpanded(const QModelIndex& item) {
const bool is_dir = type == GameListItemType::CustomDir || type == GameListItemType::SdmcDir || const bool is_dir = type == GameListItemType::CustomDir || type == GameListItemType::SdmcDir ||
type == GameListItemType::UserNandDir || type == GameListItemType::UserNandDir ||
type == GameListItemType::SysNandDir; type == GameListItemType::SysNandDir;
const bool is_fave = type == GameListItemType::Favorites;
if (!is_dir) { if (!is_dir && !is_fave) {
return; return;
} }
const bool is_expanded = tree_view->isExpanded(item);
UISettings::values.game_dirs[item.data(GameListDir::GameDirRole).toInt()].expanded = if (is_fave) {
tree_view->isExpanded(item); UISettings::values.favorites_expanded = is_expanded;
return;
}
const int item_dir_index = item.data(GameListDir::GameDirRole).toInt();
UISettings::values.game_dirs[item_dir_index].expanded = is_expanded;
} }
// Event in order to filter the gamelist after editing the searchfield // Event in order to filter the gamelist after editing the searchfield
@ -458,10 +462,13 @@ void GameList::DonePopulating(const QStringList& watch_list) {
emit ShowList(!IsEmpty()); emit ShowList(!IsEmpty());
item_model->invisibleRootItem()->appendRow(new GameListAddDir()); item_model->invisibleRootItem()->appendRow(new GameListAddDir());
// Add favorites row
item_model->invisibleRootItem()->insertRow(0, new GameListFavorites()); item_model->invisibleRootItem()->insertRow(0, new GameListFavorites());
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
UISettings::values.favorited_ids.size() == 0); UISettings::values.favorited_ids.size() == 0);
tree_view->expand(item_model->invisibleRootItem()->child(0)->index()); tree_view->setExpanded(item_model->invisibleRootItem()->child(0)->index(),
UISettings::values.favorites_expanded.GetValue());
for (const auto id : UISettings::values.favorited_ids) { for (const auto id : UISettings::values.favorited_ids) {
AddFavorite(id); AddFavorite(id);
} }

View File

@ -1304,16 +1304,13 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
case Core::SystemResultStatus::ErrorVideoCore: case Core::SystemResultStatus::ErrorVideoCore:
QMessageBox::critical( QMessageBox::critical(
this, tr("An error occurred initializing the video core."), this, tr("An error occurred initializing the video core."),
tr("yuzu has encountered an error while running the video core, please see the " tr("yuzu has encountered an error while running the video core. "
"log for more details." "This is usually caused by outdated GPU drivers, including integrated ones. "
"Please see the log for more details. "
"For more information on accessing the log, please see the following page: " "For more information on accessing the log, please see the following page: "
"<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How " "<a href='https://yuzu-emu.org/help/reference/log-files/'>"
"to " "How to Upload the Log File</a>. "));
"Upload the Log File</a>."
"Ensure that you have the latest graphics drivers for your GPU."));
break; break;
default: default:
if (result > Core::SystemResultStatus::ErrorLoader) { if (result > Core::SystemResultStatus::ErrorLoader) {
const u16 loader_id = static_cast<u16>(Core::SystemResultStatus::ErrorLoader); const u16 loader_id = static_cast<u16>(Core::SystemResultStatus::ErrorLoader);

View File

@ -74,7 +74,6 @@ struct Values {
QString game_dir_deprecated; QString game_dir_deprecated;
bool game_dir_deprecated_deepscan; bool game_dir_deprecated_deepscan;
QVector<UISettings::GameDir> game_dirs; QVector<UISettings::GameDir> game_dirs;
QVector<u64> favorited_ids;
QStringList recent_files; QStringList recent_files;
QString language; QString language;
@ -96,6 +95,8 @@ struct Values {
Settings::BasicSetting<uint8_t> row_2_text_id{2, "row_2_text_id"}; Settings::BasicSetting<uint8_t> row_2_text_id{2, "row_2_text_id"};
std::atomic_bool is_game_list_reload_pending{false}; std::atomic_bool is_game_list_reload_pending{false};
Settings::BasicSetting<bool> cache_game_list{true, "cache_game_list"}; Settings::BasicSetting<bool> cache_game_list{true, "cache_game_list"};
Settings::BasicSetting<bool> favorites_expanded{true, "favorites_expanded"};
QVector<u64> favorited_ids;
bool configuration_applied; bool configuration_applied;
bool reset_to_defaults; bool reset_to_defaults;