early-access version 2321
This commit is contained in:
parent
669d9a246c
commit
994096ad3a
41 changed files with 598 additions and 424 deletions
218
CMakeLists.txt
218
CMakeLists.txt
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
9
externals/CMakeLists.txt
vendored
9
externals/CMakeLists.txt
vendored
|
@ -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
214
externals/ffmpeg/CMakeLists.txt
vendored
Executable 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)
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
|
||||||
std::lock_guard lock(HLE::g_hle_lock);
|
|
||||||
update_event->GetWritableEvent().Signal();
|
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)) {}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 "";
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue