Compare commits

..
Author SHA1 Message Date
yuzubot fe34f07d5a "Merge Tagged PR 1012" 2019-10-21 12:01:23 +00:00
yuzubot ba0a20b394 "Merge Tagged PR 1340" 2019-10-21 12:01:22 +00:00
yuzubot e0fe8802b6 "Merge Tagged PR 1703" 2019-10-21 12:01:22 +00:00
yuzubot 11d3927b5b "Merge Tagged PR 2365" 2019-10-21 12:01:21 +00:00
yuzubot a1e7391c39 "Merge Tagged PR 2542" 2019-10-21 12:01:20 +00:00
yuzubot 6775e03817 "Merge Tagged PR 2710" 2019-10-21 12:01:19 +00:00
yuzubot abee0adfb8 "Merge Tagged PR 2859" 2019-10-21 12:01:18 +00:00
yuzubot a8f8f36baa "Merge Tagged PR 2914" 2019-10-21 12:01:17 +00:00
yuzubot 96e50c0d8a "Merge Tagged PR 2933" 2019-10-21 12:01:16 +00:00
yuzubot 4d66449142 "Merge Tagged PR 2945" 2019-10-21 12:01:16 +00:00
yuzubot 68694e007a "Merge Tagged PR 2976" 2019-10-21 12:01:15 +00:00
yuzubot 64724ebe5f "Merge Tagged PR 2987" 2019-10-21 12:01:13 +00:00
yuzubot dc69b06d37 "Merge Tagged PR 2995" 2019-10-21 12:01:13 +00:00
yuzubot 4fe711bde9 "Merge Tagged PR 3007" 2019-10-21 12:01:12 +00:00
122 changed files with 2074 additions and 2325 deletions

No files matched your search

+4 -4
View File
@@ -1,12 +1,12 @@
#!/bin/bash -ex
# Copy documentation
cp license.txt "$DIR_NAME"
cp README.md "$DIR_NAME"
cp license.txt "$REV_NAME"
cp README.md "$REV_NAME"
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME"
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME"
mv "$DIR_NAME" $RELEASE_NAME
mv "$REV_NAME" $RELEASE_NAME
7z a "$REV_NAME.7z" $RELEASE_NAME
+2 -1
View File
@@ -11,4 +11,5 @@ ninja
ccache -s
ctest -VV -C Release
# Ignore zlib's tests, since they aren't gated behind a CMake option.
ctest -VV -E "(example|example64)" -C Release
+3 -9
View File
@@ -6,15 +6,9 @@ REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
if [ "${RELEASE_NAME}" = "mainline" ]; then
DIR_NAME="${REV_NAME}"
else
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
fi
mkdir "$REV_NAME"
mkdir "$DIR_NAME"
cp build/bin/yuzu-cmd "$DIR_NAME"
cp build/bin/yuzu "$DIR_NAME"
cp build/bin/yuzu-cmd "$REV_NAME"
cp build/bin/yuzu "$REV_NAME"
. .ci/scripts/common/post-upload.sh
+1 -8
View File
@@ -1,13 +1,6 @@
param($BUILD_NAME)
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
$GITREV = $(git show -s --format='%h')
if ("$BUILD_NAME" -eq "mainline") {
$RELEASE_DIST = "yuzu-windows-msvc"
} else {
$RELEASE_DIST = "yuzu-windows-msvc-$BUILD_NAME"
}
$RELEASE_DIST = "yuzu-windows-msvc"
$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
$MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", ""
+2 -8
View File
@@ -6,14 +6,8 @@ REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
if [ "${RELEASE_NAME}" = "mainline" ]; then
DIR_NAME="${REV_NAME}"
else
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
fi
mkdir "$DIR_NAME"
mkdir "$REV_NAME"
# get around the permission issues
cp -r package/* "$DIR_NAME"
cp -r package/* "$REV_NAME"
. .ci/scripts/common/post-upload.sh
-1
View File
@@ -17,7 +17,6 @@ steps:
inputs:
targetType: 'filePath'
filePath: './.ci/scripts/windows/upload.ps1'
arguments: '$(BuildName)'
- publish: artifacts
artifact: 'yuzu-$(BuildName)-windows-msvc'
displayName: 'Upload Artifacts'
+8 -8
View File
@@ -26,11 +26,11 @@
path = externals/mbedtls
url = https://github.com/DarkLordZach/mbedtls
[submodule "opus"]
path = externals/opus/opus
url = https://github.com/xiph/opus.git
path = externals/opus
url = https://github.com/ogniK5377/opus.git
[submodule "soundtouch"]
path = externals/soundtouch
url = https://github.com/citra-emu/ext-soundtouch.git
path = externals/soundtouch
url = https://github.com/citra-emu/ext-soundtouch.git
[submodule "libressl"]
path = externals/libressl
url = https://github.com/citra-emu/ext-libressl-portable.git
@@ -47,8 +47,8 @@
path = externals/sirit
url = https://github.com/ReinUsesLisp/sirit
[submodule "libzip"]
path = externals/libzip/libzip
url = https://github.com/nih-at/libzip.git
path = externals/libzip
url = https://github.com/DarkLordZach/libzip
[submodule "zlib"]
path = externals/zlib/zlib
url = https://github.com/madler/zlib.git
path = externals/zlib
url = https://github.com/madler/zlib
-1
View File
@@ -76,7 +76,6 @@ endif()
# zlib
add_subdirectory(zlib EXCLUDE_FROM_ALL)
set(ZLIB_LIBRARIES z)
# libzip
add_subdirectory(libzip EXCLUDE_FROM_ALL)
Vendored Submodule
+1
Submodule externals/libzip added at bd7a8103e9.
-564
View File
@@ -1,564 +0,0 @@
# TODO:
# create usable libtool .la file
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libzip")
PROJECT(libzip C)
OPTION(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" ON)
OPTION(ENABLE_GNUTLS "Enable use of GnuTLS" ON)
OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
OPTION(ENABLE_WINDOWS_CRYPTO "Enable use of Windows cryptography libraries" ON)
OPTION(ENABLE_BZIP2 "Enable use of BZip2" OFF)
OPTION(ENABLE_LZMA "Enable use of LZMA" OFF)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckTypeSize)
INCLUDE(CheckCSourceRuns)
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckStructHasMember)
INCLUDE(TestBigEndian)
INCLUDE(GNUInstallDirs)
IF(ENABLE_COMMONCRYPTO)
CHECK_INCLUDE_FILES(CommonCrypto/CommonCrypto.h COMMONCRYPTO_FOUND)
ELSE()
SET(COMMONCRYPTO_FOUND FALSE)
ENDIF()
IF(ENABLE_GNUTLS)
INCLUDE(FindNettle)
INCLUDE(FindGnuTLS)
ELSE()
SET(GNUTLS_FOUND FALSE)
ENDIF()
IF(ENABLE_MBEDTLS)
FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/aes.h)
FIND_LIBRARY(MBEDTLS_LIBRARIES NAMES mbedcrypto)
ELSE()
SET(MBEDTLS_LIBRARIES FALSE)
ENDIF()
IF(ENABLE_OPENSSL)
INCLUDE(FindOpenSSL)
ELSE()
SET(OPENSSL_FOUND FALSE)
ENDIF()
IF(WIN32)
IF(ENABLE_WINDOWS_CRYPTO)
SET(WINDOWS_CRYPTO_FOUND TRUE)
ENDIF()
ELSE()
SET(WINDOWS_CRYPTO_FOUND FALSE)
ENDIF()
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
OPTION(SHARED_LIB_VERSIONNING "Add SO version in .so build" ON)
SET(PACKAGE "libzip")
SET(PACKAGE_NAME ${PACKAGE})
SET(PACKAGE_VERSION_MAJOR "1")
SET(PACKAGE_VERSION_MINOR "5")
SET(PACKAGE_VERSION_MICRO "2a")
#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_MICRO}")
SET(PACKAGE_VERSION ${VERSION})
SET(LIBZIP_VERSION ${PACKAGE_VERSION})
SET(LIBZIP_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR})
SET(LIBZIP_VERSION_MINOR ${PACKAGE_VERSION_MINOR})
SET(LIBZIP_VERSION_MICRO ${PACKAGE_VERSION_MICRO})
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
SET(ARCHIVE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
IF(NOT TARGET dist)
ADD_CUSTOM_TARGET(dist
COMMAND git config tar.tar.xz.command "xz -c"
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.gz HEAD
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.xz HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
ADD_CUSTOM_TARGET(distcheck
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest 2>/dev/null || true
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND cmake -E tar xf ${ARCHIVE_NAME}.tar.gz
COMMAND chmod -R u-w ${ARCHIVE_NAME}
COMMAND mkdir ${ARCHIVE_NAME}-build
COMMAND mkdir ${ARCHIVE_NAME}-dest
COMMAND cd ${ARCHIVE_NAME}-build && cmake -DCMAKE_INSTALL_PREFIX=../${ARCHIVE_NAME}-dest ../${ARCHIVE_NAME}
COMMAND cd ${ARCHIVE_NAME}-build && make -j4
COMMAND cd ${ARCHIVE_NAME}-build && make test
COMMAND cd ${ARCHIVE_NAME}-build && make install
# COMMAND cd ${ARCHIVE_NAME}-build && make uninstall
# COMMAND if [ `find ${ARCHIVE_NAME}-dest ! -type d | wc -l` -ne 0 ]; then echo leftover files in ${ARCHIVE_NAME}-dest; false; fi
COMMAND cd ${ARCHIVE_NAME}-build && make clean
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND echo "${ARCHIVE_NAME}.tar.gz is ready for distribution."
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
ADD_DEPENDENCIES(distcheck dist)
ENDIF(NOT TARGET dist)
IF(BUILD_SHARED_LIBS)
SET(HAVE_SHARED TRUE)
ELSE()
SET(ZIP_STATIC TRUE)
ENDIF()
# Checks
CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD)
CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE)
CHECK_FUNCTION_EXISTS(_dup HAVE__DUP)
CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN)
CHECK_FUNCTION_EXISTS(_fileno HAVE__FILENO)
CHECK_FUNCTION_EXISTS(_open HAVE__OPEN)
CHECK_FUNCTION_EXISTS(_setmode HAVE__SETMODE)
CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
CHECK_FUNCTION_EXISTS(_strdup HAVE__STRDUP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64)
CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64)
CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK)
CHECK_FUNCTION_EXISTS(arc4random HAVE_ARC4RANDOM)
CHECK_FUNCTION_EXISTS(clonefile HAVE_CLONEFILE)
CHECK_FUNCTION_EXISTS(explicit_bzero HAVE_EXPLICIT_BZERO)
CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET)
CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO)
CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
CHECK_FUNCTION_EXISTS(ftello HAVE_FTELLO)
CHECK_FUNCTION_EXISTS(getprogname HAVE_GETPROGNAME)
CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS(open HAVE_OPEN)
CHECK_FUNCTION_EXISTS(setmode HAVE_SETMODE)
CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP)
CHECK_FUNCTION_EXISTS(stricmp HAVE_STRICMP)
CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL)
CHECK_FUNCTION_EXISTS(strtoull HAVE_STRTOULL)
CHECK_INCLUDE_FILES("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H)
CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H_LIBZIP)
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H_LIBZIP)
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H_LIBZIP)
# TODO: fix test
# this test does not find __progname even when it exists
#CHECK_SYMBOL_EXISTS(__progname stdlib.h HAVE___PROGNAME)
CHECK_TYPE_SIZE(__int8 __INT8_LIBZIP)
CHECK_TYPE_SIZE(int8_t INT8_T_LIBZIP)
CHECK_TYPE_SIZE(uint8_t UINT8_T_LIBZIP)
CHECK_TYPE_SIZE(__int16 __INT16_LIBZIP)
CHECK_TYPE_SIZE(int16_t INT16_T_LIBZIP)
CHECK_TYPE_SIZE(uint16_t UINT16_T_LIBZIP)
CHECK_TYPE_SIZE(__int32 __INT32_LIBZIP)
CHECK_TYPE_SIZE(int32_t INT32_T_LIBZIP)
CHECK_TYPE_SIZE(uint32_t UINT32_T_LIBZIP)
CHECK_TYPE_SIZE(__int64 __INT64_LIBZIP)
CHECK_TYPE_SIZE(int64_t INT64_T_LIBZIP)
CHECK_TYPE_SIZE(uint64_t UINT64_T_LIBZIP)
CHECK_TYPE_SIZE("short" SHORT_LIBZIP)
CHECK_TYPE_SIZE("int" INT_LIBZIP)
CHECK_TYPE_SIZE("long" LONG_LIBZIP)
CHECK_TYPE_SIZE("long long" LONG_LONG_LIBZIP)
CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T)
CHECK_TYPE_SIZE("size_t" SIZE_T_LIBZIP)
CHECK_TYPE_SIZE("ssize_t" SSIZE_T_LIBZIP)
CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
#include <linux/fs.h>
int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE)
CHECK_C_SOURCE_COMPILES("
int foo(char * _Nullable bar);
int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
#FIND_PACKAGE(ZLIB 1.1.2 REQUIRED)
INCLUDE_DIRECTORIES(../zlib/zlib)
SET(CMAKE_REQUIRED_INCLUDES ../zlib/zlib)
IF(ENABLE_BZIP2)
FIND_PACKAGE(BZip2)
IF(BZIP2_FOUND)
SET (HAVE_LIBBZ2 1)
INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${BZIP2_LIBRARIES})
ELSE()
MESSAGE(WARNING "-- bzip2 library not found; bzip2 support disabled")
ENDIF(BZIP2_FOUND)
ENDIF(ENABLE_BZIP2)
IF(ENABLE_LZMA)
FIND_PACKAGE(LibLZMA)
IF(LIBLZMA_FOUND)
SET (HAVE_LIBLZMA 1)
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${LIBLZMA_LIBRARY})
ELSE()
MESSAGE(WARNING "-- lzma library not found; lzma support disabled")
ENDIF(LIBLZMA_FOUND)
ENDIF(ENABLE_LZMA)
IF (COMMONCRYPTO_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_COMMONCRYPTO 1)
ELSEIF (WINDOWS_CRYPTO_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_WINDOWS_CRYPTO 1)
ELSEIF (GNUTLS_FOUND AND NETTLE_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_GNUTLS 1)
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR} ${NETTLE_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${GNUTLS_LIBRARY} ${NETTLE_LIBRARY})
ELSEIF (OPENSSL_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_OPENSSL 1)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${OPENSSL_LIBRARIES})
ELSEIF (MBEDTLS_LIBRARIES)
SET (HAVE_CRYPTO 1)
SET (HAVE_MBEDTLS 1)
INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${MBEDTLS_LIBRARIES})
ENDIF()
IF (NOT HAVE_CRYPTO)
MESSAGE(WARNING "-- neither Common Crypto, GnuTLS, mbed TLS, OpenSSL, nor Windows Cryptography found; AES support disabled")
ENDIF()
IF(MSVC)
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS")
ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE")
ENDIF(MSVC)
if(WIN32)
if(HAVE_WINDOWS_CRYPTO)
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} bcrypt)
endif()
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
ADD_DEFINITIONS(-DMS_UWP)
else(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} advapi32)
endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
endif(WIN32)
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
# rpath handling: use rpath in installed binaries
IF(NOT CMAKE_SYSTEM_NAME MATCHES Linux)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ENDIF()
# fixed size integral types
IF(HAVE_INTTYPES_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>")
ELSEIF(HAVE_STDINT_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#include <stdint.h>")
ELSEIF(HAVE_SYS_TYPES_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#include <sys/types.h>")
ENDIF()
IF(HAVE_INT8_T_LIBZIP)
SET(ZIP_INT8_T int8_t)
ELSEIF(HAVE___INT8_LIBZIP)
SET(ZIP_INT8_T __int8)
ELSE()
SET(ZIP_INT8_T "signed char")
ENDIF()
IF(HAVE_UINT8_T_LIBZIP)
SET(ZIP_UINT8_T uint8_t)
ELSEIF(HAVE___INT8_LIBZIP)
SET(ZIP_UINT8_T "unsigned __int8")
ELSE()
SET(ZIP_UINT8_T "unsigned char")
ENDIF()
IF(HAVE_INT16_T_LIBZIP)
SET(ZIP_INT16_T int16_t)
ELSEIF(HAVE___INT16_LIBZIP)
SET(INT16_T_LIBZIP __int16)
ELSEIF(SHORT_LIBZIP EQUAL 2)
SET(INT16_T_LIBZIP short)
ENDIF()
IF(HAVE_UINT16_T_LIBZIP)
SET(ZIP_UINT16_T uint16_t)
ELSEIF(HAVE___INT16_LIBZIP)
SET(UINT16_T_LIBZIP "unsigned __int16")
ELSEIF(SHORT_LIBZIP EQUAL 2)
SET(UINT16_T_LIBZIP "unsigned short")
ENDIF()
IF(HAVE_INT32_T_LIBZIP)
SET(ZIP_INT32_T int32_t)
ELSEIF(HAVE___INT32_LIBZIP)
SET(ZIP_INT32_T __int32)
ELSEIF(INT_LIBZIP EQUAL 4)
SET(ZIP_INT32_T int)
ELSEIF(LONG_LIBZIP EQUAL 4)
SET(ZIP_INT32_T long)
ENDIF()
IF(HAVE_UINT32_T_LIBZIP)
SET(ZIP_UINT32_T uint32_t)
ELSEIF(HAVE___INT32_LIBZIP)
SET(ZIP_UINT32_T "unsigned __int32")
ELSEIF(INT_LIBZIP EQUAL 4)
SET(ZIP_UINT32_T "unsigned int")
ELSEIF(LONG_LIBZIP EQUAL 4)
SET(ZIP_UINT32_T "unsigned long")
ENDIF()
IF(HAVE_INT64_T_LIBZIP)
SET(ZIP_INT64_T int64_t)
ELSEIF(HAVE___INT64_LIBZIP)
SET(ZIP_INT64_T __int64)
ELSEIF(LONG_LIBZIP EQUAL 8)
SET(ZIP_INT64_T long)
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
SET(ZIP_INT64_T "long long")
ENDIF()
IF(HAVE_UINT64_T_LIBZIP)
SET(ZIP_UINT64_T uint64_t)
ELSEIF(HAVE___INT64_LIBZIP)
SET(ZIP_UINT64_T "unsigned __int64")
ELSEIF(LONG_LIBZIP EQUAL 8)
SET(ZIP_UINT64_T "unsigned long")
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
SET(ZIP_UINT64_T "unsigned long long")
ENDIF()
IF(HAVE_NULLABLE)
SET(ZIP_NULLABLE_DEFINES)
ELSE()
SET(ZIP_NULLABLE_DEFINES "#define _Nullable
#define _Nonnull")
ENDIF()
# write out config file
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/config.h)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-zipconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h)
# installation
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
INSTALL(FILES libzip/lib/zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
SET(CMAKE_C_VISIBILITY_PRESET hidden)
ADD_LIBRARY(zip
libzip/lib/zip_add.c
libzip/lib/zip_add_dir.c
libzip/lib/zip_add_entry.c
libzip/lib/zip_algorithm_deflate.c
libzip/lib/zip_buffer.c
libzip/lib/zip_close.c
libzip/lib/zip_delete.c
libzip/lib/zip_dir_add.c
libzip/lib/zip_dirent.c
libzip/lib/zip_discard.c
libzip/lib/zip_entry.c
libzip/lib/zip_err_str.c
libzip/lib/zip_error.c
libzip/lib/zip_error_clear.c
libzip/lib/zip_error_get.c
libzip/lib/zip_error_get_sys_type.c
libzip/lib/zip_error_strerror.c
libzip/lib/zip_error_to_str.c
libzip/lib/zip_extra_field.c
libzip/lib/zip_extra_field_api.c
libzip/lib/zip_fclose.c
libzip/lib/zip_fdopen.c
libzip/lib/zip_file_add.c
libzip/lib/zip_file_error_clear.c
libzip/lib/zip_file_error_get.c
libzip/lib/zip_file_get_comment.c
libzip/lib/zip_file_get_external_attributes.c
libzip/lib/zip_file_get_offset.c
libzip/lib/zip_file_rename.c
libzip/lib/zip_file_replace.c
libzip/lib/zip_file_set_comment.c
libzip/lib/zip_file_set_encryption.c
libzip/lib/zip_file_set_external_attributes.c
libzip/lib/zip_file_set_mtime.c
libzip/lib/zip_file_strerror.c
libzip/lib/zip_filerange_crc.c
libzip/lib/zip_fopen.c
libzip/lib/zip_fopen_encrypted.c
libzip/lib/zip_fopen_index.c
libzip/lib/zip_fopen_index_encrypted.c
libzip/lib/zip_fread.c
libzip/lib/zip_fseek.c
libzip/lib/zip_ftell.c
libzip/lib/zip_get_archive_comment.c
libzip/lib/zip_get_archive_flag.c
libzip/lib/zip_get_encryption_implementation.c
libzip/lib/zip_get_file_comment.c
libzip/lib/zip_get_name.c
libzip/lib/zip_get_num_entries.c
libzip/lib/zip_get_num_files.c
libzip/lib/zip_hash.c
libzip/lib/zip_io_util.c
libzip/lib/zip_libzip_version.c
libzip/lib/zip_memdup.c
libzip/lib/zip_name_locate.c
libzip/lib/zip_new.c
libzip/lib/zip_open.c
libzip/lib/zip_progress.c
libzip/lib/zip_rename.c
libzip/lib/zip_replace.c
libzip/lib/zip_set_archive_comment.c
libzip/lib/zip_set_archive_flag.c
libzip/lib/zip_set_default_password.c
libzip/lib/zip_set_file_comment.c
libzip/lib/zip_set_file_compression.c
libzip/lib/zip_set_name.c
libzip/lib/zip_source_accept_empty.c
libzip/lib/zip_source_begin_write.c
libzip/lib/zip_source_begin_write_cloning.c
libzip/lib/zip_source_buffer.c
libzip/lib/zip_source_call.c
libzip/lib/zip_source_close.c
libzip/lib/zip_source_commit_write.c
libzip/lib/zip_source_compress.c
libzip/lib/zip_source_crc.c
libzip/lib/zip_source_error.c
libzip/lib/zip_source_filep.c
libzip/lib/zip_source_free.c
libzip/lib/zip_source_function.c
libzip/lib/zip_source_get_compression_flags.c
libzip/lib/zip_source_is_deleted.c
libzip/lib/zip_source_layered.c
libzip/lib/zip_source_open.c
libzip/lib/zip_source_pkware.c
libzip/lib/zip_source_read.c
libzip/lib/zip_source_remove.c
libzip/lib/zip_source_rollback_write.c
libzip/lib/zip_source_seek.c
libzip/lib/zip_source_seek_write.c
libzip/lib/zip_source_stat.c
libzip/lib/zip_source_supports.c
libzip/lib/zip_source_tell.c
libzip/lib/zip_source_tell_write.c
libzip/lib/zip_source_window.c
libzip/lib/zip_source_write.c
libzip/lib/zip_source_zip.c
libzip/lib/zip_source_zip_new.c
libzip/lib/zip_stat.c
libzip/lib/zip_stat_index.c
libzip/lib/zip_stat_init.c
libzip/lib/zip_strerror.c
libzip/lib/zip_string.c
libzip/lib/zip_unchange.c
libzip/lib/zip_unchange_all.c
libzip/lib/zip_unchange_archive.c
libzip/lib/zip_unchange_data.c
libzip/lib/zip_utf-8.c
)
IF(WIN32)
target_sources(zip PRIVATE
libzip/lib/zip_source_win32handle.c
libzip/lib/zip_source_win32utf8.c
libzip/lib/zip_source_win32w.c
)
IF(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
ELSE()
target_sources(zip PRIVATE libzip/lib/zip_source_win32a.c)
ENDIF()
ELSE()
target_sources(zip PRIVATE
libzip/lib/zip_mkstempm.c
libzip/lib/zip_source_file.c
libzip/lib/zip_random_unix.c
)
ENDIF()
IF(HAVE_LIBBZ2)
target_sources(zip PRIVATE libzip/lib/zip_algorithm_bzip2.c)
ENDIF()
IF(HAVE_LIBLZMA)
target_sources(zip PRIVATE libzip/lib/zip_algorithm_xz.c)
ENDIF()
IF(HAVE_COMMONCRYPTO)
target_sources(zip PRIVATE libzip/lib/zip_crypto_commoncrypto.c)
ELSEIF(HAVE_WINDOWS_CRYPTO)
target_sources(zip PRIVATE libzip/lib/zip_crypto_win.c)
ELSEIF(HAVE_GNUTLS)
target_sources(zip PRIVATE libzip/lib/zip_crypto_gnutls.c)
ELSEIF(HAVE_OPENSSL)
target_sources(zip PRIVATE libzip/lib/zip_crypto_openssl.c)
ELSEIF(HAVE_MBEDTLS)
target_sources(zip PRIVATE libzip/lib/zip_crypto_mbedtls.c)
ENDIF()
IF(HAVE_CRYPTO)
target_sources(zip PRIVATE
libzip/lib/zip_winzip_aes.c
libzip/lib/zip_source_winzip_aes_decode.c
libzip/lib/zip_source_winzip_aes_encode.c
)
ENDIF()
target_include_directories(zip
PUBLIC
libzip/lib
${CMAKE_CURRENT_BINARY_DIR}/libzip
)
# pkgconfig file
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(exec_prefix \${prefix})
SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
IF(CMAKE_SYSTEM_NAME MATCHES BSD)
SET(PKG_CONFIG_RPATH "-Wl,-R\${libdir}")
ENDIF(CMAKE_SYSTEM_NAME MATCHES BSD)
get_target_property(LIBS_PRIVATE zip LINK_LIBRARIES)
foreach(LIB ${LIBS_PRIVATE})
if(LIB MATCHES "^/")
get_filename_component(LIB ${LIB} NAME_WE)
string(REGEX REPLACE "^lib" "" LIB ${LIB})
endif()
set(LIBS "${LIBS} -l${LIB}")
endforeach()
CONFIGURE_FILE(libzip/libzip.pc.in libzip/libzip.pc @ONLY)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
ADD_CUSTOM_TARGET(update_zip_err_str
COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip_err_str.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh
)
IF(SHARED_LIB_VERSIONNING)
SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 5.0 SOVERSION 5)
ENDIF()
TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARIES} ${OPTIONAL_LIBRARY})
INSTALL(TARGETS zip
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
Vendored Submodule
+1
Submodule externals/opus added at 562f8ba555.
-250
View File
@@ -1,250 +0,0 @@
cmake_minimum_required(VERSION 3.8)
project(opus)
option(OPUS_STACK_PROTECTOR "Use stack protection" OFF)
option(OPUS_USE_ALLOCA "Use alloca for stack arrays (on non-C99 compilers)" OFF)
option(OPUS_CUSTOM_MODES "Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames" OFF)
option(OPUS_FIXED_POINT "Compile as fixed-point (for machines without a fast enough FPU)" OFF)
option(OPUS_ENABLE_FLOAT_API "Compile with the floating point API (for machines with float library" ON)
include(opus/opus_functions.cmake)
if(OPUS_STACK_PROTECTOR)
if(NOT MSVC) # GC on by default on MSVC
check_and_set_flag(STACK_PROTECTION_STRONG -fstack-protector-strong)
endif()
else()
if(MSVC)
check_and_set_flag(BUFFER_SECURITY_CHECK /GS-)
endif()
endif()
add_library(opus STATIC
# CELT sources
opus/celt/bands.c
opus/celt/celt.c
opus/celt/celt_decoder.c
opus/celt/celt_encoder.c
opus/celt/celt_lpc.c
opus/celt/cwrs.c
opus/celt/entcode.c
opus/celt/entdec.c
opus/celt/entenc.c
opus/celt/kiss_fft.c
opus/celt/laplace.c
opus/celt/mathops.c
opus/celt/mdct.c
opus/celt/modes.c
opus/celt/pitch.c
opus/celt/quant_bands.c
opus/celt/rate.c
opus/celt/vq.c
# SILK sources
opus/silk/A2NLSF.c
opus/silk/CNG.c
opus/silk/HP_variable_cutoff.c
opus/silk/LPC_analysis_filter.c
opus/silk/LPC_fit.c
opus/silk/LPC_inv_pred_gain.c
opus/silk/LP_variable_cutoff.c
opus/silk/NLSF2A.c
opus/silk/NLSF_VQ.c
opus/silk/NLSF_VQ_weights_laroia.c
opus/silk/NLSF_decode.c
opus/silk/NLSF_del_dec_quant.c
opus/silk/NLSF_encode.c
opus/silk/NLSF_stabilize.c
opus/silk/NLSF_unpack.c
opus/silk/NSQ.c
opus/silk/NSQ_del_dec.c
opus/silk/PLC.c
opus/silk/VAD.c
opus/silk/VQ_WMat_EC.c
opus/silk/ana_filt_bank_1.c
opus/silk/biquad_alt.c
opus/silk/bwexpander.c
opus/silk/bwexpander_32.c
opus/silk/check_control_input.c
opus/silk/code_signs.c
opus/silk/control_SNR.c
opus/silk/control_audio_bandwidth.c
opus/silk/control_codec.c
opus/silk/dec_API.c
opus/silk/decode_core.c
opus/silk/decode_frame.c
opus/silk/decode_indices.c
opus/silk/decode_parameters.c
opus/silk/decode_pitch.c
opus/silk/decode_pulses.c
opus/silk/decoder_set_fs.c
opus/silk/enc_API.c
opus/silk/encode_indices.c
opus/silk/encode_pulses.c
opus/silk/gain_quant.c
opus/silk/init_decoder.c
opus/silk/init_encoder.c
opus/silk/inner_prod_aligned.c
opus/silk/interpolate.c
opus/silk/lin2log.c
opus/silk/log2lin.c
opus/silk/pitch_est_tables.c
opus/silk/process_NLSFs.c
opus/silk/quant_LTP_gains.c
opus/silk/resampler.c
opus/silk/resampler_down2.c
opus/silk/resampler_down2_3.c
opus/silk/resampler_private_AR2.c
opus/silk/resampler_private_IIR_FIR.c
opus/silk/resampler_private_down_FIR.c
opus/silk/resampler_private_up2_HQ.c
opus/silk/resampler_rom.c
opus/silk/shell_coder.c
opus/silk/sigm_Q15.c
opus/silk/sort.c
opus/silk/stereo_LR_to_MS.c
opus/silk/stereo_MS_to_LR.c
opus/silk/stereo_decode_pred.c
opus/silk/stereo_encode_pred.c
opus/silk/stereo_find_predictor.c
opus/silk/stereo_quant_pred.c
opus/silk/sum_sqr_shift.c
opus/silk/table_LSF_cos.c
opus/silk/tables_LTP.c
opus/silk/tables_NLSF_CB_NB_MB.c
opus/silk/tables_NLSF_CB_WB.c
opus/silk/tables_gain.c
opus/silk/tables_other.c
opus/silk/tables_pitch_lag.c
opus/silk/tables_pulses_per_block.c
# Opus sources
opus/src/analysis.c
opus/src/mapping_matrix.c
opus/src/mlp.c
opus/src/mlp_data.c
opus/src/opus.c
opus/src/opus_decoder.c
opus/src/opus_encoder.c
opus/src/opus_multistream.c
opus/src/opus_multistream_decoder.c
opus/src/opus_multistream_encoder.c
opus/src/opus_projection_decoder.c
opus/src/opus_projection_encoder.c
opus/src/repacketizer.c
)
if (DEBUG)
target_sources(opus PRIVATE opus/silk/debug.c)
endif()
if (OPUS_FIXED_POINT)
target_sources(opus PRIVATE
opus/silk/fixed/LTP_analysis_filter_FIX.c
opus/silk/fixed/LTP_scale_ctrl_FIX.c
opus/silk/fixed/apply_sine_window_FIX.c
opus/silk/fixed/autocorr_FIX.c
opus/silk/fixed/burg_modified_FIX.c
opus/silk/fixed/corrMatrix_FIX.c
opus/silk/fixed/encode_frame_FIX.c
opus/silk/fixed/find_LPC_FIX.c
opus/silk/fixed/find_LTP_FIX.c
opus/silk/fixed/find_pitch_lags_FIX.c
opus/silk/fixed/find_pred_coefs_FIX.c
opus/silk/fixed/k2a_FIX.c
opus/silk/fixed/k2a_Q16_FIX.c
opus/silk/fixed/noise_shape_analysis_FIX.c
opus/silk/fixed/pitch_analysis_core_FIX.c
opus/silk/fixed/prefilter_FIX.c
opus/silk/fixed/process_gains_FIX.c
opus/silk/fixed/regularize_correlations_FIX.c
opus/silk/fixed/residual_energy16_FIX.c
opus/silk/fixed/residual_energy_FIX.c
opus/silk/fixed/schur64_FIX.c
opus/silk/fixed/schur_FIX.c
opus/silk/fixed/solve_LS_FIX.c
opus/silk/fixed/vector_ops_FIX.c
opus/silk/fixed/warped_autocorrelation_FIX.c
)
else()
target_sources(opus PRIVATE
opus/silk/float/LPC_analysis_filter_FLP.c
opus/silk/float/LPC_inv_pred_gain_FLP.c
opus/silk/float/LTP_analysis_filter_FLP.c
opus/silk/float/LTP_scale_ctrl_FLP.c
opus/silk/float/apply_sine_window_FLP.c
opus/silk/float/autocorrelation_FLP.c
opus/silk/float/burg_modified_FLP.c
opus/silk/float/bwexpander_FLP.c
opus/silk/float/corrMatrix_FLP.c
opus/silk/float/encode_frame_FLP.c
opus/silk/float/energy_FLP.c
opus/silk/float/find_LPC_FLP.c
opus/silk/float/find_LTP_FLP.c
opus/silk/float/find_pitch_lags_FLP.c
opus/silk/float/find_pred_coefs_FLP.c
opus/silk/float/inner_product_FLP.c
opus/silk/float/k2a_FLP.c
opus/silk/float/noise_shape_analysis_FLP.c
opus/silk/float/pitch_analysis_core_FLP.c
opus/silk/float/process_gains_FLP.c
opus/silk/float/regularize_correlations_FLP.c
opus/silk/float/residual_energy_FLP.c
opus/silk/float/scale_copy_vector_FLP.c
opus/silk/float/scale_vector_FLP.c
opus/silk/float/schur_FLP.c
opus/silk/float/sort_FLP.c
opus/silk/float/warped_autocorrelation_FLP.c
opus/silk/float/wrappers_FLP.c
)
endif()
target_compile_definitions(opus PRIVATE OPUS_BUILD ENABLE_HARDENING)
if(NOT MSVC)
target_compile_definitions(opus PRIVATE _FORTIFY_SOURCE=2)
endif()
# It is strongly recommended to uncomment one of these VAR_ARRAYS: Use C99
# variable-length arrays for stack allocation USE_ALLOCA: Use alloca() for stack
# allocation If none is defined, then the fallback is a non-threadsafe global
# array
if(OPUS_USE_ALLOCA OR MSVC)
target_compile_definitions(opus PRIVATE USE_ALLOCA)
else()
target_compile_definitions(opus PRIVATE VAR_ARRAYS)
endif()
if(OPUS_CUSTOM_MODES)
target_compile_definitions(opus PRIVATE CUSTOM_MODES)
endif()
if(NOT OPUS_ENABLE_FLOAT_API)
target_compile_definitions(opus PRIVATE DISABLE_FLOAT_API)
endif()
target_compile_definitions(opus
PUBLIC
-DOPUS_VERSION="\\"1.3.1\\""
PRIVATE
# Use C99 intrinsics to speed up float-to-int conversion
HAVE_LRINTF
)
if (FIXED_POINT)
target_compile_definitions(opus PRIVATE -DFIXED_POINT=1 -DDISABLE_FLOAT_API)
endif()
target_include_directories(opus
PUBLIC
opus/include
PRIVATE
opus/celt
opus/silk
opus/silk/fixed
opus/silk/float
opus/src
)
Submodule externals/opus/opus deleted from ad8fe90db7.
View File
File renamed without changes.
-81
View File
@@ -1,81 +0,0 @@
project(zlib C)
include(CheckTypeSize)
include(CheckFunctionExists)
include(CheckIncludeFile)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stddef.h HAVE_STDDEF_H)
# Check to see if we have large file support
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
# We add these other definitions here because CheckTypeSize.cmake
# in CMake 2.4.x does not automatically do so and we want
# compatibility with CMake 2.4.x.
if(HAVE_SYS_TYPES_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
endif()
if(HAVE_STDINT_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
endif()
if(HAVE_STDDEF_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
endif()
check_type_size(off64_t OFF64_T)
if(HAVE_OFF64_T)
add_definitions(-D_LARGEFILE64_SOURCE=1)
endif()
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
# Check for fseeko
check_function_exists(fseeko HAVE_FSEEKO)
if(NOT HAVE_FSEEKO)
add_definitions(-DNO_FSEEKO)
endif()
# Check for unistd.h
check_include_file(unistd.h HAVE_UNISTD_H)
if(HAVE_UNISTD_H)
add_definitions(-DHAVE_UNISTD_H)
endif()
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
endif()
add_library(z STATIC
zlib/adler32.c
zlib/compress.c
zlib/crc32.c
zlib/crc32.h
zlib/deflate.c
zlib/deflate.h
zlib/gzclose.c
zlib/gzguts.h
zlib/gzlib.c
zlib/gzread.c
zlib/gzwrite.c
zlib/inffast.h
zlib/inffixed.h
zlib/inflate.c
zlib/inflate.h
zlib/infback.c
zlib/inftrees.c
zlib/inftrees.h
zlib/inffast.c
zlib/trees.c
zlib/trees.h
zlib/uncompr.c
zlib/zconf.h
zlib/zlib.h
zlib/zutil.c
zlib/zutil.h
)
add_library(ZLIB::ZLIB ALIAS z)
target_include_directories(z
PUBLIC
zlib/
)
+11 -2
View File
@@ -3,8 +3,17 @@
# could affect the result, but much more unlikely than the following files. Keeping a list of files
# like this allows for much better caching since it doesn't force the user to recompile binary shaders every update
set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core")
if (DEFINED ENV{AZURECIREPO})
set(BUILD_REPOSITORY $ENV{AZURECIREPO})
if (DEFINED ENV{CI})
if (DEFINED ENV{TRAVIS})
set(BUILD_REPOSITORY $ENV{TRAVIS_REPO_SLUG})
set(BUILD_TAG $ENV{TRAVIS_TAG})
elseif(DEFINED ENV{APPVEYOR})
set(BUILD_REPOSITORY $ENV{APPVEYOR_REPO_NAME})
set(BUILD_TAG $ENV{APPVEYOR_REPO_TAG_NAME})
elseif(DEFINED ENV{AZURE})
set(BUILD_REPOSITORY $ENV{AZURE_REPO_NAME})
set(BUILD_TAG $ENV{AZURE_REPO_TAG})
endif()
endif()
if (DEFINED ENV{TITLEBARFORMATIDLE})
set(TITLE_BAR_FORMAT_IDLE $ENV{TITLEBARFORMATIDLE})
+2 -9
View File
@@ -36,13 +36,6 @@
#include "common/common_funcs.h"
#include "common/swap.h"
// Inlining
#ifdef _WIN32
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE inline __attribute__((always_inline))
#endif
/*
* Abstract bitfield class
*
@@ -175,11 +168,11 @@ public:
constexpr BitField(BitField&&) noexcept = default;
constexpr BitField& operator=(BitField&&) noexcept = default;
constexpr operator T() const {
constexpr FORCE_INLINE operator T() const {
return Value();
}
constexpr void Assign(const T& value) {
constexpr FORCE_INLINE void Assign(const T& value) {
storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value);
}
+12 -10
View File
@@ -1,11 +1,10 @@
// Copyright 2019 yuzu emulator team
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <algorithm>
#include <array>
#include <string>
#if !defined(ARCHITECTURE_x86_64)
@@ -17,15 +16,18 @@
#define CONCAT2(x, y) DO_CONCAT2(x, y)
#define DO_CONCAT2(x, y) x##y
/// Helper macros to insert unused bytes or words to properly align structs. These values will be
/// zero-initialized.
#define INSERT_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__){};
#define INSERT_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__){};
// helper macro to properly align structure members.
// Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121",
// depending on the current source line to make sure variable names are unique.
#define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)]
#define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)]
/// These are similar to the INSERT_PADDING_* macros, but are needed for padding unions. This is
/// because unions can only be initialized by one member.
#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__);
#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__);
// Inlining
#ifdef _WIN32
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE inline __attribute__((always_inline))
#endif
#ifndef _MSC_VER
+2
View File
@@ -108,6 +108,8 @@ add_library(core STATIC
file_sys/vfs_offset.h
file_sys/vfs_real.cpp
file_sys/vfs_real.h
file_sys/vfs_ro_layer.cpp
file_sys/vfs_ro_layer.h
file_sys/vfs_static.h
file_sys/vfs_types.h
file_sys/vfs_vector.cpp
+11 -28
View File
@@ -32,28 +32,11 @@ enum class NCASectionFilesystemType : u8 {
ROMFS = 0x3,
};
struct IVFCLevel {
u64_le offset;
u64_le size;
u32_le block_size;
u32_le reserved;
};
static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
struct IVFCHeader {
u32_le magic;
u32_le magic_number;
INSERT_UNION_PADDING_BYTES(8);
std::array<IVFCLevel, 6> levels;
INSERT_UNION_PADDING_BYTES(64);
};
static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
struct NCASectionHeaderBlock {
INSERT_UNION_PADDING_BYTES(3);
INSERT_PADDING_BYTES(3);
NCASectionFilesystemType filesystem_type;
NCASectionCryptoType crypto_type;
INSERT_UNION_PADDING_BYTES(3);
INSERT_PADDING_BYTES(3);
};
static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size.");
@@ -61,7 +44,7 @@ struct NCASectionRaw {
NCASectionHeaderBlock header;
std::array<u8, 0x138> block_data;
std::array<u8, 0x8> section_ctr;
INSERT_UNION_PADDING_BYTES(0xB8);
INSERT_PADDING_BYTES(0xB8);
};
static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size.");
@@ -69,19 +52,19 @@ struct PFS0Superblock {
NCASectionHeaderBlock header_block;
std::array<u8, 0x20> hash;
u32_le size;
INSERT_UNION_PADDING_BYTES(4);
INSERT_PADDING_BYTES(4);
u64_le hash_table_offset;
u64_le hash_table_size;
u64_le pfs0_header_offset;
u64_le pfs0_size;
INSERT_UNION_PADDING_BYTES(0x1B0);
INSERT_PADDING_BYTES(0x1B0);
};
static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
struct RomFSSuperblock {
NCASectionHeaderBlock header_block;
IVFCHeader ivfc;
INSERT_UNION_PADDING_BYTES(0x118);
INSERT_PADDING_BYTES(0x118);
};
static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size.");
@@ -89,24 +72,24 @@ struct BKTRHeader {
u64_le offset;
u64_le size;
u32_le magic;
INSERT_UNION_PADDING_BYTES(0x4);
INSERT_PADDING_BYTES(0x4);
u32_le number_entries;
INSERT_UNION_PADDING_BYTES(0x4);
INSERT_PADDING_BYTES(0x4);
};
static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size.");
struct BKTRSuperblock {
NCASectionHeaderBlock header_block;
IVFCHeader ivfc;
INSERT_UNION_PADDING_BYTES(0x18);
INSERT_PADDING_BYTES(0x18);
BKTRHeader relocation;
BKTRHeader subsection;
INSERT_UNION_PADDING_BYTES(0xC0);
INSERT_PADDING_BYTES(0xC0);
};
static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size.");
union NCASectionHeader {
NCASectionRaw raw{};
NCASectionRaw raw;
PFS0Superblock pfs0;
RomFSSuperblock romfs;
BKTRSuperblock bktr;
+19
View File
@@ -13,6 +13,25 @@
namespace FileSys {
struct RomFSHeader;
struct IVFCLevel {
u64_le offset;
u64_le size;
u32_le block_size;
u32_le reserved;
};
static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
struct IVFCHeader {
u32_le magic;
u32_le magic_number;
INSERT_PADDING_BYTES(8);
std::array<IVFCLevel, 6> levels;
INSERT_PADDING_BYTES(64);
};
static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
enum class RomFSExtractionType {
Full, // Includes data directory
Truncated, // Traverses into data directory
+4 -3
View File
@@ -55,9 +55,10 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
}
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
return desc.type == SaveDataType::CacheStorage ///< Cache Saves
|| desc.type == SaveDataType::TemporaryStorage ///< Temp Saves
|| (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
}
} // Anonymous namespace
+181
View File
@@ -0,0 +1,181 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/file_sys/vfs_ro_layer.h"
namespace FileSys {
ReadOnlyVfsFileLayer::ReadOnlyVfsFileLayer(VirtualFile base) : base(std::move(base)) {}
ReadOnlyVfsFileLayer::~ReadOnlyVfsFileLayer() = default;
std::string ReadOnlyVfsFileLayer::GetName() const {
return base->GetName();
}
std::size_t ReadOnlyVfsFileLayer::GetSize() const {
return base->GetSize();
}
bool ReadOnlyVfsFileLayer::Resize(std::size_t new_size) {
return false;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsFileLayer::GetContainingDirectory() const {
// Make containing read-only to prevent escaping the layer by getting containing and then
// getting this file again.
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetContainingDirectory());
}
bool ReadOnlyVfsFileLayer::IsWritable() const {
return false;
}
bool ReadOnlyVfsFileLayer::IsReadable() const {
return base->IsReadable();
}
std::size_t ReadOnlyVfsFileLayer::Read(u8* data, std::size_t length, std::size_t offset) const {
return base->Read(data, length, offset);
}
std::size_t ReadOnlyVfsFileLayer::Write(const u8* data, std::size_t length, std::size_t offset) {
return 0;
}
bool ReadOnlyVfsFileLayer::Rename(std::string_view name) {
return false;
}
std::string ReadOnlyVfsFileLayer::GetFullPath() const {
return base->GetFullPath();
}
ReadOnlyVfsDirectoryLayer::ReadOnlyVfsDirectoryLayer(VirtualDir base) : base(std::move(base)) {}
ReadOnlyVfsDirectoryLayer::~ReadOnlyVfsDirectoryLayer() = default;
std::vector<std::shared_ptr<VfsFile>> ReadOnlyVfsDirectoryLayer::GetFiles() const {
std::vector<VirtualFile> out;
const auto in = base->GetFiles();
std::transform(in.begin(), in.end(), std::back_inserter(out),
[](const VirtualFile& i) { return std::make_shared<ReadOnlyVfsFileLayer>(i); });
return out;
}
std::vector<std::shared_ptr<VfsDirectory>> ReadOnlyVfsDirectoryLayer::GetSubdirectories() const {
std::vector<VirtualDir> out;
const auto in = base->GetSubdirectories();
std::transform(in.begin(), in.end(), std::back_inserter(out), [](const VirtualDir& i) {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(i);
});
return out;
}
std::string ReadOnlyVfsDirectoryLayer::GetName() const {
return base->GetName();
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetParentDirectory() const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetParentDirectory());
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFileRelative(std::string_view path) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFileRelative(path));
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFileAbsolute(std::string_view path) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFileAbsolute(path));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetDirectoryRelative(
std::string_view path) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetDirectoryRelative(path));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetDirectoryAbsolute(
std::string_view path) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetDirectoryAbsolute(path));
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFile(std::string_view name) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFile(name));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetSubdirectory(
std::string_view name) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetSubdirectory(name));
}
bool ReadOnlyVfsDirectoryLayer::IsRoot() const {
return base->IsRoot();
}
std::size_t ReadOnlyVfsDirectoryLayer::GetSize() const {
return base->GetSize();
}
bool ReadOnlyVfsDirectoryLayer::Copy(std::string_view src, std::string_view dest) {
return false;
}
std::string ReadOnlyVfsDirectoryLayer::GetFullPath() const {
return base->GetFullPath();
}
bool ReadOnlyVfsDirectoryLayer::IsWritable() const {
return false;
}
bool ReadOnlyVfsDirectoryLayer::IsReadable() const {
return base->IsReadable();
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateSubdirectory(std::string_view name) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFile(std::string_view name) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFileAbsolute(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFileRelative(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateDirectoryAbsolute(
std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateDirectoryRelative(
std::string_view path) {
return nullptr;
}
bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectory(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::CleanSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::DeleteFile(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::Rename(std::string_view name) {
return false;
}
} // namespace FileSys
+73
View File
@@ -0,0 +1,73 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/file_sys/vfs.h"
namespace FileSys {
// Class that wraps a VfsFile making it read-only
class ReadOnlyVfsFileLayer : public VfsFile {
public:
explicit ReadOnlyVfsFileLayer(VirtualFile base);
~ReadOnlyVfsFileLayer() override;
std::string GetName() const override;
std::size_t GetSize() const override;
bool Resize(std::size_t new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
bool IsWritable() const override;
bool IsReadable() const override;
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
bool Rename(std::string_view name) override;
std::string GetFullPath() const override;
private:
VirtualFile base;
};
// Class that wraps a VfsDirectory making it and its children read only.
class ReadOnlyVfsDirectoryLayer : public ReadOnlyVfsDirectory {
public:
explicit ReadOnlyVfsDirectoryLayer(VirtualDir base);
~ReadOnlyVfsDirectoryLayer() override;
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
std::string GetName() const override;
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const override;
std::shared_ptr<VfsFile> GetFileAbsolute(std::string_view path) const override;
std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const override;
std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(std::string_view path) const override;
std::shared_ptr<VfsFile> GetFile(std::string_view name) const override;
std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const override;
bool IsRoot() const override;
std::size_t GetSize() const override;
bool Copy(std::string_view src, std::string_view dest) override;
std::string GetFullPath() const override;
bool IsWritable() const override;
bool IsReadable() const override;
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path) override;
std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path) override;
bool DeleteSubdirectory(std::string_view name) override;
bool DeleteSubdirectoryRecursive(std::string_view name) override;
bool CleanSubdirectoryRecursive(std::string_view name) override;
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
private:
VirtualDir base;
};
} // namespace FileSys
+2 -4
View File
@@ -160,7 +160,7 @@ struct DomainMessageHeader {
// Used when responding to an IPC request, Server -> Client.
struct {
u32_le num_objects;
INSERT_UNION_PADDING_WORDS(3);
INSERT_PADDING_WORDS(3);
};
// Used when performing an IPC request, Client -> Server.
@@ -171,10 +171,8 @@ struct DomainMessageHeader {
BitField<16, 16, u32> size;
};
u32_le object_id;
INSERT_UNION_PADDING_WORDS(2);
INSERT_PADDING_WORDS(2);
};
std::array<u32, 4> raw{};
};
};
static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect");
+2 -1
View File
@@ -58,7 +58,8 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
auto& kernel = Core::System::GetInstance().Kernel();
if (!writable_event) {
// Create event if not provided
const auto pair = WritableEvent::CreateEventPair(kernel, "HLE Pause Event: " + reason);
const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic,
"HLE Pause Event: " + reason);
writable_event = pair.writable;
}
+5
View File
@@ -32,6 +32,11 @@ enum class HandleType : u32 {
ServerSession,
};
enum class ResetType {
Automatic, ///< Reset automatically on object acquisition
Manual, ///< Never reset automatically
};
class Object : NonCopyable {
public:
explicit Object(KernelCore& kernel);
+6 -4
View File
@@ -20,13 +20,15 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const {
void ReadableEvent::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
if (reset_type == ResetType::Automatic) {
signaled = false;
}
}
void ReadableEvent::Signal() {
if (!signaled) {
signaled = true;
WakeupAllWaitingThreads();
};
signaled = true;
WakeupAllWaitingThreads();
}
void ReadableEvent::Clear() {
+6 -1
View File
@@ -27,6 +27,10 @@ public:
return name;
}
ResetType GetResetType() const {
return reset_type;
}
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
@@ -51,7 +55,8 @@ private:
void Signal();
bool signaled{};
ResetType reset_type;
bool signaled;
std::string name; ///< Name of event (optional)
};
+43 -12
View File
@@ -22,9 +22,9 @@
namespace Kernel {
GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {}
GlobalScheduler::~GlobalScheduler() = default;
GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {
is_reselection_pending = false;
}
void GlobalScheduler::AddThread(SharedPtr<Thread> thread) {
thread_list.push_back(std::move(thread));
@@ -35,11 +35,24 @@ void GlobalScheduler::RemoveThread(const Thread* thread) {
thread_list.end());
}
/*
* UnloadThread selects a core and forces it to unload its current thread's context
*/
void GlobalScheduler::UnloadThread(s32 core) {
Scheduler& sched = system.Scheduler(core);
sched.UnloadThread();
}
/*
* SelectThread takes care of selecting the new scheduled thread.
* It does it in 3 steps:
* - First a thread is selected from the top of the priority queue. If no thread
* is obtained then we move to step two, else we are done.
* - Second we try to get a suggested thread that's not assigned to any core or
* that is not the top thread in that core.
* - Third is no suggested thread is found, we do a second pass and pick a running
* thread in another core and swap it with its current thread.
*/
void GlobalScheduler::SelectThread(u32 core) {
const auto update_thread = [](Thread* thread, Scheduler& sched) {
if (thread != sched.selected_thread) {
@@ -101,19 +114,30 @@ void GlobalScheduler::SelectThread(u32 core) {
update_thread(current_thread, sched);
}
/*
* YieldThread takes a thread and moves it to the back of the it's priority list
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool GlobalScheduler::YieldThread(Thread* yielding_thread) {
// Note: caller should use critical section, etc.
const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID());
const u32 priority = yielding_thread->GetPriority();
// Yield the thread
const Thread* const winner = scheduled_queue[core_id].front(priority);
ASSERT_MSG(yielding_thread == winner, "Thread yielding without being in front");
ASSERT_MSG(yielding_thread == scheduled_queue[core_id].front(priority),
"Thread yielding without being in front");
scheduled_queue[core_id].yield(priority);
Thread* winner = scheduled_queue[core_id].front(priority);
return AskForReselectionOrMarkRedundant(yielding_thread, winner);
}
/*
* YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list.
* Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
* a better priority than the next thread in the core.
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
// Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
// etc.
@@ -165,6 +189,12 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
return AskForReselectionOrMarkRedundant(yielding_thread, winner);
}
/*
* YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue
* and into the suggested queue. If no thread can be squeduled afterwards in that core,
* a suggested thread is obtained instead.
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread) {
// Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
// etc.
@@ -250,7 +280,7 @@ void GlobalScheduler::PreemptThreads() {
if (winner->IsRunning()) {
UnloadThread(winner->GetProcessorID());
}
TransferToCore(winner->GetPriority(), s32(core_id), winner);
TransferToCore(winner->GetPriority(), core_id, winner);
current_thread =
winner->GetPriority() <= current_thread->GetPriority() ? winner : current_thread;
}
@@ -283,7 +313,7 @@ void GlobalScheduler::PreemptThreads() {
if (winner->IsRunning()) {
UnloadThread(winner->GetProcessorID());
}
TransferToCore(winner->GetPriority(), s32(core_id), winner);
TransferToCore(winner->GetPriority(), core_id, winner);
current_thread = winner;
}
}
@@ -301,12 +331,12 @@ void GlobalScheduler::Unsuggest(u32 priority, u32 core, Thread* thread) {
}
void GlobalScheduler::Schedule(u32 priority, u32 core, Thread* thread) {
ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core.");
scheduled_queue[core].add(thread, priority);
}
void GlobalScheduler::SchedulePrepend(u32 priority, u32 core, Thread* thread) {
ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core.");
scheduled_queue[core].add(thread, priority, false);
}
@@ -338,8 +368,7 @@ void GlobalScheduler::TransferToCore(u32 priority, s32 destination_core, Thread*
}
}
bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread,
const Thread* winner) {
bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner) {
if (current_thread == winner) {
current_thread->IncrementYieldCount();
return true;
@@ -357,6 +386,8 @@ void GlobalScheduler::Shutdown() {
thread_list.clear();
}
GlobalScheduler::~GlobalScheduler() = default;
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id)
: system(system), cpu_core(cpu_core), core_id(core_id) {}
@@ -439,7 +470,7 @@ void Scheduler::SwitchContext() {
// Load context of new thread
if (new_thread) {
ASSERT_MSG(new_thread->GetProcessorID() == s32(this->core_id),
ASSERT_MSG(new_thread->GetProcessorID() == this->core_id,
"Thread must be assigned to this core.");
ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready,
"Thread must be ready to become running.");
+48 -61
View File
@@ -26,7 +26,6 @@ public:
explicit GlobalScheduler(Core::System& system);
~GlobalScheduler();
/// Adds a new thread to the scheduler
void AddThread(SharedPtr<Thread> thread);
@@ -38,57 +37,47 @@ public:
return thread_list;
}
/**
* Add a thread to the suggested queue of a cpu core. Suggested threads may be
* picked if no thread is scheduled to run on the core.
*/
// Add a thread to the suggested queue of a cpu core. Suggested threads may be
// picked if no thread is scheduled to run on the core.
void Suggest(u32 priority, u32 core, Thread* thread);
/**
* Remove a thread to the suggested queue of a cpu core. Suggested threads may be
* picked if no thread is scheduled to run on the core.
*/
// Remove a thread to the suggested queue of a cpu core. Suggested threads may be
// picked if no thread is scheduled to run on the core.
void Unsuggest(u32 priority, u32 core, Thread* thread);
/**
* Add a thread to the scheduling queue of a cpu core. The thread is added at the
* back the queue in its priority level.
*/
// Add a thread to the scheduling queue of a cpu core. The thread is added at the
// back the queue in its priority level
void Schedule(u32 priority, u32 core, Thread* thread);
/**
* Add a thread to the scheduling queue of a cpu core. The thread is added at the
* front the queue in its priority level.
*/
// Add a thread to the scheduling queue of a cpu core. The thread is added at the
// front the queue in its priority level
void SchedulePrepend(u32 priority, u32 core, Thread* thread);
/// Reschedule an already scheduled thread based on a new priority
// Reschedule an already scheduled thread based on a new priority
void Reschedule(u32 priority, u32 core, Thread* thread);
/// Unschedules a thread.
// Unschedule a thread.
void Unschedule(u32 priority, u32 core, Thread* thread);
/**
* Transfers a thread into an specific core. If the destination_core is -1
* it will be unscheduled from its source code and added into its suggested
* queue.
*/
// Transfers a thread into an specific core. If the destination_core is -1
// it will be unscheduled from its source code and added into its suggested
// queue.
void TransferToCore(u32 priority, s32 destination_core, Thread* thread);
/// Selects a core and forces it to unload its current thread's context
/*
* UnloadThread selects a core and forces it to unload its current thread's context
*/
void UnloadThread(s32 core);
/**
* Takes care of selecting the new scheduled thread in three steps:
*
* 1. First a thread is selected from the top of the priority queue. If no thread
* is obtained then we move to step two, else we are done.
*
* 2. Second we try to get a suggested thread that's not assigned to any core or
* that is not the top thread in that core.
*
* 3. Third is no suggested thread is found, we do a second pass and pick a running
* thread in another core and swap it with its current thread.
/*
* SelectThread takes care of selecting the new scheduled thread.
* It does it in 3 steps:
* - First a thread is selected from the top of the priority queue. If no thread
* is obtained then we move to step two, else we are done.
* - Second we try to get a suggested thread that's not assigned to any core or
* that is not the top thread in that core.
* - Third is no suggested thread is found, we do a second pass and pick a running
* thread in another core and swap it with its current thread.
*/
void SelectThread(u32 core);
@@ -96,37 +85,33 @@ public:
return !scheduled_queue[core_id].empty();
}
/**
* Takes a thread and moves it to the back of the it's priority list.
*
* @note This operation can be redundant and no scheduling is changed if marked as so.
/*
* YieldThread takes a thread and moves it to the back of the it's priority list
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThread(Thread* thread);
/**
* Takes a thread and moves it to the back of the it's priority list.
/*
* YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list.
* Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
* a better priority than the next thread in the core.
*
* @note This operation can be redundant and no scheduling is changed if marked as so.
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThreadAndBalanceLoad(Thread* thread);
/**
* Takes a thread and moves it out of the scheduling queue.
* and into the suggested queue. If no thread can be scheduled afterwards in that core,
/*
* YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue
* and into the suggested queue. If no thread can be squeduled afterwards in that core,
* a suggested thread is obtained instead.
*
* @note This operation can be redundant and no scheduling is changed if marked as so.
* This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThreadAndWaitForLoadBalancing(Thread* thread);
/**
* Rotates the scheduling queues of threads at a preemption priority and then does
* some core rebalancing. Preemption priorities can be found in the array
* 'preemption_priorities'.
*
* @note This operation happens every 10ms.
/*
* PreemptThreads this operation rotates the scheduling queues of threads at
* a preemption priority and then does some core rebalancing. Preemption priorities
* can be found in the array 'preemption_priorities'. This operation happens
* every 10ms.
*/
void PreemptThreads();
@@ -145,15 +130,15 @@ public:
void Shutdown();
private:
bool AskForReselectionOrMarkRedundant(Thread* current_thread, const Thread* winner);
bool AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner);
static constexpr u32 min_regular_priority = 2;
std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> scheduled_queue;
std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> suggested_queue;
std::atomic<bool> is_reselection_pending{false};
std::atomic<bool> is_reselection_pending;
// The priority levels at which the global scheduler preempts threads every 10 ms. They are
// ordered from Core 0 to Core 3.
// `preemption_priorities` are the priority levels at which the global scheduler
// preempts threads every 10 ms. They are ordered from Core 0 to Core 3
std::array<u32, NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
/// Lists all thread ids that aren't deleted/etc.
@@ -196,8 +181,10 @@ public:
private:
friend class GlobalScheduler;
/// Switches the CPU's active thread context to that of the specified thread
/**
* Switches the CPU's active thread context to that of the specified thread
* @param new_thread The thread to switch to
*/
void SwitchContext();
/**
+1 -1
View File
@@ -2102,7 +2102,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle
auto& kernel = system.Kernel();
const auto [readable_event, writable_event] =
WritableEvent::CreateEventPair(kernel, "CreateEvent");
WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent");
HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
+7 -1
View File
@@ -15,7 +15,8 @@ namespace Kernel {
WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
WritableEvent::~WritableEvent() = default;
EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type,
std::string name) {
SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel));
SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel));
@@ -23,6 +24,7 @@ EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
writable_event->readable = readable_event;
readable_event->name = name + ":Readable";
readable_event->signaled = false;
readable_event->reset_type = reset_type;
return {std::move(readable_event), std::move(writable_event)};
}
@@ -31,6 +33,10 @@ SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const {
return readable;
}
ResetType WritableEvent::GetResetType() const {
return readable->reset_type;
}
void WritableEvent::Signal() {
readable->Signal();
}
+5 -1
View File
@@ -24,9 +24,11 @@ public:
/**
* Creates an event
* @param kernel The kernel instance to create this event under.
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
static EventPair CreateEventPair(KernelCore& kernel, ResetType reset_type,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "WritableEvent";
@@ -42,6 +44,8 @@ public:
SharedPtr<ReadableEvent> GetReadableEvent() const;
ResetType GetResetType() const;
void Signal();
void Clear();
bool IsSignaled() const;
+11 -36
View File
@@ -289,8 +289,8 @@ ISelfController::ISelfController(Core::System& system,
RegisterHandlers(functions);
auto& kernel = system.Kernel();
launchable_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent");
launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"ISelfController:LaunchableEvent");
// This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
// called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
@@ -298,7 +298,7 @@ ISelfController::ISelfController(Core::System& system,
// suspended if the event has previously been created by a call to
// GetAccumulatedSuspendedTickChangedEvent.
accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
kernel, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent");
accumulated_suspended_tick_changed_event.writable->Signal();
}
@@ -523,10 +523,10 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
}
AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
on_new_message =
Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageRecieved");
on_operation_mode_changed =
Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged");
on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"AMMessageQueue:OnMessageRecieved");
on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged");
}
AppletMessageQueue::~AppletMessageQueue() = default;
@@ -1072,9 +1072,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{71, nullptr, "RequestToReboot"},
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
{90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
{100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
{101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
{102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
{100, nullptr, "InitializeApplicationCopyrightFrameBuffer"},
{101, nullptr, "SetApplicationCopyrightImage"},
{102, nullptr, "SetApplicationCopyrightVisibility"},
{110, nullptr, "QueryApplicationPlayStatistics"},
{120, nullptr, "ExecuteProgram"},
{121, nullptr, "ClearUserChannel"},
@@ -1090,7 +1090,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
auto& kernel = system.Kernel();
gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
kernel, Kernel::ResetType::Manual, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
}
IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1102,31 +1102,6 @@ void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestConte
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_visible = rp.Pop<bool>();
LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
-3
View File
@@ -252,9 +252,6 @@ private:
void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
void EndBlockingHomeButton(Kernel::HLERequestContext& ctx);
void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
void InitializeApplicationCopyrightFrameBuffer(Kernel::HLERequestContext& ctx);
void SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx);
void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
+5 -7
View File
@@ -24,12 +24,12 @@
namespace Service::AM::Applets {
AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
state_changed_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
state_changed_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "ILibraryAppletAccessor:PopDataOutEvent");
pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
kernel, Kernel::ResetType::Automatic, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
}
AppletDataBroker::~AppletDataBroker() = default;
@@ -88,7 +88,6 @@ std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() {
void AppletDataBroker::PushNormalDataFromGame(IStorage storage) {
in_channel.push_back(std::make_unique<IStorage>(storage));
pop_out_data_event.writable->Clear();
}
void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) {
@@ -98,7 +97,6 @@ void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) {
void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
in_interactive_channel.push_back(std::make_unique<IStorage>(storage));
pop_interactive_out_data_event.writable->Clear();
}
void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) {
+5 -6
View File
@@ -20,9 +20,9 @@ namespace Service::AM::Applets {
struct ShowError {
u8 mode;
bool jump;
INSERT_UNION_PADDING_BYTES(4);
INSERT_PADDING_BYTES(4);
bool use_64bit_error_code;
INSERT_UNION_PADDING_BYTES(1);
INSERT_PADDING_BYTES(1);
u64 error_code_64;
u32 error_code_32;
};
@@ -32,7 +32,7 @@ static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
struct ShowErrorRecord {
u8 mode;
bool jump;
INSERT_UNION_PADDING_BYTES(6);
INSERT_PADDING_BYTES(6);
u64 error_code_64;
u64 posix_time;
};
@@ -41,7 +41,7 @@ static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect si
struct SystemErrorArg {
u8 mode;
bool jump;
INSERT_UNION_PADDING_BYTES(6);
INSERT_PADDING_BYTES(6);
u64 error_code_64;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
@@ -52,7 +52,7 @@ static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect si
struct ApplicationErrorArg {
u8 mode;
bool jump;
INSERT_UNION_PADDING_BYTES(6);
INSERT_PADDING_BYTES(6);
u32 error_code;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
@@ -65,7 +65,6 @@ union Error::ErrorArguments {
ShowErrorRecord error_record;
SystemErrorArg system_error;
ApplicationErrorArg application_error;
std::array<u8, 0x1018> raw{};
};
namespace {
+2 -2
View File
@@ -67,8 +67,8 @@ AOC_U::AOC_U(Core::System& system)
RegisterHandlers(functions);
auto& kernel = system.Kernel();
aoc_change_event =
Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event");
aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"GetAddOnContentListChanged:Event");
}
AOC_U::~AOC_U() = default;
+2 -2
View File
@@ -65,8 +65,8 @@ public:
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
buffer_event =
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased");
buffer_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), Kernel::ResetType::Manual, "IAudioOutBufferReleased");
stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
audio_params.channel_count, std::move(unique_name),
+6 -6
View File
@@ -47,8 +47,8 @@ public:
// clang-format on
RegisterHandlers(functions);
system_event =
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
system_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent");
renderer = std::make_unique<AudioCore::AudioRenderer>(
system.CoreTiming(), audren_params, system_event.writable, instance_number);
}
@@ -180,17 +180,17 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
buffer_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent");
buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IAudioOutBufferReleasedEvent");
// Should be similar to audio_output_device_switch_event
audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
kernel, Kernel::ResetType::Automatic, "IAudioDevice:AudioInputDeviceSwitchedEvent");
// Should only be signalled when an audio output device has been changed, example: speaker
// to headset
audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
kernel, Kernel::ResetType::Automatic, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
}
private:
@@ -13,7 +13,8 @@ namespace Service::BCAT {
ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
std::string_view event_name) {
event = Kernel::WritableEvent::CreateEventPair(
kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
kernel, Kernel::ResetType::Automatic,
std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
}
Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const {
+2 -1
View File
@@ -34,7 +34,8 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent");
register_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent");
}
private:
+8 -6
View File
@@ -57,12 +57,14 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent");
connection_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent");
service_discovery =
Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery");
config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent");
scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IBtmUserCore:ScanEvent");
connection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConnectionEvent");
service_discovery = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "IBtmUserCore:Discovery");
config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IBtmUserCore:ConfigEvent");
}
private:
@@ -725,8 +725,7 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
void InstallInterfaces(Core::System& system) {
std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager());
std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager());
std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter())
->InstallAsService(system.ServiceManager());
std::make_shared<FSP_SRV>(system)->InstallAsService(system.ServiceManager());
}
} // namespace Service::FileSystem
+345 -37
View File
@@ -14,17 +14,22 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/directory.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/system_archive/system_archive.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_ro_layer.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
#include "core/reporter.h"
@@ -54,6 +59,12 @@ enum class FileSystemType : u8 {
ApplicationPackage = 7,
};
enum class SaveDataOpenMode {
Normal,
ReadOnly,
System,
};
class IStorage final : public ServiceFramework<IStorage> {
public:
explicit IStorage(FileSys::VirtualFile backend_)
@@ -503,14 +514,17 @@ private:
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
public:
explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space, FileSystemController& fsc)
explicit ISaveDataInfoReader(FileSystemController& fsc,
std::vector<FileSys::SaveDataSpaceId> spaces)
: ServiceFramework("ISaveDataInfoReader"), fsc(fsc) {
static const FunctionInfo functions[] = {
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
};
RegisterHandlers(functions);
FindAllSaves(space);
for (const auto& space : spaces) {
FindAllSaves(space);
}
}
void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) {
@@ -650,8 +664,31 @@ private:
u64 next_entry_index = 0;
};
FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
: ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) {
class IEventNotifier final : public ServiceFramework<IEventNotifier> {
public:
explicit IEventNotifier(Kernel::SharedPtr<Kernel::ReadableEvent> event)
: ServiceFramework{"IEventNotifier"}, event(std::move(event)) {
static const FunctionInfo functions[] = {
{0, &IEventNotifier::GetEventHandle, "GetEventHandle"},
};
RegisterHandlers(functions);
}
private:
void GetEventHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
}
Kernel::SharedPtr<Kernel::ReadableEvent> event;
};
FSP_SRV::FSP_SRV(Core::System& system)
: ServiceFramework("fsp-srv"), system(system), fsc(system.GetFileSystemController()) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFileSystem"},
@@ -660,15 +697,15 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"},
{8, nullptr, "OpenFileSystemWithId"},
{9, nullptr, "OpenDataFileSystemByApplicationId"},
{11, nullptr, "OpenBisFileSystem"},
{12, nullptr, "OpenBisStorage"},
{13, nullptr, "InvalidateBisCache"},
{11, &FSP_SRV::OpenBisFileSystem, "OpenBisFileSystem"},
{12, &FSP_SRV::OpenBisStorage, "OpenBisStorage"},
{13, &FSP_SRV::InvalidateBisCache, "InvalidateBisCache"},
{17, nullptr, "OpenHostFileSystem"},
{18, &FSP_SRV::OpenSdCardFileSystem, "OpenSdCardFileSystem"},
{19, nullptr, "FormatSdCardFileSystem"},
{21, nullptr, "DeleteSaveDataFileSystem"},
{22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"},
{23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
{23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"},
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"},
@@ -681,12 +718,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{34, nullptr, "GetCacheStorageSize"},
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
{51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
{52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
{52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"},
{53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"},
{57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
{58, nullptr, "ReadSaveDataFileSystemExtraData"},
{59, nullptr, "WriteSaveDataFileSystemExtraData"},
{60, nullptr, "OpenSaveDataInfoReader"},
{60, &FSP_SRV::OpenSaveDataInfoReader, "OpenSaveDataInfoReader"},
{61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"},
{62, nullptr, "OpenCacheStorageList"},
{64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
@@ -699,8 +736,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{82, nullptr, "OpenSaveDataTransferManagerVersion2"},
{83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"},
{84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"},
{100, nullptr, "OpenImageDirectoryFileSystem"},
{110, nullptr, "OpenContentStorageFileSystem"},
{100, &FSP_SRV::OpenImageDirectoryFileSystem, "OpenImageDirectoryFileSystem"},
{110, &FSP_SRV::OpenContentStorageFileSystem, "OpenContentStorageFileSystem"},
{120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
{130, nullptr, "OpenCustomStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
@@ -710,8 +747,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, nullptr, "OpenDataStorageByProgramIndex"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
{500, &FSP_SRV::OpenSdCardDetectionEventNotifier, "OpenSdCardDetectionEventNotifier"},
{501, &FSP_SRV::OpenGameCardDetectionEventNotifier, "OpenGameCardDetectionEventNotifier"},
{510, nullptr, "OpenSystemDataUpdateEventNotifier"},
{511, nullptr, "NotifySystemDataUpdateEvent"},
{520, nullptr, "SimulateGameCardDetectionEvent"},
@@ -733,7 +770,7 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
{616, nullptr, "GetSaveDataCommitId"},
{617, nullptr, "UnregisterExternalKey"},
{620, nullptr, "SetSdCardEncryptionSeed"},
{620, &FSP_SRV::SetSdCardEncryptionSeed, "SetSdCardEncryptionSeed"},
{630, nullptr, "SetSdCardAccessibility"},
{631, nullptr, "IsSdCardAccessible"},
{640, nullptr, "IsSignedSystemPartitionOnSdCardValid"},
@@ -762,6 +799,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
};
// clang-format on
RegisterHandlers(functions);
auto& kernel{system.Kernel()};
sd_card_detection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "fsp-srv:SdCardDetectionEvent");
game_card_detection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "fsp-srv:GameCardDetectionEvent");
}
FSP_SRV::~FSP_SRV() = default;
@@ -781,11 +824,134 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) {
const auto type = rp.PopRaw<FileSystemType>();
const auto title_id = rp.PopRaw<u64>();
LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}",
static_cast<u8>(type), title_id);
LOG_DEBUG(Service_FS, "called with type={}, title_id={:016X}", static_cast<u8>(type), title_id);
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(ResultCode(-1));
const auto& prov{system.GetContentProvider()};
FileSys::PatchManager pm{title_id};
FileSys::ContentRecordType cr_type;
switch (type) {
case FileSystemType::ApplicationPackage:
case FileSystemType::Logo:
cr_type = FileSys::ContentRecordType::Program;
break;
case FileSystemType::ContentControl:
cr_type = FileSys::ContentRecordType::Control;
break;
case FileSystemType::ContentManual:
cr_type = FileSys::ContentRecordType::HtmlDocument;
break;
case FileSystemType::ContentMeta:
cr_type = FileSys::ContentRecordType::Meta;
break;
case FileSystemType::ContentData:
cr_type = FileSys::ContentRecordType::Data;
break;
default:
LOG_WARNING(Service_FS, "called with invalid filesystem type!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
const auto& nca{prov.GetEntry(title_id, cr_type)};
if (nca == nullptr) {
LOG_WARNING(Service_FS, "NCA requested doesn't exist in content provider!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
FileSys::VirtualDir dir;
if (type == FileSystemType::ApplicationPackage) {
dir = nca->GetExeFS();
if (dir != nullptr)
dir = pm.PatchExeFS(dir);
} else if (type == FileSystemType::Logo) {
dir = nca->GetSubdirectories()[1];
} else if (type == FileSystemType::ContentControl || type == FileSystemType::ContentManual ||
type == FileSystemType::ContentData) {
if (nca->GetRomFS() != nullptr) {
const auto romfs = pm.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), cr_type);
if (romfs != nullptr)
dir = FileSys::ExtractRomFS(romfs);
}
} else {
dir = nca->GetSubdirectories()[0];
}
if (dir == nullptr) {
LOG_WARNING(Service_FS, "couldn't get requested NCA section!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IFileSystem>(
dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host)));
}
void FSP_SRV::OpenBisFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto partition = rp.PopRaw<FileSys::BisPartitionId>();
LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast<u32>(partition));
auto dir = fsc.OpenBISPartition(partition);
if (dir.Failed()) {
LOG_ERROR(Service_FS,
"Failed to mount BIS filesystem for partition_id={:08X}! Could be invalid "
"argument or uninitialized system.",
static_cast<u32>(partition));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(dir.Code());
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
IFileSystem fs(dir.Unwrap(), SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host));
rb.PushIpcInterface<IFileSystem>(std::move(fs));
}
void FSP_SRV::OpenBisStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto partition = rp.PopRaw<FileSys::BisPartitionId>();
LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast<u32>(partition));
auto file = fsc.OpenBISPartitionStorage(partition);
if (file.Failed()) {
LOG_ERROR(Service_FS,
"Failed to mount BIS storage for partition_id={:08X}! Could be invalid "
"argument or uninitialized system.",
static_cast<u32>(partition));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(file.Code());
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
IStorage fs(file.Unwrap());
rb.PushIpcInterface<IStorage>(std::move(fs));
}
void FSP_SRV::InvalidateBisCache(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
// Exists for SDK compatibility -- We do not emulate a BIS cache.
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) {
@@ -815,44 +981,103 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_FS, "called.");
void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>();
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
const auto dir = fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandSystem, save_struct);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(dir.Code());
}
namespace {
FileSys::StorageId StorageFromSaveDataSpace(FileSys::SaveDataSpaceId space) {
switch (space) {
case FileSys::SaveDataSpaceId::NandSystem:
case FileSys::SaveDataSpaceId::ProperSystem:
case FileSys::SaveDataSpaceId::TemporaryStorage:
return FileSys::StorageId::NandSystem;
case FileSys::SaveDataSpaceId::NandUser:
return FileSys::StorageId::NandUser;
case FileSys::SaveDataSpaceId::SdCardSystem:
case FileSys::SaveDataSpaceId::SdCardUser:
return FileSys::StorageId::SdCard;
default:
return FileSys::StorageId::None;
}
}
template <SaveDataOpenMode mode>
void OpenSaveDataFileSystemGeneric(Kernel::HLERequestContext& ctx, FileSystemController& fsc) {
IPC::RequestParser rp{ctx};
struct Parameters {
FileSys::SaveDataSpaceId save_data_space_id;
FileSys::SaveDataDescriptor descriptor;
};
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
auto dir = fsc.OpenSaveData(parameters.save_data_space_id, parameters.descriptor);
if (dir.Failed()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
FileSys::StorageId id;
if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::NandUser) {
id = FileSys::StorageId::NandUser;
} else if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardSystem ||
parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardUser) {
id = FileSys::StorageId::SdCard;
} else {
id = FileSys::StorageId::NandSystem;
auto diru = dir.Unwrap();
if (diru == nullptr) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
IFileSystem filesystem(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id));
if constexpr (mode == SaveDataOpenMode::ReadOnly) {
diru = std::make_shared<FileSys::ReadOnlyVfsDirectoryLayer>(diru);
}
IFileSystem filesystem(
std::move(diru),
SizeGetter::FromStorageId(fsc, StorageFromSaveDataSpace(parameters.save_data_space_id)));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
}
} // namespace
void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::Normal>(ctx, fsc);
}
void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
OpenSaveDataFileSystem(ctx);
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::ReadOnly>(ctx, fsc);
}
void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) {
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::System>(ctx, fsc);
}
void FSP_SRV::OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISaveDataInfoReader>(
std::make_shared<ISaveDataInfoReader>(fsc, std::vector<FileSys::SaveDataSpaceId>{
FileSys::SaveDataSpaceId::NandSystem,
FileSys::SaveDataSpaceId::NandUser,
FileSys::SaveDataSpaceId::TemporaryStorage,
FileSys::SaveDataSpaceId::SdCardUser,
}));
}
void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) {
@@ -862,7 +1087,64 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space, fsc));
rb.PushIpcInterface<ISaveDataInfoReader>(
std::make_shared<ISaveDataInfoReader>(fsc, std::vector<FileSys::SaveDataSpaceId>{space}));
}
void FSP_SRV::OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage = rp.PopRaw<ImageDirectoryId>();
LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast<u32>(storage));
auto dir = fsc.GetImageDirectory(storage);
if (dir == nullptr) {
LOG_ERROR(Service_FS, "The image directory requested was invalid!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IFileSystem>(
std::move(dir), SizeGetter::FromStorageId(fsc, storage == ImageDirectoryId::NAND
? FileSys::StorageId::NandUser
: FileSys::StorageId::SdCard)));
}
void FSP_SRV::OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage = rp.PopRaw<ContentStorageId>();
LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast<u32>(storage));
auto dir = fsc.GetContentDirectory(storage);
if (dir == nullptr) {
LOG_ERROR(Service_FS, "The content storage requested was invalid!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
FileSys::StorageId storage_id = FileSys::StorageId::None;
switch (storage) {
case ContentStorageId::SdCard:
storage_id = FileSys::StorageId::SdCard;
break;
case ContentStorageId::User:
storage_id = FileSys::StorageId::NandUser;
break;
case ContentStorageId::System:
storage_id = FileSys::StorageId::NandSystem;
break;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(
std::make_shared<IFileSystem>(std::move(dir), SizeGetter::FromStorageId(fsc, storage_id)));
}
void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
@@ -961,7 +1243,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called, log='{}'", log);
reporter.SaveFilesystemAccessReport(log_mode, std::move(log));
system.GetReporter().SaveFilesystemAccessReport(log_mode, std::move(log));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -976,4 +1258,30 @@ void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) {
rb.Push(access_log_program_index);
}
void FSP_SRV::OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IEventNotifier>(sd_card_detection_event.readable));
}
void FSP_SRV::OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IEventNotifier>(game_card_detection_event.readable));
}
void FSP_SRV::SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto seed = rp.PopRaw<u128>();
LOG_INFO(Service_FS, "called with seed={:016X}{:016X}", seed[1], seed[0]);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
} // namespace Service::FileSystem
+16 -2
View File
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -32,17 +33,25 @@ enum class LogMode : u32 {
class FSP_SRV final : public ServiceFramework<FSP_SRV> {
public:
explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter);
explicit FSP_SRV(Core::System& system);
~FSP_SRV() override;
private:
void SetCurrentProcess(Kernel::HLERequestContext& ctx);
void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx);
void OpenBisFileSystem(Kernel::HLERequestContext& ctx);
void OpenBisStorage(Kernel::HLERequestContext& ctx);
void InvalidateBisCache(Kernel::HLERequestContext& ctx);
void OpenSdCardFileSystem(Kernel::HLERequestContext& ctx);
void CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx);
void CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx);
void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx);
void OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx);
void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx);
void OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx);
void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx);
void OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx);
void OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx);
void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
@@ -50,7 +59,11 @@ private:
void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx);
void OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx);
void OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx);
void SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx);
Core::System& system;
FileSystemController& fsc;
FileSys::VirtualFile romfs;
@@ -58,7 +71,8 @@ private:
u32 access_log_program_index = 0;
LogMode log_mode = LogMode::LogToSdCard;
const Core::Reporter& reporter;
Kernel::EventPair sd_card_detection_event;
Kernel::EventPair game_card_detection_event;
};
} // namespace Service::FileSystem
+1 -1
View File
@@ -162,7 +162,7 @@ public:
RegisterHandlers(functions);
notification_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), "INotificationService:NotifyEvent");
system.Kernel(), Kernel::ResetType::Manual, "INotificationService:NotifyEvent");
}
private:
+47 -19
View File
@@ -174,7 +174,7 @@ void Controller_NPad::OnInit() {
auto& kernel = system.Kernel();
for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
kernel, Kernel::ResetType::Manual, fmt::format("npad:NpadStyleSetChanged_{}", i));
}
if (!IsControllerActivated()) {
@@ -583,6 +583,36 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
return true;
}
bool Controller_NPad::IsControllerSupported(NPadControllerType controller) {
if (controller == NPadControllerType::Handheld) {
// Handheld is not even a supported type, lets stop here
if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
NPAD_HANDHELD) == supported_npad_id_types.end()) {
return false;
}
// Handheld should not be supported in docked mode
if (Settings::values.use_docked_mode) {
return false;
}
}
switch (controller) {
case NPadControllerType::ProController:
return style.pro_controller;
case NPadControllerType::Handheld:
return style.handheld;
case NPadControllerType::JoyDual:
return style.joycon_dual;
case NPadControllerType::JoyLeft:
return style.joycon_left;
case NPadControllerType::JoyRight:
return style.joycon_right;
case NPadControllerType::Pokeball:
return style.pokeball;
default:
return false;
}
}
Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
// These are controllers without led patterns
@@ -629,24 +659,25 @@ void Controller_NPad::ClearAllConnectedControllers() {
}
void Controller_NPad::DisconnectAllConnectedControllers() {
for (ControllerHolder& controller : connected_controllers) {
controller.is_connected = false;
}
std::for_each(connected_controllers.begin(), connected_controllers.end(),
[](ControllerHolder& controller) { controller.is_connected = false; });
}
void Controller_NPad::ConnectAllDisconnectedControllers() {
for (ControllerHolder& controller : connected_controllers) {
if (controller.type != NPadControllerType::None && !controller.is_connected) {
controller.is_connected = true;
}
}
std::for_each(connected_controllers.begin(), connected_controllers.end(),
[](ControllerHolder& controller) {
if (controller.type != NPadControllerType::None && !controller.is_connected) {
controller.is_connected = false;
}
});
}
void Controller_NPad::ClearAllControllers() {
for (ControllerHolder& controller : connected_controllers) {
controller.type = NPadControllerType::None;
controller.is_connected = false;
}
std::for_each(connected_controllers.begin(), connected_controllers.end(),
[](ControllerHolder& controller) {
controller.type = NPadControllerType::None;
controller.is_connected = false;
});
}
u32 Controller_NPad::GetAndResetPressState() {
@@ -654,10 +685,10 @@ u32 Controller_NPad::GetAndResetPressState() {
}
bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
const bool support_handheld =
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) !=
supported_npad_id_types.end();
if (controller == NPadControllerType::Handheld) {
const bool support_handheld =
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
NPAD_HANDHELD) != supported_npad_id_types.end();
// Handheld is not even a supported type, lets stop here
if (!support_handheld) {
return false;
@@ -669,7 +700,6 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
return true;
}
if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
[](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
switch (controller) {
@@ -687,7 +717,6 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
return false;
}
}
return false;
}
@@ -766,7 +795,6 @@ Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
priority_list.push_back(NPadControllerType::JoyLeft);
priority_list.push_back(NPadControllerType::JoyRight);
priority_list.push_back(NPadControllerType::JoyDual);
break;
}
const auto iter = std::find_if(priority_list.begin(), priority_list.end(),
+5 -5
View File
@@ -301,11 +301,6 @@ private:
bool is_connected;
};
void InitNewlyAddedControler(std::size_t controller_idx);
bool IsControllerSupported(NPadControllerType controller) const;
NPadControllerType DecideBestController(NPadControllerType priority) const;
void RequestPadStateUpdate(u32 npad_id);
u32 press_state{};
NPadType style{};
@@ -326,7 +321,12 @@ private:
std::array<ControllerHolder, 10> connected_controllers{};
bool can_controllers_vibrate{true};
void InitNewlyAddedControler(std::size_t controller_idx);
bool IsControllerSupported(NPadControllerType controller) const;
NPadControllerType DecideBestController(NPadControllerType priority) const;
void RequestPadStateUpdate(u32 npad_id);
std::array<ControllerPad, 10> npad_pad_states{};
bool IsControllerSupported(NPadControllerType controller);
bool is_in_lr_assignment_mode{false};
Core::System& system;
};
+6 -4
View File
@@ -26,7 +26,8 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152);
Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name)
: ServiceFramework(name), module(std::move(module)), system(system) {
auto& kernel = system.Kernel();
nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected");
nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IUser:NFCTagDetected");
}
Module::Interface::~Interface() = default;
@@ -65,9 +66,10 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent");
availability_change_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent");
deactivate_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent");
availability_change_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent");
}
private:
+4 -2
View File
@@ -70,8 +70,10 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1");
event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2");
event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IRequest:Event1");
event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IRequest:Event2");
}
private:
+2 -1
View File
@@ -141,7 +141,8 @@ public:
auto& kernel = system.Kernel();
finished_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
kernel, Kernel::ResetType::Automatic,
"IEnsureNetworkClockAvailabilityService:FinishEvent");
}
private:
+2 -1
View File
@@ -40,7 +40,8 @@ Module::Module(Core::System& system) {
auto& kernel = system.Kernel();
for (u32 i = 0; i < MaxNvEvents; i++) {
std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
events_interface.events[i] = Kernel::WritableEvent::CreateEventPair(kernel, event_label);
events_interface.events[i] =
Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, event_label);
events_interface.status[i] = EventState::Free;
events_interface.registered[i] = false;
}
@@ -16,7 +16,8 @@ namespace Service::NVFlinger {
BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
: id(id), layer_id(layer_id) {
buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle");
buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"BufferQueue NativeHandle");
}
BufferQueue::~BufferQueue() = default;
@@ -17,8 +17,8 @@ namespace Service::VI {
Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
auto& kernel = system.Kernel();
vsync_event =
Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id));
vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
fmt::format("Display VSync Event {}", id));
}
Display::~Display() = default;
+1 -1
View File
@@ -45,7 +45,7 @@ struct DisplayInfo {
/// Whether or not the display has a limited number of layers.
u8 has_limited_layers{1};
INSERT_PADDING_BYTES(7);
INSERT_PADDING_BYTES(7){};
/// Indicates the total amount of layers supported by the display.
/// @note This is only valid if has_limited_layers is set.
-2
View File
@@ -36,8 +36,6 @@ add_library(video_core STATIC
memory_manager.h
morton.cpp
morton.h
rasterizer_accelerated.cpp
rasterizer_accelerated.h
rasterizer_cache.cpp
rasterizer_cache.h
rasterizer_interface.h
+3 -15
View File
@@ -12,10 +12,6 @@
#include <utility>
#include <vector>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include <boost/range/iterator_range.hpp>
#include "common/alignment.h"
#include "common/common_types.h"
#include "core/core.h"
@@ -34,7 +30,7 @@ public:
using BufferInfo = std::pair<const TBufferType*, u64>;
BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4,
bool is_written = false, bool use_fast_cbuf = false) {
bool is_written = false) {
std::lock_guard lock{mutex};
auto& memory_manager = system.GPU().MemoryManager();
@@ -47,13 +43,9 @@ public:
// Cache management is a big overhead, so only cache entries with a given size.
// TODO: Figure out which size is the best for given games.
constexpr std::size_t max_stream_size = 0x800;
if (use_fast_cbuf || size < max_stream_size) {
if (size < max_stream_size) {
if (!is_written && !IsRegionWritten(cache_addr, cache_addr + size - 1)) {
if (use_fast_cbuf) {
return ConstBufferUpload(host_ptr, size);
} else {
return StreamBufferUpload(host_ptr, size, alignment);
}
return StreamBufferUpload(host_ptr, size, alignment);
}
}
@@ -160,10 +152,6 @@ protected:
virtual void CopyBlock(const TBuffer& src, const TBuffer& dst, std::size_t src_offset,
std::size_t dst_offset, std::size_t size) = 0;
virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
return {};
}
/// Register an object into the cache
void Register(const MapInterval& new_map, bool inherit_written = false) {
const CacheAddr cache_ptr = new_map->GetStart();
@@ -35,7 +35,7 @@ struct SamplerDescriptor {
}
bool operator!=(const SamplerDescriptor& rhs) const noexcept {
return !operator==(rhs);
return raw != rhs.raw;
}
static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) {
@@ -77,12 +77,13 @@ struct SamplerDescriptor {
result.is_buffer.Assign(0);
result.is_shadow.Assign(0);
return result;
case Tegra::Texture::TextureType::Texture1DBuffer:
case Tegra::Texture::TextureType::Texture1DBuffer: {
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
result.is_array.Assign(0);
result.is_buffer.Assign(1);
result.is_shadow.Assign(0);
return result;
}
case Tegra::Texture::TextureType::Texture2DNoMipmap:
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
result.is_array.Assign(0);
+6 -6
View File
@@ -99,19 +99,19 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0x80);
INSERT_PADDING_WORDS(0x80);
Surface dst;
INSERT_UNION_PADDING_WORDS(2);
INSERT_PADDING_WORDS(2);
Surface src;
INSERT_UNION_PADDING_WORDS(0x15);
INSERT_PADDING_WORDS(0x15);
Operation operation;
INSERT_UNION_PADDING_WORDS(0x177);
INSERT_PADDING_WORDS(0x177);
union {
u32 raw;
@@ -119,7 +119,7 @@ public:
BitField<4, 1, Filter> filter;
} blit_control;
INSERT_UNION_PADDING_WORDS(0x8);
INSERT_PADDING_WORDS(0x8);
u32 blit_dst_x;
u32 blit_dst_y;
@@ -130,7 +130,7 @@ public:
u64 blit_src_x;
u64 blit_src_y;
INSERT_UNION_PADDING_WORDS(0x21);
INSERT_PADDING_WORDS(0x21);
};
std::array<u32, NUM_REGS> reg_array;
};
+7 -5
View File
@@ -50,7 +50,7 @@ void KeplerCompute::CallMethod(const GPU::MethodCall& method_call) {
}
}
Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const {
Tegra::Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const {
const std::bitset<8> cbuf_mask = launch_description.const_buffer_enable_mask.Value();
ASSERT(cbuf_mask[regs.tex_cb_index]);
@@ -61,11 +61,13 @@ Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const {
ASSERT(address < texinfo.Address() + texinfo.size);
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(address)};
return GetTextureInfo(tex_handle);
return GetTextureInfo(tex_handle, offset);
}
Texture::FullTextureInfo KeplerCompute::GetTextureInfo(Texture::TextureHandle tex_handle) const {
return Texture::FullTextureInfo{GetTICEntry(tex_handle.tic_id), GetTSCEntry(tex_handle.tsc_id)};
Texture::FullTextureInfo KeplerCompute::GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const {
return Texture::FullTextureInfo{static_cast<u32>(offset), GetTICEntry(tex_handle.tic_id),
GetTSCEntry(tex_handle.tsc_id)};
}
u32 KeplerCompute::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
@@ -87,7 +89,7 @@ SamplerDescriptor KeplerCompute::AccessBindlessSampler(ShaderType stage, u64 con
const GPUVAddr tex_info_address = tex_info_buffer.Address() + offset;
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(tex_info_address)};
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle);
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle, offset);
SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value());
result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value());
return result;
+13 -12
View File
@@ -51,7 +51,7 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0x60);
INSERT_PADDING_WORDS(0x60);
Upload::Registers upload;
@@ -63,7 +63,7 @@ public:
u32 data_upload;
INSERT_UNION_PADDING_WORDS(0x3F);
INSERT_PADDING_WORDS(0x3F);
struct {
u32 address;
@@ -72,11 +72,11 @@ public:
}
} launch_desc_loc;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
u32 launch;
INSERT_UNION_PADDING_WORDS(0x4A7);
INSERT_PADDING_WORDS(0x4A7);
struct {
u32 address_high;
@@ -88,7 +88,7 @@ public:
}
} tsc;
INSERT_UNION_PADDING_WORDS(0x3);
INSERT_PADDING_WORDS(0x3);
struct {
u32 address_high;
@@ -100,7 +100,7 @@ public:
}
} tic;
INSERT_UNION_PADDING_WORDS(0x22);
INSERT_PADDING_WORDS(0x22);
struct {
u32 address_high;
@@ -111,11 +111,11 @@ public:
}
} code_loc;
INSERT_UNION_PADDING_WORDS(0x3FE);
INSERT_PADDING_WORDS(0x3FE);
u32 tex_cb_index;
INSERT_UNION_PADDING_WORDS(0x374);
INSERT_PADDING_WORDS(0x374);
};
std::array<u32, NUM_REGS> reg_array;
};
@@ -179,7 +179,7 @@ public:
};
INSERT_PADDING_WORDS(0x11);
} launch_description{};
} launch_description;
struct {
u32 write_offset = 0;
@@ -196,10 +196,11 @@ public:
/// Write the value to the register identified by method.
void CallMethod(const GPU::MethodCall& method_call);
Texture::FullTextureInfo GetTexture(std::size_t offset) const;
Tegra::Texture::FullTextureInfo GetTexture(std::size_t offset) const;
/// Given a texture handle, returns the TSC and TIC entries.
Texture::FullTextureInfo GetTextureInfo(Texture::TextureHandle tex_handle) const;
/// Given a Texture Handle, returns the TSC and TIC entries.
Texture::FullTextureInfo GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const;
u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const override;
+2 -2
View File
@@ -45,7 +45,7 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0x60);
INSERT_PADDING_WORDS(0x60);
Upload::Registers upload;
@@ -57,7 +57,7 @@ public:
u32 data;
INSERT_UNION_PADDING_WORDS(0x11);
INSERT_PADDING_WORDS(0x11);
};
std::array<u32, NUM_REGS> reg_array;
};
+81 -27
View File
@@ -98,10 +98,11 @@ void Maxwell3D::InitializeRegisterDefaults() {
mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
}
#define DIRTY_REGS_POS(field_name) static_cast<u8>(offsetof(Maxwell3D::DirtyRegs, field_name))
#define DIRTY_REGS_POS(field_name) (offsetof(Maxwell3D::DirtyRegs, field_name))
void Maxwell3D::InitDirtySettings() {
const auto set_block = [this](std::size_t start, std::size_t range, u8 position) {
const auto set_block = [this](const std::size_t start, const std::size_t range,
const u8 position) {
const auto start_itr = dirty_pointers.begin() + start;
const auto end_itr = start_itr + range;
std::fill(start_itr, end_itr, position);
@@ -112,10 +113,10 @@ void Maxwell3D::InitDirtySettings() {
constexpr u32 registers_per_rt = sizeof(regs.rt[0]) / sizeof(u32);
constexpr u32 rt_start_reg = MAXWELL3D_REG_INDEX(rt);
constexpr u32 rt_end_reg = rt_start_reg + registers_per_rt * 8;
u8 rt_dirty_reg = DIRTY_REGS_POS(render_target);
u32 rt_dirty_reg = DIRTY_REGS_POS(render_target);
for (u32 rt_reg = rt_start_reg; rt_reg < rt_end_reg; rt_reg += registers_per_rt) {
set_block(rt_reg, registers_per_rt, rt_dirty_reg);
++rt_dirty_reg;
rt_dirty_reg++;
}
constexpr u32 depth_buffer_flag = DIRTY_REGS_POS(depth_buffer);
dirty_pointers[MAXWELL3D_REG_INDEX(zeta_enable)] = depth_buffer_flag;
@@ -129,35 +130,35 @@ void Maxwell3D::InitDirtySettings() {
constexpr u32 vertex_array_start = MAXWELL3D_REG_INDEX(vertex_array);
constexpr u32 vertex_array_size = sizeof(regs.vertex_array[0]) / sizeof(u32);
constexpr u32 vertex_array_end = vertex_array_start + vertex_array_size * Regs::NumVertexArrays;
u8 va_dirty_reg = DIRTY_REGS_POS(vertex_array);
u8 vi_dirty_reg = DIRTY_REGS_POS(vertex_instance);
u32 va_reg = DIRTY_REGS_POS(vertex_array);
u32 vi_reg = DIRTY_REGS_POS(vertex_instance);
for (u32 vertex_reg = vertex_array_start; vertex_reg < vertex_array_end;
vertex_reg += vertex_array_size) {
set_block(vertex_reg, 3, va_dirty_reg);
set_block(vertex_reg, 3, va_reg);
// The divisor concerns vertex array instances
dirty_pointers[static_cast<std::size_t>(vertex_reg) + 3] = vi_dirty_reg;
++va_dirty_reg;
++vi_dirty_reg;
dirty_pointers[vertex_reg + 3] = vi_reg;
va_reg++;
vi_reg++;
}
constexpr u32 vertex_limit_start = MAXWELL3D_REG_INDEX(vertex_array_limit);
constexpr u32 vertex_limit_size = sizeof(regs.vertex_array_limit[0]) / sizeof(u32);
constexpr u32 vertex_limit_end = vertex_limit_start + vertex_limit_size * Regs::NumVertexArrays;
va_dirty_reg = DIRTY_REGS_POS(vertex_array);
va_reg = DIRTY_REGS_POS(vertex_array);
for (u32 vertex_reg = vertex_limit_start; vertex_reg < vertex_limit_end;
vertex_reg += vertex_limit_size) {
set_block(vertex_reg, vertex_limit_size, va_dirty_reg);
va_dirty_reg++;
set_block(vertex_reg, vertex_limit_size, va_reg);
va_reg++;
}
constexpr u32 vertex_instance_start = MAXWELL3D_REG_INDEX(instanced_arrays);
constexpr u32 vertex_instance_size =
sizeof(regs.instanced_arrays.is_instanced[0]) / sizeof(u32);
constexpr u32 vertex_instance_end =
vertex_instance_start + vertex_instance_size * Regs::NumVertexArrays;
vi_dirty_reg = DIRTY_REGS_POS(vertex_instance);
vi_reg = DIRTY_REGS_POS(vertex_instance);
for (u32 vertex_reg = vertex_instance_start; vertex_reg < vertex_instance_end;
vertex_reg += vertex_instance_size) {
set_block(vertex_reg, vertex_instance_size, vi_dirty_reg);
vi_dirty_reg++;
set_block(vertex_reg, vertex_instance_size, vi_reg);
vi_reg++;
}
set_block(MAXWELL3D_REG_INDEX(vertex_attrib_format), regs.vertex_attrib_format.size(),
DIRTY_REGS_POS(vertex_attrib_format));
@@ -171,7 +172,7 @@ void Maxwell3D::InitDirtySettings() {
// State
// Viewport
constexpr u8 viewport_dirty_reg = DIRTY_REGS_POS(viewport);
constexpr u32 viewport_dirty_reg = DIRTY_REGS_POS(viewport);
constexpr u32 viewport_start = MAXWELL3D_REG_INDEX(viewports);
constexpr u32 viewport_size = sizeof(regs.viewports) / sizeof(u32);
set_block(viewport_start, viewport_size, viewport_dirty_reg);
@@ -198,7 +199,7 @@ void Maxwell3D::InitDirtySettings() {
set_block(primitive_restart_start, primitive_restart_size, DIRTY_REGS_POS(primitive_restart));
// Depth Test
constexpr u8 depth_test_dirty_reg = DIRTY_REGS_POS(depth_test);
constexpr u32 depth_test_dirty_reg = DIRTY_REGS_POS(depth_test);
dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_enable)] = depth_test_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(depth_write_enabled)] = depth_test_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_func)] = depth_test_dirty_reg;
@@ -223,12 +224,12 @@ void Maxwell3D::InitDirtySettings() {
dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_mask)] = stencil_test_dirty_reg;
// Color Mask
constexpr u8 color_mask_dirty_reg = DIRTY_REGS_POS(color_mask);
constexpr u32 color_mask_dirty_reg = DIRTY_REGS_POS(color_mask);
dirty_pointers[MAXWELL3D_REG_INDEX(color_mask_common)] = color_mask_dirty_reg;
set_block(MAXWELL3D_REG_INDEX(color_mask), sizeof(regs.color_mask) / sizeof(u32),
color_mask_dirty_reg);
// Blend State
constexpr u8 blend_state_dirty_reg = DIRTY_REGS_POS(blend_state);
constexpr u32 blend_state_dirty_reg = DIRTY_REGS_POS(blend_state);
set_block(MAXWELL3D_REG_INDEX(blend_color), sizeof(regs.blend_color) / sizeof(u32),
blend_state_dirty_reg);
dirty_pointers[MAXWELL3D_REG_INDEX(independent_blend_enable)] = blend_state_dirty_reg;
@@ -237,12 +238,12 @@ void Maxwell3D::InitDirtySettings() {
blend_state_dirty_reg);
// Scissor State
constexpr u8 scissor_test_dirty_reg = DIRTY_REGS_POS(scissor_test);
constexpr u32 scissor_test_dirty_reg = DIRTY_REGS_POS(scissor_test);
set_block(MAXWELL3D_REG_INDEX(scissor_test), sizeof(regs.scissor_test) / sizeof(u32),
scissor_test_dirty_reg);
// Polygon Offset
constexpr u8 polygon_offset_dirty_reg = DIRTY_REGS_POS(polygon_offset);
constexpr u32 polygon_offset_dirty_reg = DIRTY_REGS_POS(polygon_offset);
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_fill_enable)] = polygon_offset_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_line_enable)] = polygon_offset_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_point_enable)] = polygon_offset_dirty_reg;
@@ -251,7 +252,7 @@ void Maxwell3D::InitDirtySettings() {
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_clamp)] = polygon_offset_dirty_reg;
// Depth bounds
constexpr u8 depth_bounds_values_dirty_reg = DIRTY_REGS_POS(depth_bounds_values);
constexpr u32 depth_bounds_values_dirty_reg = DIRTY_REGS_POS(depth_bounds_values);
dirty_pointers[MAXWELL3D_REG_INDEX(depth_bounds[0])] = depth_bounds_values_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(depth_bounds[1])] = depth_bounds_values_dirty_reg;
}
@@ -760,8 +761,61 @@ Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
return tsc_entry;
}
Texture::FullTextureInfo Maxwell3D::GetTextureInfo(Texture::TextureHandle tex_handle) const {
return Texture::FullTextureInfo{GetTICEntry(tex_handle.tic_id), GetTSCEntry(tex_handle.tsc_id)};
std::vector<Texture::FullTextureInfo> Maxwell3D::GetStageTextures(Regs::ShaderStage stage) const {
std::vector<Texture::FullTextureInfo> textures;
auto& fragment_shader = state.shader_stages[static_cast<std::size_t>(stage)];
auto& tex_info_buffer = fragment_shader.const_buffers[regs.tex_cb_index];
ASSERT(tex_info_buffer.enabled && tex_info_buffer.address != 0);
GPUVAddr tex_info_buffer_end = tex_info_buffer.address + tex_info_buffer.size;
// Offset into the texture constbuffer where the texture info begins.
static constexpr std::size_t TextureInfoOffset = 0x20;
for (GPUVAddr current_texture = tex_info_buffer.address + TextureInfoOffset;
current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) {
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(current_texture)};
Texture::FullTextureInfo tex_info{};
// TODO(Subv): Use the shader to determine which textures are actually accessed.
tex_info.index =
static_cast<u32>(current_texture - tex_info_buffer.address - TextureInfoOffset) /
sizeof(Texture::TextureHandle);
// Load the TIC data.
auto tic_entry = GetTICEntry(tex_handle.tic_id);
// TODO(Subv): Workaround for BitField's move constructor being deleted.
std::memcpy(&tex_info.tic, &tic_entry, sizeof(tic_entry));
// Load the TSC data
auto tsc_entry = GetTSCEntry(tex_handle.tsc_id);
// TODO(Subv): Workaround for BitField's move constructor being deleted.
std::memcpy(&tex_info.tsc, &tsc_entry, sizeof(tsc_entry));
textures.push_back(tex_info);
}
return textures;
}
Texture::FullTextureInfo Maxwell3D::GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const {
Texture::FullTextureInfo tex_info{};
tex_info.index = static_cast<u32>(offset);
// Load the TIC data.
auto tic_entry = GetTICEntry(tex_handle.tic_id);
// TODO(Subv): Workaround for BitField's move constructor being deleted.
std::memcpy(&tex_info.tic, &tic_entry, sizeof(tic_entry));
// Load the TSC data
auto tsc_entry = GetTSCEntry(tex_handle.tsc_id);
// TODO(Subv): Workaround for BitField's move constructor being deleted.
std::memcpy(&tex_info.tsc, &tsc_entry, sizeof(tsc_entry));
return tex_info;
}
Texture::FullTextureInfo Maxwell3D::GetStageTexture(Regs::ShaderStage stage,
@@ -777,7 +831,7 @@ Texture::FullTextureInfo Maxwell3D::GetStageTexture(Regs::ShaderStage stage,
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(tex_info_address)};
return GetTextureInfo(tex_handle);
return GetTextureInfo(tex_handle, offset);
}
u32 Maxwell3D::GetRegisterValue(u32 method) const {
@@ -814,7 +868,7 @@ SamplerDescriptor Maxwell3D::AccessBindlessSampler(ShaderType stage, u64 const_b
const GPUVAddr tex_info_address = tex_info_buffer.address + offset;
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(tex_info_address)};
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle);
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle, offset);
SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value());
result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value());
return result;
+64 -62
View File
@@ -496,7 +496,7 @@ public:
Equation equation_a;
Factor factor_source_a;
Factor factor_dest_a;
INSERT_UNION_PADDING_WORDS(1);
INSERT_PADDING_WORDS(1);
};
struct RenderTargetConfig {
@@ -517,7 +517,7 @@ public:
};
u32 layer_stride;
u32 base_layer;
INSERT_UNION_PADDING_WORDS(7);
INSERT_PADDING_WORDS(7);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -542,7 +542,7 @@ public:
f32 translate_x;
f32 translate_y;
f32 translate_z;
INSERT_UNION_PADDING_WORDS(2);
INSERT_PADDING_WORDS(2);
Common::Rectangle<s32> GetRect() const {
return {
@@ -606,7 +606,7 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0x45);
INSERT_PADDING_WORDS(0x45);
struct {
u32 upload_address;
@@ -615,7 +615,7 @@ public:
u32 bind;
} macros;
INSERT_UNION_PADDING_WORDS(0x17);
INSERT_PADDING_WORDS(0x17);
Upload::Registers upload;
struct {
@@ -626,7 +626,7 @@ public:
u32 data_upload;
INSERT_UNION_PADDING_WORDS(0x44);
INSERT_PADDING_WORDS(0x44);
struct {
union {
@@ -636,11 +636,11 @@ public:
};
} sync_info;
INSERT_UNION_PADDING_WORDS(0x11E);
INSERT_PADDING_WORDS(0x11E);
u32 tfb_enabled;
INSERT_UNION_PADDING_WORDS(0x2E);
INSERT_PADDING_WORDS(0x2E);
std::array<RenderTargetConfig, NumRenderTargets> rt;
@@ -648,49 +648,49 @@ public:
std::array<ViewPort, NumViewports> viewports;
INSERT_UNION_PADDING_WORDS(0x1D);
INSERT_PADDING_WORDS(0x1D);
struct {
u32 first;
u32 count;
} vertex_buffer;
INSERT_UNION_PADDING_WORDS(1);
INSERT_PADDING_WORDS(1);
float clear_color[4];
float clear_depth;
INSERT_UNION_PADDING_WORDS(0x3);
INSERT_PADDING_WORDS(0x3);
s32 clear_stencil;
INSERT_UNION_PADDING_WORDS(0x7);
INSERT_PADDING_WORDS(0x7);
u32 polygon_offset_point_enable;
u32 polygon_offset_line_enable;
u32 polygon_offset_fill_enable;
INSERT_UNION_PADDING_WORDS(0xD);
INSERT_PADDING_WORDS(0xD);
std::array<ScissorTest, NumViewports> scissor_test;
INSERT_UNION_PADDING_WORDS(0x15);
INSERT_PADDING_WORDS(0x15);
s32 stencil_back_func_ref;
u32 stencil_back_mask;
u32 stencil_back_func_mask;
INSERT_UNION_PADDING_WORDS(0xC);
INSERT_PADDING_WORDS(0xC);
u32 color_mask_common;
INSERT_UNION_PADDING_WORDS(0x6);
INSERT_PADDING_WORDS(0x6);
u32 rt_separate_frag_data;
f32 depth_bounds[2];
INSERT_UNION_PADDING_WORDS(0xA);
INSERT_PADDING_WORDS(0xA);
struct {
u32 address_high;
@@ -710,7 +710,7 @@ public:
}
} zeta;
INSERT_UNION_PADDING_WORDS(0x41);
INSERT_PADDING_WORDS(0x41);
union {
BitField<0, 4, u32> stencil;
@@ -719,11 +719,11 @@ public:
BitField<12, 4, u32> viewport;
} clear_flags;
INSERT_UNION_PADDING_WORDS(0x19);
INSERT_PADDING_WORDS(0x19);
std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
INSERT_UNION_PADDING_WORDS(0xF);
INSERT_PADDING_WORDS(0xF);
struct {
union {
@@ -746,16 +746,16 @@ public:
}
} rt_control;
INSERT_UNION_PADDING_WORDS(0x2);
INSERT_PADDING_WORDS(0x2);
u32 zeta_width;
u32 zeta_height;
INSERT_UNION_PADDING_WORDS(0x27);
INSERT_PADDING_WORDS(0x27);
u32 depth_test_enable;
INSERT_UNION_PADDING_WORDS(0x5);
INSERT_PADDING_WORDS(0x5);
u32 independent_blend_enable;
@@ -763,7 +763,7 @@ public:
u32 alpha_test_enabled;
INSERT_UNION_PADDING_WORDS(0x6);
INSERT_PADDING_WORDS(0x6);
u32 d3d_cull_mode;
@@ -777,7 +777,7 @@ public:
float b;
float a;
} blend_color;
INSERT_UNION_PADDING_WORDS(0x4);
INSERT_PADDING_WORDS(0x4);
struct {
u32 separate_alpha;
@@ -786,7 +786,7 @@ public:
Blend::Factor factor_dest_rgb;
Blend::Equation equation_a;
Blend::Factor factor_source_a;
INSERT_UNION_PADDING_WORDS(1);
INSERT_PADDING_WORDS(1);
Blend::Factor factor_dest_a;
u32 enable_common;
@@ -802,7 +802,7 @@ public:
u32 stencil_front_func_mask;
u32 stencil_front_mask;
INSERT_UNION_PADDING_WORDS(0x2);
INSERT_PADDING_WORDS(0x2);
u32 frag_color_clamp;
@@ -811,12 +811,12 @@ public:
BitField<4, 1, u32> triangle_rast_flip;
} screen_y_control;
INSERT_UNION_PADDING_WORDS(0x21);
INSERT_PADDING_WORDS(0x21);
u32 vb_element_base;
u32 vb_base_instance;
INSERT_UNION_PADDING_WORDS(0x35);
INSERT_PADDING_WORDS(0x35);
union {
BitField<0, 1, u32> c0;
@@ -829,11 +829,11 @@ public:
BitField<7, 1, u32> c7;
} clip_distance_enabled;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
float point_size;
INSERT_UNION_PADDING_WORDS(0x7);
INSERT_PADDING_WORDS(0x7);
u32 zeta_enable;
@@ -842,7 +842,7 @@ public:
BitField<4, 1, u32> alpha_to_one;
} multisample_control;
INSERT_UNION_PADDING_WORDS(0x4);
INSERT_PADDING_WORDS(0x4);
struct {
u32 address_high;
@@ -866,11 +866,11 @@ public:
}
} tsc;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
float polygon_offset_factor;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
struct {
u32 tic_address_high;
@@ -883,7 +883,7 @@ public:
}
} tic;
INSERT_UNION_PADDING_WORDS(0x5);
INSERT_PADDING_WORDS(0x5);
u32 stencil_two_side_enable;
StencilOp stencil_back_op_fail;
@@ -891,13 +891,13 @@ public:
StencilOp stencil_back_op_zpass;
ComparisonOp stencil_back_func_func;
INSERT_UNION_PADDING_WORDS(0x4);
INSERT_PADDING_WORDS(0x4);
u32 framebuffer_srgb;
float polygon_offset_units;
INSERT_UNION_PADDING_WORDS(0x11);
INSERT_PADDING_WORDS(0x11);
union {
BitField<2, 1, u32> coord_origin;
@@ -913,7 +913,7 @@ public:
(static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
}
} code_address;
INSERT_UNION_PADDING_WORDS(1);
INSERT_PADDING_WORDS(1);
struct {
u32 vertex_end_gl;
@@ -925,14 +925,14 @@ public:
};
} draw;
INSERT_UNION_PADDING_WORDS(0xA);
INSERT_PADDING_WORDS(0xA);
struct {
u32 enabled;
u32 index;
} primitive_restart;
INSERT_UNION_PADDING_WORDS(0x5F);
INSERT_PADDING_WORDS(0x5F);
struct {
u32 start_addr_high;
@@ -973,9 +973,9 @@ public:
}
} index_array;
INSERT_UNION_PADDING_WORDS(0x7);
INSERT_PADDING_WORDS(0x7);
INSERT_UNION_PADDING_WORDS(0x1F);
INSERT_PADDING_WORDS(0x1F);
float polygon_offset_clamp;
@@ -989,17 +989,17 @@ public:
}
} instanced_arrays;
INSERT_UNION_PADDING_WORDS(0x6);
INSERT_PADDING_WORDS(0x6);
Cull cull;
u32 pixel_center_integer;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
u32 viewport_transform_enabled;
INSERT_UNION_PADDING_WORDS(0x3);
INSERT_PADDING_WORDS(0x3);
union {
BitField<0, 1, u32> depth_range_0_1;
@@ -1007,13 +1007,13 @@ public:
BitField<4, 1, u32> depth_clamp_far;
} view_volume_clip_control;
INSERT_UNION_PADDING_WORDS(0x21);
INSERT_PADDING_WORDS(0x21);
struct {
u32 enable;
LogicOperation operation;
} logic_op;
INSERT_UNION_PADDING_WORDS(0x1);
INSERT_PADDING_WORDS(0x1);
union {
u32 raw;
@@ -1026,9 +1026,9 @@ public:
BitField<6, 4, u32> RT;
BitField<10, 11, u32> layer;
} clear_buffers;
INSERT_UNION_PADDING_WORDS(0xB);
INSERT_PADDING_WORDS(0xB);
std::array<ColorMask, NumRenderTargets> color_mask;
INSERT_UNION_PADDING_WORDS(0x38);
INSERT_PADDING_WORDS(0x38);
struct {
u32 query_address_high;
@@ -1050,7 +1050,7 @@ public:
}
} query;
INSERT_UNION_PADDING_WORDS(0x3C);
INSERT_PADDING_WORDS(0x3C);
struct {
union {
@@ -1090,10 +1090,10 @@ public:
BitField<4, 4, ShaderProgram> program;
};
u32 offset;
INSERT_UNION_PADDING_WORDS(14);
INSERT_PADDING_WORDS(14);
} shader_config[MaxShaderProgram];
INSERT_UNION_PADDING_WORDS(0x60);
INSERT_PADDING_WORDS(0x60);
u32 firmware[0x20];
@@ -1110,7 +1110,7 @@ public:
}
} const_buffer;
INSERT_UNION_PADDING_WORDS(0x10);
INSERT_PADDING_WORDS(0x10);
struct {
union {
@@ -1118,14 +1118,14 @@ public:
BitField<0, 1, u32> valid;
BitField<4, 5, u32> index;
};
INSERT_UNION_PADDING_WORDS(7);
INSERT_PADDING_WORDS(7);
} cb_bind[MaxShaderStage];
INSERT_UNION_PADDING_WORDS(0x56);
INSERT_PADDING_WORDS(0x56);
u32 tex_cb_index;
INSERT_UNION_PADDING_WORDS(0x395);
INSERT_PADDING_WORDS(0x395);
struct {
/// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1137,14 +1137,14 @@ public:
}
} ssbo_info;
INSERT_UNION_PADDING_WORDS(0x11);
INSERT_PADDING_WORDS(0x11);
struct {
u32 address[MaxShaderStage];
u32 size[MaxShaderStage];
} tex_info_buffers;
INSERT_UNION_PADDING_WORDS(0xCC);
INSERT_PADDING_WORDS(0xCC);
};
std::array<u32, NUM_REGS> reg_array;
};
@@ -1166,8 +1166,6 @@ public:
struct DirtyRegs {
static constexpr std::size_t NUM_REGS = 256;
static_assert(NUM_REGS - 1 <= std::numeric_limits<u8>::max());
union {
struct {
bool null_dirty;
@@ -1250,8 +1248,12 @@ public:
void FlushMMEInlineDraw();
/// Given a texture handle, returns the TSC and TIC entries.
Texture::FullTextureInfo GetTextureInfo(Texture::TextureHandle tex_handle) const;
/// Given a Texture Handle, returns the TSC and TIC entries.
Texture::FullTextureInfo GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const;
/// Returns a list of enabled textures for the specified shader stage.
std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
/// Returns the texture information for a specific texture in a specific shader stage.
Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, std::size_t offset) const;
+5 -5
View File
@@ -94,7 +94,7 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0xC0);
INSERT_PADDING_WORDS(0xC0);
struct {
union {
@@ -112,7 +112,7 @@ public:
};
} exec;
INSERT_UNION_PADDING_WORDS(0x3F);
INSERT_PADDING_WORDS(0x3F);
struct {
u32 address_high;
@@ -139,7 +139,7 @@ public:
u32 x_count;
u32 y_count;
INSERT_UNION_PADDING_WORDS(0xB8);
INSERT_PADDING_WORDS(0xB8);
u32 const0;
u32 const1;
@@ -162,11 +162,11 @@ public:
Parameters dst_params;
INSERT_UNION_PADDING_WORDS(1);
INSERT_PADDING_WORDS(1);
Parameters src_params;
INSERT_UNION_PADDING_WORDS(0x13);
INSERT_PADDING_WORDS(0x13);
};
std::array<u32, NUM_REGS> reg_array;
};
+14 -42
View File
@@ -574,7 +574,7 @@ enum class ShuffleOperation : u64 {
};
union Instruction {
constexpr Instruction& operator=(const Instruction& instr) {
Instruction& operator=(const Instruction& instr) {
value = instr.value;
return *this;
}
@@ -1237,32 +1237,6 @@ union Instruction {
}
} tld4;
union {
BitField<35, 1, u64> ndv_flag;
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
BitField<33, 2, u64> info;
BitField<37, 2, u64> component;
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return ndv_flag != 0;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
case TextureMiscMode::DC:
return dc_flag != 0;
case TextureMiscMode::AOFFI:
return info == 1;
case TextureMiscMode::PTP:
return info == 2;
default:
break;
}
return false;
}
} tld4_b;
union {
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
@@ -1616,8 +1590,7 @@ public:
TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
TLD, // Texture Load
TLDS, // Texture Load with scalar/non-vec4 source/destinations
TLD4, // Texture Gather 4
TLD4_B, // Texture Gather 4 Bindless
TLD4, // Texture Load 4
TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
TMML_B, // Texture Mip Map Level
TMML, // Texture Mip Map Level
@@ -1787,22 +1760,22 @@ public:
class Matcher {
public:
constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type)
Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type)
: name{name}, mask{mask}, expected{expected}, id{id}, type{type} {}
constexpr const char* GetName() const {
const char* GetName() const {
return name;
}
constexpr u16 GetMask() const {
u16 GetMask() const {
return mask;
}
constexpr Id GetId() const {
Id GetId() const {
return id;
}
constexpr Type GetType() const {
Type GetType() const {
return type;
}
@@ -1811,7 +1784,7 @@ public:
* @param instruction The instruction to test
* @returns true if the given instruction matches.
*/
constexpr bool Matches(u16 instruction) const {
bool Matches(u16 instruction) const {
return (instruction & mask) == expected;
}
@@ -1845,7 +1818,7 @@ private:
* A '0' in a bitstring indicates that a zero must be present at that bit position.
* A '1' in a bitstring indicates that a one must be present at that bit position.
*/
static constexpr auto GetMaskAndExpect(const char* const bitstring) {
static auto GetMaskAndExpect(const char* const bitstring) {
u16 mask = 0, expect = 0;
for (std::size_t i = 0; i < opcode_bitsize; i++) {
const std::size_t bit_position = opcode_bitsize - i - 1;
@@ -1862,15 +1835,15 @@ private:
break;
}
}
return std::make_pair(mask, expect);
return std::make_tuple(mask, expect);
}
public:
/// Creates a matcher that can match and parse instructions based on bitstring.
static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type,
const char* const name) {
const auto [mask, expected] = GetMaskAndExpect(bitstring);
return Matcher(name, mask, expected, op, type);
static auto GetMatcher(const char* const bitstring, OpCode::Id op, OpCode::Type type,
const char* const name) {
const auto mask_expect = GetMaskAndExpect(bitstring);
return Matcher(name, std::get<0>(mask_expect), std::get<1>(mask_expect), op, type);
}
};
@@ -1908,7 +1881,6 @@ private:
INST("11011100--11----", Id::TLD, Type::Texture, "TLD"),
INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"),
INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"),
INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"),
INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
+24 -26
View File
@@ -38,37 +38,37 @@ struct Header {
BitField<26, 1, u32> does_load_or_store;
BitField<27, 1, u32> does_fp64;
BitField<28, 4, u32> stream_out_mask;
} common0{};
} common0;
union {
BitField<0, 24, u32> shader_local_memory_low_size;
BitField<24, 8, u32> per_patch_attribute_count;
} common1{};
} common1;
union {
BitField<0, 24, u32> shader_local_memory_high_size;
BitField<24, 8, u32> threads_per_input_primitive;
} common2{};
} common2;
union {
BitField<0, 24, u32> shader_local_memory_crs_size;
BitField<24, 4, OutputTopology> output_topology;
BitField<28, 4, u32> reserved;
} common3{};
} common3;
union {
BitField<0, 12, u32> max_output_vertices;
BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
BitField<24, 4, u32> reserved;
BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
} common4{};
} common4;
union {
struct {
INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
INSERT_UNION_PADDING_BYTES(16); // ImapGenericVector[32]
INSERT_UNION_PADDING_BYTES(2); // ImapColor
INSERT_PADDING_BYTES(3); // ImapSystemValuesA
INSERT_PADDING_BYTES(1); // ImapSystemValuesB
INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
INSERT_PADDING_BYTES(2); // ImapColor
union {
BitField<0, 8, u16> clip_distances;
BitField<8, 1, u16> point_sprite_s;
@@ -79,20 +79,20 @@ struct Header {
BitField<14, 1, u16> instance_id;
BitField<15, 1, u16> vertex_id;
};
INSERT_UNION_PADDING_BYTES(5); // ImapFixedFncTexture[10]
INSERT_UNION_PADDING_BYTES(1); // ImapReserved
INSERT_UNION_PADDING_BYTES(3); // OmapSystemValuesA
INSERT_UNION_PADDING_BYTES(1); // OmapSystemValuesB
INSERT_UNION_PADDING_BYTES(16); // OmapGenericVector[32]
INSERT_UNION_PADDING_BYTES(2); // OmapColor
INSERT_UNION_PADDING_BYTES(2); // OmapSystemValuesC
INSERT_UNION_PADDING_BYTES(5); // OmapFixedFncTexture[10]
INSERT_UNION_PADDING_BYTES(1); // OmapReserved
INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10]
INSERT_PADDING_BYTES(1); // ImapReserved
INSERT_PADDING_BYTES(3); // OmapSystemValuesA
INSERT_PADDING_BYTES(1); // OmapSystemValuesB
INSERT_PADDING_BYTES(16); // OmapGenericVector[32]
INSERT_PADDING_BYTES(2); // OmapColor
INSERT_PADDING_BYTES(2); // OmapSystemValuesC
INSERT_PADDING_BYTES(5); // OmapFixedFncTexture[10]
INSERT_PADDING_BYTES(1); // OmapReserved
} vtg;
struct {
INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
INSERT_PADDING_BYTES(3); // ImapSystemValuesA
INSERT_PADDING_BYTES(1); // ImapSystemValuesB
union {
BitField<0, 2, AttributeUse> x;
BitField<2, 2, AttributeUse> y;
@@ -100,10 +100,10 @@ struct Header {
BitField<6, 2, AttributeUse> z;
u8 raw;
} imap_generic_vector[32];
INSERT_UNION_PADDING_BYTES(2); // ImapColor
INSERT_UNION_PADDING_BYTES(2); // ImapSystemValuesC
INSERT_UNION_PADDING_BYTES(10); // ImapFixedFncTexture[10]
INSERT_UNION_PADDING_BYTES(2); // ImapReserved
INSERT_PADDING_BYTES(2); // ImapColor
INSERT_PADDING_BYTES(2); // ImapSystemValuesC
INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10]
INSERT_PADDING_BYTES(2); // ImapReserved
struct {
u32 target;
union {
@@ -139,8 +139,6 @@ struct Header {
return result;
}
} ps;
std::array<u32, 0xF> raw{};
};
u64 GetLocalMemorySize() const {
+4 -4
View File
@@ -207,7 +207,7 @@ public:
union {
struct {
INSERT_UNION_PADDING_WORDS(0x4);
INSERT_PADDING_WORDS(0x4);
struct {
u32 address_high;
u32 address_low;
@@ -220,12 +220,12 @@ public:
u32 semaphore_sequence;
u32 semaphore_trigger;
INSERT_UNION_PADDING_WORDS(0xC);
INSERT_PADDING_WORDS(0xC);
// The puser and the puller share the reference counter, the pusher only has read
// access
u32 reference_count;
INSERT_UNION_PADDING_WORDS(0x5);
INSERT_PADDING_WORDS(0x5);
u32 semaphore_acquire;
u32 semaphore_release;
@@ -234,7 +234,7 @@ public:
BitField<4, 4, u32> operation;
BitField<8, 8, u32> id;
} fence_action;
INSERT_UNION_PADDING_WORDS(0xE2);
INSERT_PADDING_WORDS(0xE2);
// Puller state
u32 acquire_mode;
-2
View File
@@ -112,7 +112,6 @@ static constexpr ConversionArray morton_to_linear_fns = {
MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
MortonCopy<true, PixelFormat::ASTC_2D_6X5>,
MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
MortonCopy<true, PixelFormat::E5B9G9R9F>,
MortonCopy<true, PixelFormat::Z32F>,
MortonCopy<true, PixelFormat::Z16>,
MortonCopy<true, PixelFormat::Z24S8>,
@@ -193,7 +192,6 @@ static constexpr ConversionArray linear_to_morton_fns = {
nullptr,
nullptr,
nullptr,
MortonCopy<false, PixelFormat::E5B9G9R9F>,
MortonCopy<false, PixelFormat::Z32F>,
MortonCopy<false, PixelFormat::Z16>,
MortonCopy<false, PixelFormat::Z24S8>,
-63
View File
@@ -1,63 +0,0 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <mutex>
#include <boost/icl/interval_map.hpp>
#include "common/assert.h"
#include "common/common_types.h"
#include "core/memory.h"
#include "video_core/rasterizer_accelerated.h"
namespace VideoCore {
namespace {
template <typename Map, typename Interval>
constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
return boost::make_iterator_range(map.equal_range(interval));
}
} // Anonymous namespace
RasterizerAccelerated::RasterizerAccelerated() = default;
RasterizerAccelerated::~RasterizerAccelerated() = default;
void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
std::lock_guard lock{pages_mutex};
const u64 page_start{addr >> Memory::PAGE_BITS};
const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to
// subtract after iterating
const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
if (delta > 0) {
cached_pages.add({pages_interval, delta});
}
for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
const auto interval = pair.first & pages_interval;
const int count = pair.second;
const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
const u64 interval_size = interval_end_addr - interval_start_addr;
if (delta > 0 && count == delta) {
Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
} else if (delta < 0 && count == -delta) {
Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
} else {
ASSERT(count >= 0);
}
}
if (delta < 0) {
cached_pages.add({pages_interval, delta});
}
}
} // namespace VideoCore
-31
View File
@@ -1,31 +0,0 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <mutex>
#include <boost/icl/interval_map.hpp>
#include "common/common_types.h"
#include "video_core/rasterizer_interface.h"
namespace VideoCore {
/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
class RasterizerAccelerated : public RasterizerInterface {
public:
explicit RasterizerAccelerated();
~RasterizerAccelerated() override;
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
private:
using CachedPageMap = boost::icl::interval_map<u64, int>;
CachedPageMap cached_pages;
std::mutex pages_mutex;
};
} // namespace VideoCore
@@ -8,17 +8,13 @@
#include "common/assert.h"
#include "common/microprofile.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_device.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
namespace OpenGL {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128));
CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t size)
@@ -30,22 +26,11 @@ CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t siz
CachedBufferBlock::~CachedBufferBlock() = default;
OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
const Device& device, std::size_t stream_size)
: GenericBufferCache{rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} {
if (!device.HasFastBufferSubData()) {
return;
}
std::size_t stream_size)
: VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>{
rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} {}
static constexpr auto size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize);
glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs));
for (const GLuint cbuf : cbufs) {
glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW);
}
}
OGLBufferCache::~OGLBufferCache() {
glDeleteBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs));
}
OGLBufferCache::~OGLBufferCache() = default;
Buffer OGLBufferCache::CreateBlock(CacheAddr cache_addr, std::size_t size) {
return std::make_shared<CachedBufferBlock>(cache_addr, size);
@@ -84,12 +69,4 @@ void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t
static_cast<GLsizeiptr>(size));
}
OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
std::size_t size) {
DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));
const GLuint& cbuf = cbufs[cbuf_cursor++];
glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer);
return {&cbuf, 0};
}
} // namespace OpenGL
@@ -4,12 +4,10 @@
#pragma once
#include <array>
#include <memory>
#include "common/common_types.h"
#include "video_core/buffer_cache/buffer_cache.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
@@ -20,14 +18,12 @@ class System;
namespace OpenGL {
class Device;
class OGLStreamBuffer;
class RasterizerOpenGL;
class CachedBufferBlock;
using Buffer = std::shared_ptr<CachedBufferBlock>;
using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
class CachedBufferBlock : public VideoCommon::BufferBlock {
public:
@@ -42,18 +38,14 @@ private:
OGLBuffer gl_buffer{};
};
class OGLBufferCache final : public GenericBufferCache {
class OGLBufferCache final : public VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer> {
public:
explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
const Device& device, std::size_t stream_size);
std::size_t stream_size);
~OGLBufferCache();
const GLuint* GetEmptyBuffer(std::size_t) override;
void Acquire() noexcept {
cbuf_cursor = 0;
}
protected:
Buffer CreateBlock(CacheAddr cache_addr, std::size_t size) override;
@@ -69,14 +61,6 @@ protected:
void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
std::size_t dst_offset, std::size_t size) override;
BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override;
private:
std::size_t cbuf_cursor = 0;
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers *
Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram>
cbufs;
};
} // namespace OpenGL
@@ -51,11 +51,8 @@ bool HasExtension(const std::vector<std::string_view>& images, std::string_view
} // Anonymous namespace
Device::Device() {
const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
const std::vector extensions = GetExtensions();
const bool is_nvidia = vendor == "NVIDIA Corporation";
uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
@@ -67,7 +64,6 @@ Device::Device() {
has_variable_aoffi = TestVariableAoffi();
has_component_indexing_bug = TestComponentIndexingBug();
has_precise_bug = TestPreciseBug();
has_fast_buffer_sub_data = is_nvidia;
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
@@ -54,10 +54,6 @@ public:
return has_precise_bug;
}
bool HasFastBufferSubData() const {
return has_fast_buffer_sub_data;
}
private:
static bool TestVariableAoffi();
static bool TestComponentIndexingBug();
@@ -73,7 +69,6 @@ private:
bool has_variable_aoffi{};
bool has_component_indexing_bug{};
bool has_precise_bug{};
bool has_fast_buffer_sub_data{};
};
} // namespace OpenGL
@@ -67,7 +67,9 @@ static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buf
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
ScreenInfo& info)
: texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device},
system{system}, screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
system{system}, screen_info{info}, buffer_cache{*this, system, STREAM_BUFFER_SIZE} {
OpenGLState::ApplyDefaultState();
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
state.draw.shader_program = 0;
state.Apply();
@@ -257,8 +259,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
continue;
}
const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5
GLShader::MaxwellUniformData ubo{};
ubo.SetFromRegs(gpu);
ubo.SetFromRegs(gpu, stage);
const auto [buffer, offset] =
buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
@@ -267,11 +271,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
Shader shader{shader_cache.GetStageProgram(program)};
// Stage indices are 0 - 5
const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1);
SetupDrawConstBuffers(stage, shader);
SetupDrawGlobalMemory(stage, shader);
const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)};
const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage);
SetupDrawConstBuffers(stage_enum, shader);
SetupDrawGlobalMemory(stage_enum, shader);
const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)};
const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage};
const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant);
@@ -339,6 +342,42 @@ std::size_t RasterizerOpenGL::CalculateIndexBufferSize() const {
static_cast<std::size_t>(regs.index_array.FormatSizeInBytes());
}
template <typename Map, typename Interval>
static constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
return boost::make_iterator_range(map.equal_range(interval));
}
void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
std::lock_guard lock{pages_mutex};
const u64 page_start{addr >> Memory::PAGE_BITS};
const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to
// subtract after iterating
const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
if (delta > 0)
cached_pages.add({pages_interval, delta});
for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
const auto interval = pair.first & pages_interval;
const int count = pair.second;
const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
const u64 interval_size = interval_end_addr - interval_start_addr;
if (delta > 0 && count == delta)
Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
else if (delta < 0 && count == -delta)
Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
else
ASSERT(count >= 0);
}
if (delta < 0)
cached_pages.add({pages_interval, delta});
}
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) {
shader_cache.LoadDiskCache(stop_loading, callback);
@@ -557,8 +596,6 @@ void RasterizerOpenGL::DrawPrelude() {
SyncPolygonOffset();
SyncAlphaTest();
buffer_cache.Acquire();
// Draw the vertex batch
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
@@ -880,8 +917,7 @@ void RasterizerOpenGL::SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& b
const std::size_t size = Common::AlignUp(GetConstBufferSize(buffer, entry), sizeof(GLvec4));
const auto alignment = device.GetUniformBufferAlignment();
const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false,
device.HasFastBufferSubData());
const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment);
bind_ubo_pushbuffer.Push(cbuf, offset, size);
}
@@ -933,14 +969,15 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto texture = [&] {
const auto texture = [&]() {
if (!entry.IsBindless()) {
return maxwell3d.GetStageTexture(stage, entry.GetOffset());
}
const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
const Tegra::Texture::TextureHandle tex_handle =
maxwell3d.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset());
return maxwell3d.GetTextureInfo(tex_handle);
const auto cbuf = entry.GetBindlessCBuf();
Tegra::Texture::TextureHandle tex_handle;
Tegra::Engines::ShaderType shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
tex_handle.raw = maxwell3d.AccessConstBuffer32(shader_type, cbuf.first, cbuf.second);
return maxwell3d.GetTextureInfo(tex_handle, entry.GetOffset());
}();
if (SetupTexture(base_bindings.sampler + bindpoint, texture, entry)) {
@@ -963,13 +1000,15 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel)
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto texture = [&] {
const auto texture = [&]() {
if (!entry.IsBindless()) {
return compute.GetTexture(entry.GetOffset());
}
const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
return compute.GetTextureInfo(tex_handle);
const auto cbuf = entry.GetBindlessCBuf();
Tegra::Texture::TextureHandle tex_handle;
tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
cbuf.first, cbuf.second);
return compute.GetTextureInfo(tex_handle, entry.GetOffset());
}();
if (SetupTexture(bindpoint, texture, entry)) {
@@ -1007,13 +1046,15 @@ void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
const auto& entries = shader->GetShaderEntries().images;
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto tic = [&] {
const auto tic = [&]() {
if (!entry.IsBindless()) {
return compute.GetTexture(entry.GetOffset()).tic;
}
const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
return compute.GetTextureInfo(tex_handle).tic;
const auto cbuf = entry.GetBindlessCBuf();
Tegra::Texture::TextureHandle tex_handle;
tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
cbuf.first, cbuf.second);
return compute.GetTextureInfo(tex_handle, entry.GetOffset()).tic;
}();
SetupImage(bindpoint, tic, entry);
}
@@ -1054,15 +1095,6 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
}
state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;
state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
bool flip_y = false;
if (regs.viewport_transform[0].scale_y < 0.0) {
flip_y = !flip_y;
}
if (regs.screen_y_control.y_negate != 0) {
flip_y = !flip_y;
}
state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
}
void RasterizerOpenGL::SyncClipEnabled(
@@ -1085,14 +1117,28 @@ void RasterizerOpenGL::SyncClipCoef() {
}
void RasterizerOpenGL::SyncCullMode() {
const auto& regs = system.GPU().Maxwell3D().regs;
auto& maxwell3d = system.GPU().Maxwell3D();
const auto& regs = maxwell3d.regs;
state.cull.enabled = regs.cull.enabled != 0;
if (state.cull.enabled) {
state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
}
state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 ||
regs.viewport_transform[0].scale_y < 0.0f};
// If the GPU is configured to flip the rasterized triangles, then we need to flip the
// notion of front and back. Note: We flip the triangles when the value of the register is 0
// because OpenGL already does it for us.
if (flip_triangles) {
if (state.cull.front_face == GL_CCW)
state.cull.front_face = GL_CW;
else if (state.cull.front_face == GL_CW)
state.cull.front_face = GL_CCW;
}
}
}
void RasterizerOpenGL::SyncPrimitiveRestart() {
@@ -9,16 +9,17 @@
#include <cstddef>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <tuple>
#include <utility>
#include <boost/icl/interval_map.hpp>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/engines/const_buffer_info.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
@@ -51,7 +52,7 @@ namespace OpenGL {
struct ScreenInfo;
struct DrawParameters;
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
ScreenInfo& info);
@@ -72,6 +73,7 @@ public:
const Tegra::Engines::Fermi2D::Config& copy_config) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
void LoadDiskResources(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -226,6 +228,11 @@ private:
AccelDraw accelerate_draw = AccelDraw::Disabled;
OGLFramebuffer clear_framebuffer;
using CachedPageMap = boost::icl::interval_map<u64, int>;
CachedPageMap cached_pages;
std::mutex pages_mutex;
};
} // namespace OpenGL
@@ -394,8 +394,7 @@ Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
params.disk_cache.SaveRaw(ShaderDiskCacheRaw(
params.unique_identifier, GetProgramType(program_type), program_code, program_code_b));
ConstBufferLocker locker(GetEnginesShaderType(GetProgramType(program_type)),
params.system.GPU().Maxwell3D());
ConstBufferLocker locker(GetEnginesShaderType(GetProgramType(program_type)));
const ShaderIR ir(program_code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, locker);
// TODO(Rodrigo): Handle VertexA shaders
// std::optional<ShaderIR> ir_b;
@@ -411,8 +410,7 @@ Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, Prog
params.disk_cache.SaveRaw(
ShaderDiskCacheRaw(params.unique_identifier, ProgramType::Compute, code));
ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute,
params.system.GPU().KeplerCompute());
ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute);
const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, locker);
return std::shared_ptr<CachedShader>(new CachedShader(
params, ProgramType::Compute, GLShader::GetEntries(ir), std::move(code), {}));
@@ -735,7 +735,7 @@ private:
void DeclareImages() {
const auto& images{ir.GetImages()};
for (const auto& image : images) {
for (const auto& [offset, image] : images) {
std::string qualifier = "coherent volatile";
if (image.IsRead() && !image.IsWritten()) {
qualifier += " readonly";
@@ -1670,7 +1670,7 @@ private:
const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
return {GenerateTexture(operation, "Gather",
{TextureAoffi{}, TextureArgument{type, meta->component}}) +
{TextureArgument{type, meta->component}, TextureAoffi{}}) +
GetSwizzle(meta->element),
Type::Float};
}
@@ -1872,6 +1872,10 @@ private:
Expression EmitVertex(Operation operation) {
ASSERT_MSG(stage == ProgramType::Geometry,
"EmitVertex is expected to be used in a geometry shader.");
// If a geometry shader is attached, it will always flip (it's the last stage before
// fragment). For more info about flipping, refer to gl_shader_gen.cpp.
code.AddLine("gl_Position.xy *= viewport_flip.xy;");
code.AddLine("EmitVertex();");
return {};
}
@@ -1879,12 +1883,14 @@ private:
Expression EndPrimitive(Operation operation) {
ASSERT_MSG(stage == ProgramType::Geometry,
"EndPrimitive is expected to be used in a geometry shader.");
code.AddLine("EndPrimitive();");
return {};
}
Expression YNegate(Operation operation) {
return {"y_direction", Type::Float};
// Config pack's third value is Y_NEGATE's state.
return {"config_pack[2]", Type::Uint};
}
template <u32 element>
@@ -2287,13 +2293,10 @@ public:
switch (index) {
case Tegra::Shader::Pred::NeverExecute:
target = "false";
break;
case Tegra::Shader::Pred::UnusedIndex:
target = "true";
break;
default:
target = decomp.GetPredicate(index);
break;
}
} else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
target = decomp.GetInternalFlag(flag->GetFlag());
@@ -2460,16 +2463,16 @@ ShaderEntries GetEntries(const VideoCommon::Shader::ShaderIR& ir) {
entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(),
cbuf.first);
}
for (const auto& [base, usage] : ir.GetGlobalMemory()) {
entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read,
usage.is_written);
}
for (const auto& sampler : ir.GetSamplers()) {
entries.samplers.emplace_back(sampler);
}
for (const auto& image : ir.GetImages()) {
for (const auto& [offset, image] : ir.GetImages()) {
entries.images.emplace_back(image);
}
for (const auto& [base, usage] : ir.GetGlobalMemory()) {
entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read,
usage.is_written);
}
entries.clip_distances = ir.GetClipDistances();
entries.shader_length = ir.GetLength();
return entries;
@@ -82,9 +82,10 @@ private:
struct ShaderEntries {
std::vector<ConstBufferEntry> const_buffers;
std::vector<GlobalMemoryEntry> global_memory_entries;
std::vector<SamplerEntry> samplers;
std::vector<SamplerEntry> bindless_samplers;
std::vector<ImageEntry> images;
std::vector<GlobalMemoryEntry> global_memory_entries;
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
std::size_t shader_length{};
};
@@ -20,7 +20,8 @@ std::string GenerateVertexShader(const Device& device, const ShaderIR& ir, const
std::string out = GetCommonDeclarations();
out += R"(
layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
float y_direction;
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
};
)";
@@ -34,10 +35,23 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
void main() {
execute_vertex();
)";
if (ir_b) {
out += " execute_vertex_b();";
}
out += "}\n";
out += R"(
// Set Position Y direction
gl_Position.y *= utof(config_pack[2]);
// Check if the flip stage is VertexB
// Config pack's second value is flip_stage
if (config_pack[1] == 1) {
// Viewport can be flipped, which is unsupported by glViewport
gl_Position.xy *= viewport_flip.xy;
}
}
)";
return out;
}
@@ -45,7 +59,8 @@ std::string GenerateGeometryShader(const Device& device, const ShaderIR& ir) {
std::string out = GetCommonDeclarations();
out += R"(
layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
float y_direction;
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
};
)";
@@ -72,7 +87,8 @@ layout (location = 6) out vec4 FragColor6;
layout (location = 7) out vec4 FragColor7;
layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
float y_direction;
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
};
)";
@@ -40,11 +40,27 @@ void ProgramManager::UpdatePipeline() {
old_state = current_state;
}
void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {
void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) {
const auto& regs = maxwell.regs;
const auto& state = maxwell.state;
// TODO(bunnei): Support more than one viewport
viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
instance_id = state.current_instance;
// Assign in which stage the position has to be flipped
// (the last stage before the fragment shader).
constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
if (maxwell.regs.shader_config[geometry_index].enable) {
flip_stage = geometry_index;
} else {
flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
}
// Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f;
y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f;
}
} // namespace OpenGL::GLShader
@@ -18,12 +18,17 @@ namespace OpenGL::GLShader {
/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
/// Not following that rule will cause problems on some AMD drivers.
struct alignas(16) MaxwellUniformData {
void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell);
struct MaxwellUniformData {
void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage);
GLfloat y_direction;
alignas(16) GLvec4 viewport_flip;
struct alignas(16) {
GLuint instance_id;
GLuint flip_stage;
GLfloat y_direction;
};
};
static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect");
static_assert(sizeof(MaxwellUniformData) < 16384,
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
+166 -64
View File
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <iterator>
#include <glad/glad.h>
#include "common/assert.h"
@@ -70,29 +69,147 @@ void Enable(GLenum cap, GLuint index, bool enable) {
}
void Enable(GLenum cap, bool& current_value, bool new_value) {
if (UpdateValue(current_value, new_value)) {
if (UpdateValue(current_value, new_value))
Enable(cap, new_value);
}
}
void Enable(GLenum cap, GLuint index, bool& current_value, bool new_value) {
if (UpdateValue(current_value, new_value)) {
if (UpdateValue(current_value, new_value))
Enable(cap, index, new_value);
}
}
} // Anonymous namespace
} // namespace
OpenGLState::OpenGLState() = default;
OpenGLState::OpenGLState() {
// These all match default OpenGL values
framebuffer_srgb.enabled = false;
multisample_control.alpha_to_coverage = false;
multisample_control.alpha_to_one = false;
cull.enabled = false;
cull.mode = GL_BACK;
cull.front_face = GL_CCW;
depth.test_enabled = false;
depth.test_func = GL_LESS;
depth.write_mask = GL_TRUE;
primitive_restart.enabled = false;
primitive_restart.index = 0;
for (auto& item : color_mask) {
item.red_enabled = GL_TRUE;
item.green_enabled = GL_TRUE;
item.blue_enabled = GL_TRUE;
item.alpha_enabled = GL_TRUE;
}
const auto ResetStencil = [](auto& config) {
config.test_func = GL_ALWAYS;
config.test_ref = 0;
config.test_mask = 0xFFFFFFFF;
config.write_mask = 0xFFFFFFFF;
config.action_depth_fail = GL_KEEP;
config.action_depth_pass = GL_KEEP;
config.action_stencil_fail = GL_KEEP;
};
stencil.test_enabled = false;
ResetStencil(stencil.front);
ResetStencil(stencil.back);
for (auto& item : viewports) {
item.x = 0;
item.y = 0;
item.width = 0;
item.height = 0;
item.depth_range_near = 0.0f;
item.depth_range_far = 1.0f;
item.scissor.enabled = false;
item.scissor.x = 0;
item.scissor.y = 0;
item.scissor.width = 0;
item.scissor.height = 0;
}
for (auto& item : blend) {
item.enabled = true;
item.rgb_equation = GL_FUNC_ADD;
item.a_equation = GL_FUNC_ADD;
item.src_rgb_func = GL_ONE;
item.dst_rgb_func = GL_ZERO;
item.src_a_func = GL_ONE;
item.dst_a_func = GL_ZERO;
}
independant_blend.enabled = false;
blend_color.red = 0.0f;
blend_color.green = 0.0f;
blend_color.blue = 0.0f;
blend_color.alpha = 0.0f;
logic_op.enabled = false;
logic_op.operation = GL_COPY;
draw.read_framebuffer = 0;
draw.draw_framebuffer = 0;
draw.vertex_array = 0;
draw.shader_program = 0;
draw.program_pipeline = 0;
clip_distance = {};
point.size = 1;
fragment_color_clamp.enabled = false;
depth_clamp.far_plane = false;
depth_clamp.near_plane = false;
polygon_offset.fill_enable = false;
polygon_offset.line_enable = false;
polygon_offset.point_enable = false;
polygon_offset.factor = 0.0f;
polygon_offset.units = 0.0f;
polygon_offset.clamp = 0.0f;
alpha_test.enabled = false;
alpha_test.func = GL_ALWAYS;
alpha_test.ref = 0.0f;
}
void OpenGLState::SetDefaultViewports() {
viewports.fill(Viewport{});
for (auto& item : viewports) {
item.x = 0;
item.y = 0;
item.width = 0;
item.height = 0;
item.depth_range_near = 0.0f;
item.depth_range_far = 1.0f;
item.scissor.enabled = false;
item.scissor.x = 0;
item.scissor.y = 0;
item.scissor.width = 0;
item.scissor.height = 0;
}
depth_clamp.far_plane = false;
depth_clamp.near_plane = false;
}
void OpenGLState::ApplyFramebufferState() {
void OpenGLState::ApplyDefaultState() {
glEnable(GL_BLEND);
glDisable(GL_FRAMEBUFFER_SRGB);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_PRIMITIVE_RESTART);
glDisable(GL_STENCIL_TEST);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_SCISSOR_TEST);
}
void OpenGLState::ApplyFramebufferState() const {
if (UpdateValue(cur_state.draw.read_framebuffer, draw.read_framebuffer)) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
}
@@ -101,52 +218,52 @@ void OpenGLState::ApplyFramebufferState() {
}
}
void OpenGLState::ApplyVertexArrayState() {
void OpenGLState::ApplyVertexArrayState() const {
if (UpdateValue(cur_state.draw.vertex_array, draw.vertex_array)) {
glBindVertexArray(draw.vertex_array);
}
}
void OpenGLState::ApplyShaderProgram() {
void OpenGLState::ApplyShaderProgram() const {
if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) {
glUseProgram(draw.shader_program);
}
}
void OpenGLState::ApplyProgramPipeline() {
void OpenGLState::ApplyProgramPipeline() const {
if (UpdateValue(cur_state.draw.program_pipeline, draw.program_pipeline)) {
glBindProgramPipeline(draw.program_pipeline);
}
}
void OpenGLState::ApplyClipDistances() {
void OpenGLState::ApplyClipDistances() const {
for (std::size_t i = 0; i < clip_distance.size(); ++i) {
Enable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i), cur_state.clip_distance[i],
clip_distance[i]);
}
}
void OpenGLState::ApplyPointSize() {
void OpenGLState::ApplyPointSize() const {
if (UpdateValue(cur_state.point.size, point.size)) {
glPointSize(point.size);
}
}
void OpenGLState::ApplyFragmentColorClamp() {
void OpenGLState::ApplyFragmentColorClamp() const {
if (UpdateValue(cur_state.fragment_color_clamp.enabled, fragment_color_clamp.enabled)) {
glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
fragment_color_clamp.enabled ? GL_TRUE : GL_FALSE);
}
}
void OpenGLState::ApplyMultisample() {
void OpenGLState::ApplyMultisample() const {
Enable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur_state.multisample_control.alpha_to_coverage,
multisample_control.alpha_to_coverage);
Enable(GL_SAMPLE_ALPHA_TO_ONE, cur_state.multisample_control.alpha_to_one,
multisample_control.alpha_to_one);
}
void OpenGLState::ApplyDepthClamp() {
void OpenGLState::ApplyDepthClamp() const {
if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
return;
@@ -159,7 +276,7 @@ void OpenGLState::ApplyDepthClamp() {
Enable(GL_DEPTH_CLAMP, depth_clamp.far_plane || depth_clamp.near_plane);
}
void OpenGLState::ApplySRgb() {
void OpenGLState::ApplySRgb() const {
if (cur_state.framebuffer_srgb.enabled == framebuffer_srgb.enabled)
return;
cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled;
@@ -170,7 +287,7 @@ void OpenGLState::ApplySRgb() {
}
}
void OpenGLState::ApplyCulling() {
void OpenGLState::ApplyCulling() const {
Enable(GL_CULL_FACE, cur_state.cull.enabled, cull.enabled);
if (UpdateValue(cur_state.cull.mode, cull.mode)) {
@@ -182,12 +299,7 @@ void OpenGLState::ApplyCulling() {
}
}
void OpenGLState::ApplyColorMask() {
if (!dirty.color_mask) {
return;
}
dirty.color_mask = false;
void OpenGLState::ApplyColorMask() const {
for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
const auto& updated = color_mask[i];
auto& current = cur_state.color_mask[i];
@@ -202,7 +314,7 @@ void OpenGLState::ApplyColorMask() {
}
}
void OpenGLState::ApplyDepth() {
void OpenGLState::ApplyDepth() const {
Enable(GL_DEPTH_TEST, cur_state.depth.test_enabled, depth.test_enabled);
if (cur_state.depth.test_func != depth.test_func) {
@@ -216,7 +328,7 @@ void OpenGLState::ApplyDepth() {
}
}
void OpenGLState::ApplyPrimitiveRestart() {
void OpenGLState::ApplyPrimitiveRestart() const {
Enable(GL_PRIMITIVE_RESTART, cur_state.primitive_restart.enabled, primitive_restart.enabled);
if (cur_state.primitive_restart.index != primitive_restart.index) {
@@ -225,12 +337,7 @@ void OpenGLState::ApplyPrimitiveRestart() {
}
}
void OpenGLState::ApplyStencilTest() {
if (!dirty.stencil_state) {
return;
}
dirty.stencil_state = false;
void OpenGLState::ApplyStencilTest() const {
Enable(GL_STENCIL_TEST, cur_state.stencil.test_enabled, stencil.test_enabled);
const auto ConfigStencil = [](GLenum face, const auto& config, auto& current) {
@@ -259,7 +366,7 @@ void OpenGLState::ApplyStencilTest() {
ConfigStencil(GL_BACK, stencil.back, cur_state.stencil.back);
}
void OpenGLState::ApplyViewport() {
void OpenGLState::ApplyViewport() const {
for (GLuint i = 0; i < static_cast<GLuint>(Maxwell::NumViewports); ++i) {
const auto& updated = viewports[i];
auto& current = cur_state.viewports[i];
@@ -296,7 +403,7 @@ void OpenGLState::ApplyViewport() {
}
}
void OpenGLState::ApplyGlobalBlending() {
void OpenGLState::ApplyGlobalBlending() const {
const Blend& updated = blend[0];
Blend& current = cur_state.blend[0];
@@ -320,7 +427,7 @@ void OpenGLState::ApplyGlobalBlending() {
}
}
void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) {
void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
const Blend& updated = blend[target];
Blend& current = cur_state.blend[target];
@@ -344,12 +451,7 @@ void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) {
}
}
void OpenGLState::ApplyBlending() {
if (!dirty.blend_state) {
return;
}
dirty.blend_state = false;
void OpenGLState::ApplyBlending() const {
if (independant_blend.enabled) {
const bool force = independant_blend.enabled != cur_state.independant_blend.enabled;
for (std::size_t target = 0; target < Maxwell::NumRenderTargets; ++target) {
@@ -368,7 +470,7 @@ void OpenGLState::ApplyBlending() {
}
}
void OpenGLState::ApplyLogicOp() {
void OpenGLState::ApplyLogicOp() const {
Enable(GL_COLOR_LOGIC_OP, cur_state.logic_op.enabled, logic_op.enabled);
if (UpdateValue(cur_state.logic_op.operation, logic_op.operation)) {
@@ -376,12 +478,7 @@ void OpenGLState::ApplyLogicOp() {
}
}
void OpenGLState::ApplyPolygonOffset() {
if (!dirty.polygon_offset) {
return;
}
dirty.polygon_offset = false;
void OpenGLState::ApplyPolygonOffset() const {
Enable(GL_POLYGON_OFFSET_FILL, cur_state.polygon_offset.fill_enable,
polygon_offset.fill_enable);
Enable(GL_POLYGON_OFFSET_LINE, cur_state.polygon_offset.line_enable,
@@ -402,7 +499,7 @@ void OpenGLState::ApplyPolygonOffset() {
}
}
void OpenGLState::ApplyAlphaTest() {
void OpenGLState::ApplyAlphaTest() const {
Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled);
if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref),
std::tie(alpha_test.func, alpha_test.ref))) {
@@ -410,25 +507,19 @@ void OpenGLState::ApplyAlphaTest() {
}
}
void OpenGLState::ApplyClipControl() {
if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) {
glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE);
}
}
void OpenGLState::ApplyTextures() {
void OpenGLState::ApplyTextures() const {
if (const auto update = UpdateArray(cur_state.textures, textures)) {
glBindTextures(update->first, update->second, textures.data() + update->first);
}
}
void OpenGLState::ApplySamplers() {
void OpenGLState::ApplySamplers() const {
if (const auto update = UpdateArray(cur_state.samplers, samplers)) {
glBindSamplers(update->first, update->second, samplers.data() + update->first);
}
}
void OpenGLState::ApplyImages() {
void OpenGLState::ApplyImages() const {
if (const auto update = UpdateArray(cur_state.images, images)) {
glBindImageTextures(update->first, update->second, images.data() + update->first);
}
@@ -444,22 +535,33 @@ void OpenGLState::Apply() {
ApplyPointSize();
ApplyFragmentColorClamp();
ApplyMultisample();
ApplyColorMask();
if (dirty.color_mask) {
ApplyColorMask();
dirty.color_mask = false;
}
ApplyDepthClamp();
ApplyViewport();
ApplyStencilTest();
if (dirty.stencil_state) {
ApplyStencilTest();
dirty.stencil_state = false;
}
ApplySRgb();
ApplyCulling();
ApplyDepth();
ApplyPrimitiveRestart();
ApplyBlending();
if (dirty.blend_state) {
ApplyBlending();
dirty.blend_state = false;
}
ApplyLogicOp();
ApplyTextures();
ApplySamplers();
ApplyImages();
ApplyPolygonOffset();
if (dirty.polygon_offset) {
ApplyPolygonOffset();
dirty.polygon_offset = false;
}
ApplyAlphaTest();
ApplyClipControl();
}
void OpenGLState::EmulateViewportWithScissor() {
+123 -104
View File
@@ -5,150 +5,168 @@
#pragma once
#include <array>
#include <type_traits>
#include <glad/glad.h>
#include "video_core/engines/maxwell_3d.h"
namespace OpenGL {
namespace TextureUnits {
struct TextureUnit {
GLint id;
constexpr GLenum Enum() const {
return static_cast<GLenum>(GL_TEXTURE0 + id);
}
};
constexpr TextureUnit MaxwellTexture(int unit) {
return TextureUnit{unit};
}
constexpr TextureUnit LightingLUT{3};
constexpr TextureUnit FogLUT{4};
constexpr TextureUnit ProcTexNoiseLUT{5};
constexpr TextureUnit ProcTexColorMap{6};
constexpr TextureUnit ProcTexAlphaMap{7};
constexpr TextureUnit ProcTexLUT{8};
constexpr TextureUnit ProcTexDiffLUT{9};
} // namespace TextureUnits
class OpenGLState {
public:
struct {
bool enabled = false; // GL_FRAMEBUFFER_SRGB
bool enabled; // GL_FRAMEBUFFER_SRGB
} framebuffer_srgb;
struct {
bool alpha_to_coverage = false; // GL_ALPHA_TO_COVERAGE
bool alpha_to_one = false; // GL_ALPHA_TO_ONE
bool alpha_to_coverage; // GL_ALPHA_TO_COVERAGE
bool alpha_to_one; // GL_ALPHA_TO_ONE
} multisample_control;
struct {
bool enabled = false; // GL_CLAMP_FRAGMENT_COLOR_ARB
bool enabled; // GL_CLAMP_FRAGMENT_COLOR_ARB
} fragment_color_clamp;
struct {
bool far_plane = false;
bool near_plane = false;
bool far_plane;
bool near_plane;
} depth_clamp; // GL_DEPTH_CLAMP
struct {
bool enabled = false; // GL_CULL_FACE
GLenum mode = GL_BACK; // GL_CULL_FACE_MODE
GLenum front_face = GL_CCW; // GL_FRONT_FACE
bool enabled; // GL_CULL_FACE
GLenum mode; // GL_CULL_FACE_MODE
GLenum front_face; // GL_FRONT_FACE
} cull;
struct {
bool test_enabled = false; // GL_DEPTH_TEST
GLboolean write_mask = GL_TRUE; // GL_DEPTH_WRITEMASK
GLenum test_func = GL_LESS; // GL_DEPTH_FUNC
bool test_enabled; // GL_DEPTH_TEST
GLenum test_func; // GL_DEPTH_FUNC
GLboolean write_mask; // GL_DEPTH_WRITEMASK
} depth;
struct {
bool enabled = false;
GLuint index = 0;
bool enabled;
GLuint index;
} primitive_restart; // GL_PRIMITIVE_RESTART
struct ColorMask {
GLboolean red_enabled = GL_TRUE;
GLboolean green_enabled = GL_TRUE;
GLboolean blue_enabled = GL_TRUE;
GLboolean alpha_enabled = GL_TRUE;
GLboolean red_enabled;
GLboolean green_enabled;
GLboolean blue_enabled;
GLboolean alpha_enabled;
};
std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
color_mask; // GL_COLOR_WRITEMASK
struct {
bool test_enabled = false; // GL_STENCIL_TEST
bool test_enabled; // GL_STENCIL_TEST
struct {
GLenum test_func = GL_ALWAYS; // GL_STENCIL_FUNC
GLint test_ref = 0; // GL_STENCIL_REF
GLuint test_mask = 0xFFFFFFFF; // GL_STENCIL_VALUE_MASK
GLuint write_mask = 0xFFFFFFFF; // GL_STENCIL_WRITEMASK
GLenum action_stencil_fail = GL_KEEP; // GL_STENCIL_FAIL
GLenum action_depth_fail = GL_KEEP; // GL_STENCIL_PASS_DEPTH_FAIL
GLenum action_depth_pass = GL_KEEP; // GL_STENCIL_PASS_DEPTH_PASS
GLenum test_func; // GL_STENCIL_FUNC
GLint test_ref; // GL_STENCIL_REF
GLuint test_mask; // GL_STENCIL_VALUE_MASK
GLuint write_mask; // GL_STENCIL_WRITEMASK
GLenum action_stencil_fail; // GL_STENCIL_FAIL
GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL
GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS
} front, back;
} stencil;
struct Blend {
bool enabled = false; // GL_BLEND
GLenum rgb_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_RGB
GLenum a_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_ALPHA
GLenum src_rgb_func = GL_ONE; // GL_BLEND_SRC_RGB
GLenum dst_rgb_func = GL_ZERO; // GL_BLEND_DST_RGB
GLenum src_a_func = GL_ONE; // GL_BLEND_SRC_ALPHA
GLenum dst_a_func = GL_ZERO; // GL_BLEND_DST_ALPHA
bool enabled; // GL_BLEND
GLenum rgb_equation; // GL_BLEND_EQUATION_RGB
GLenum a_equation; // GL_BLEND_EQUATION_ALPHA
GLenum src_rgb_func; // GL_BLEND_SRC_RGB
GLenum dst_rgb_func; // GL_BLEND_DST_RGB
GLenum src_a_func; // GL_BLEND_SRC_ALPHA
GLenum dst_a_func; // GL_BLEND_DST_ALPHA
};
std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend;
struct {
bool enabled = false;
bool enabled;
} independant_blend;
struct {
GLclampf red = 0.0f;
GLclampf green = 0.0f;
GLclampf blue = 0.0f;
GLclampf alpha = 0.0f;
GLclampf red;
GLclampf green;
GLclampf blue;
GLclampf alpha;
} blend_color; // GL_BLEND_COLOR
struct {
bool enabled = false; // GL_LOGIC_OP_MODE
GLenum operation = GL_COPY;
bool enabled; // GL_LOGIC_OP_MODE
GLenum operation;
} logic_op;
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures = {};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers = {};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images = {};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{};
struct {
GLuint read_framebuffer = 0; // GL_READ_FRAMEBUFFER_BINDING
GLuint draw_framebuffer = 0; // GL_DRAW_FRAMEBUFFER_BINDING
GLuint vertex_array = 0; // GL_VERTEX_ARRAY_BINDING
GLuint shader_program = 0; // GL_CURRENT_PROGRAM
GLuint program_pipeline = 0; // GL_PROGRAM_PIPELINE_BINDING
GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING
GLuint shader_program; // GL_CURRENT_PROGRAM
GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
} draw;
struct Viewport {
GLint x = 0;
GLint y = 0;
GLint width = 0;
GLint height = 0;
GLfloat depth_range_near = 0.0f; // GL_DEPTH_RANGE
GLfloat depth_range_far = 1.0f; // GL_DEPTH_RANGE
struct viewport {
GLint x;
GLint y;
GLint width;
GLint height;
GLfloat depth_range_near; // GL_DEPTH_RANGE
GLfloat depth_range_far; // GL_DEPTH_RANGE
struct {
bool enabled = false; // GL_SCISSOR_TEST
GLint x = 0;
GLint y = 0;
GLsizei width = 0;
GLsizei height = 0;
bool enabled; // GL_SCISSOR_TEST
GLint x;
GLint y;
GLsizei width;
GLsizei height;
} scissor;
};
std::array<Viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
struct {
float size = 1.0f; // GL_POINT_SIZE
float size; // GL_POINT_SIZE
} point;
struct {
bool point_enable = false;
bool line_enable = false;
bool fill_enable = false;
GLfloat units = 0.0f;
GLfloat factor = 0.0f;
GLfloat clamp = 0.0f;
bool point_enable;
bool line_enable;
bool fill_enable;
GLfloat units;
GLfloat factor;
GLfloat clamp;
} polygon_offset;
struct {
bool enabled = false; // GL_ALPHA_TEST
GLenum func = GL_ALWAYS; // GL_ALPHA_TEST_FUNC
GLfloat ref = 0.0f; // GL_ALPHA_TEST_REF
bool enabled; // GL_ALPHA_TEST
GLenum func; // GL_ALPHA_TEST_FUNC
GLfloat ref; // GL_ALPHA_TEST_REF
} alpha_test;
std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE
struct {
GLenum origin = GL_LOWER_LEFT;
} clip_control;
std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE
OpenGLState();
@@ -161,32 +179,34 @@ public:
/// Apply this state as the current OpenGL state
void Apply();
void ApplyFramebufferState();
void ApplyVertexArrayState();
void ApplyShaderProgram();
void ApplyProgramPipeline();
void ApplyClipDistances();
void ApplyPointSize();
void ApplyFragmentColorClamp();
void ApplyMultisample();
void ApplySRgb();
void ApplyCulling();
void ApplyColorMask();
void ApplyDepth();
void ApplyPrimitiveRestart();
void ApplyStencilTest();
void ApplyViewport();
void ApplyTargetBlending(std::size_t target, bool force);
void ApplyGlobalBlending();
void ApplyBlending();
void ApplyLogicOp();
void ApplyTextures();
void ApplySamplers();
void ApplyImages();
void ApplyDepthClamp();
void ApplyPolygonOffset();
void ApplyAlphaTest();
void ApplyClipControl();
void ApplyFramebufferState() const;
void ApplyVertexArrayState() const;
void ApplyShaderProgram() const;
void ApplyProgramPipeline() const;
void ApplyClipDistances() const;
void ApplyPointSize() const;
void ApplyFragmentColorClamp() const;
void ApplyMultisample() const;
void ApplySRgb() const;
void ApplyCulling() const;
void ApplyColorMask() const;
void ApplyDepth() const;
void ApplyPrimitiveRestart() const;
void ApplyStencilTest() const;
void ApplyViewport() const;
void ApplyTargetBlending(std::size_t target, bool force) const;
void ApplyGlobalBlending() const;
void ApplyBlending() const;
void ApplyLogicOp() const;
void ApplyTextures() const;
void ApplySamplers() const;
void ApplyImages() const;
void ApplyDepthClamp() const;
void ApplyPolygonOffset() const;
void ApplyAlphaTest() const;
/// Set the initial OpenGL state
static void ApplyDefaultState();
/// Resets any references to the given resource
OpenGLState& UnbindTexture(GLuint handle);
@@ -233,6 +253,5 @@ private:
bool color_mask;
} dirty{};
};
static_assert(std::is_trivially_copyable_v<OpenGLState>);
} // namespace OpenGL
@@ -131,7 +131,6 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X6_SRGB
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5_SRGB
{GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, ComponentType::Float, false}, // E5B9G9R9F
// Depth formats
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
@@ -1682,13 +1682,10 @@ public:
switch (index) {
case Tegra::Shader::Pred::NeverExecute:
target = decomp.v_false;
break;
case Tegra::Shader::Pred::UnusedIndex:
target = decomp.v_true;
break;
default:
target = decomp.predicates.at(index);
break;
}
} else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag()));
+104 -112
View File
@@ -16,9 +16,7 @@
#include "video_core/shader/shader_ir.h"
namespace VideoCommon::Shader {
namespace {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
@@ -70,15 +68,15 @@ struct CFGRebuildState {
const ProgramCode& program_code;
ConstBufferLocker& locker;
u32 start{};
std::vector<BlockInfo> block_info;
std::list<u32> inspect_queries;
std::list<Query> queries;
std::unordered_map<u32, u32> registered;
std::set<u32> labels;
std::map<u32, u32> ssy_labels;
std::map<u32, u32> pbk_labels;
std::unordered_map<u32, BlockStack> stacks;
ASTManager* manager{};
std::vector<BlockInfo> block_info{};
std::list<u32> inspect_queries{};
std::list<Query> queries{};
std::unordered_map<u32, u32> registered{};
std::set<u32> labels{};
std::map<u32, u32> ssy_labels{};
std::map<u32, u32> pbk_labels{};
std::unordered_map<u32, BlockStack> stacks{};
ASTManager* manager;
};
enum class BlockCollision : u32 { None, Found, Inside };
@@ -111,7 +109,7 @@ BlockInfo& CreateBlockInfo(CFGRebuildState& state, u32 start, u32 end) {
}
Pred GetPredicate(u32 index, bool negated) {
return static_cast<Pred>(static_cast<u64>(index) + (negated ? 8ULL : 0ULL));
return static_cast<Pred>(index + (negated ? 8 : 0));
}
/**
@@ -138,13 +136,15 @@ struct BranchIndirectInfo {
s32 relative_position{};
};
struct BufferInfo {
u32 index;
u32 offset;
};
std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state,
u32 start_address, u32 current_position) {
const u32 shader_start = state.start;
u32 pos = current_position;
BranchIndirectInfo result{};
u64 track_register = 0;
std::optional<std::pair<s32, u64>> GetBRXInfo(const CFGRebuildState& state, u32& pos) {
const Instruction instr = state.program_code[pos];
// Step 0 Get BRX Info
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() != OpCode::Id::BRX) {
return std::nullopt;
@@ -152,94 +152,86 @@ std::optional<std::pair<s32, u64>> GetBRXInfo(const CFGRebuildState& state, u32&
if (instr.brx.constant_buffer != 0) {
return std::nullopt;
}
--pos;
return std::make_pair(instr.brx.GetBranchExtend(), instr.gpr8.Value());
}
track_register = instr.gpr8.Value();
result.relative_position = instr.brx.GetBranchExtend();
pos--;
bool found_track = false;
template <typename Result, typename TestCallable, typename PackCallable>
// requires std::predicate<TestCallable, Instruction, const OpCode::Matcher&>
// requires std::invocable<PackCallable, Instruction, const OpCode::Matcher&>
std::optional<Result> TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test,
PackCallable pack) {
for (; pos >= state.start; --pos) {
if (IsSchedInstruction(pos, state.start)) {
// Step 1 Track LDC
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
const Instruction instr = state.program_code[pos];
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (!opcode) {
if (opcode->get().GetId() == OpCode::Id::LD_C) {
if (instr.gpr0.Value() == track_register &&
instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) {
result.buffer = instr.cbuf36.index;
result.offset = instr.cbuf36.GetOffset();
track_register = instr.gpr8.Value();
pos--;
found_track = true;
break;
}
}
pos--;
}
if (!found_track) {
return std::nullopt;
}
found_track = false;
// Step 2 Track SHL
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
if (test(instr, opcode->get())) {
--pos;
return std::make_optional(pack(instr, opcode->get()));
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::SHL_IMM) {
if (instr.gpr0.Value() == track_register) {
track_register = instr.gpr8.Value();
pos--;
found_track = true;
break;
}
}
pos--;
}
return std::nullopt;
}
std::optional<std::pair<BufferInfo, u64>> TrackLDC(const CFGRebuildState& state, u32& pos,
u64 brx_tracked_register) {
return TrackInstruction<std::pair<BufferInfo, u64>>(
state, pos,
[brx_tracked_register](auto instr, const auto& opcode) {
return opcode.GetId() == OpCode::Id::LD_C &&
instr.gpr0.Value() == brx_tracked_register &&
instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single;
},
[](auto instr, const auto& opcode) {
const BufferInfo info = {static_cast<u32>(instr.cbuf36.index.Value()),
static_cast<u32>(instr.cbuf36.GetOffset())};
return std::make_pair(info, instr.gpr8.Value());
});
}
std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos,
u64 ldc_tracked_register) {
return TrackInstruction<u64>(state, pos,
[ldc_tracked_register](auto instr, const auto& opcode) {
return opcode.GetId() == OpCode::Id::SHL_IMM &&
instr.gpr0.Value() == ldc_tracked_register;
},
[](auto instr, const auto&) { return instr.gpr8.Value(); });
}
std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos,
u64 shl_tracked_register) {
return TrackInstruction<u32>(state, pos,
[shl_tracked_register](auto instr, const auto& opcode) {
return opcode.GetId() == OpCode::Id::IMNMX_IMM &&
instr.gpr0.Value() == shl_tracked_register;
},
[](auto instr, const auto&) {
return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1);
});
}
std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) {
const auto brx_info = GetBRXInfo(state, pos);
if (!brx_info) {
if (!found_track) {
return std::nullopt;
}
const auto [relative_position, brx_tracked_register] = *brx_info;
found_track = false;
const auto ldc_info = TrackLDC(state, pos, brx_tracked_register);
if (!ldc_info) {
return std::nullopt;
}
const auto [buffer_info, ldc_tracked_register] = *ldc_info;
const auto shl_tracked_register = TrackSHLRegister(state, pos, ldc_tracked_register);
if (!shl_tracked_register) {
return std::nullopt;
// Step 3 Track IMNMX
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
if (instr.gpr0.Value() == track_register) {
track_register = instr.gpr8.Value();
result.entries = instr.alu.GetSignedImm20_20() + 1;
pos--;
found_track = true;
break;
}
}
pos--;
}
const auto entries = TrackIMNMXValue(state, pos, *shl_tracked_register);
if (!entries) {
if (!found_track) {
return std::nullopt;
}
return BranchIndirectInfo{buffer_info.index, buffer_info.offset, *entries, relative_position};
return {result};
}
std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
@@ -428,30 +420,30 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
break;
}
case OpCode::Id::BRX: {
const auto tmp = TrackBranchIndirectInfo(state, offset);
if (!tmp) {
LOG_WARNING(HW_GPU, "BRX Track Unsuccesful");
return {ParseResult::AbnormalFlow, parse_info};
}
const auto result = *tmp;
const s32 pc_target = offset + result.relative_position;
std::vector<CaseBranch> branches;
for (u32 i = 0; i < result.entries; i++) {
auto key = state.locker.ObtainKey(result.buffer, result.offset + i * 4);
if (!key) {
return {ParseResult::AbnormalFlow, parse_info};
auto tmp = TrackBranchIndirectInfo(state, address, offset);
if (tmp) {
auto result = *tmp;
std::vector<CaseBranch> branches{};
s32 pc_target = offset + result.relative_position;
for (u32 i = 0; i < result.entries; i++) {
auto k = state.locker.ObtainKey(result.buffer, result.offset + i * 4);
if (!k) {
return {ParseResult::AbnormalFlow, parse_info};
}
u32 value = *k;
u32 target = static_cast<u32>((value >> 3) + pc_target);
insert_label(state, target);
branches.emplace_back(value, target);
}
u32 value = *key;
u32 target = static_cast<u32>((value >> 3) + pc_target);
insert_label(state, target);
branches.emplace_back(value, target);
}
parse_info.end_address = offset;
parse_info.branch_info = MakeBranchInfo<MultiBranch>(
static_cast<u32>(instr.gpr8.Value()), std::move(branches));
parse_info.end_address = offset;
parse_info.branch_info = MakeBranchInfo<MultiBranch>(
static_cast<u32>(instr.gpr8.Value()), std::move(branches));
return {ParseResult::ControlCaught, parse_info};
return {ParseResult::ControlCaught, parse_info};
} else {
LOG_WARNING(HW_GPU, "BRX Track Unsuccesful");
}
return {ParseResult::AbnormalFlow, parse_info};
}
default:
break;
+1 -1
View File
@@ -155,7 +155,7 @@ void ShaderIR::Decode() {
[[fallthrough]];
case CompileDepth::BruteForce: {
coverage_begin = main_offset;
const std::size_t shader_end = program_code.size();
const u32 shader_end = program_code.size();
coverage_end = shader_end;
for (u32 label = main_offset; label < shader_end; label++) {
basic_blocks.insert({label, DecodeRange(label, label + 1)});
+5 -6
View File
@@ -43,12 +43,12 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
case OpCode::Id::FMUL_IMM: {
// FMUL does not have 'abs' bits and only the second operand has a 'neg' bit.
if (instr.fmul.tab5cb8_2 != 0) {
LOG_DEBUG(HW_GPU, "FMUL tab5cb8_2({}) is not implemented",
instr.fmul.tab5cb8_2.Value());
LOG_WARNING(HW_GPU, "FMUL tab5cb8_2({}) is not implemented",
instr.fmul.tab5cb8_2.Value());
}
if (instr.fmul.tab5c68_0 != 1) {
LOG_DEBUG(HW_GPU, "FMUL tab5cb8_0({}) is not implemented",
instr.fmul.tab5c68_0.Value());
LOG_WARNING(HW_GPU, "FMUL tab5cb8_0({}) is not implemented",
instr.fmul.tab5c68_0.Value());
}
op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b);
@@ -144,11 +144,10 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
case OpCode::Id::RRO_C:
case OpCode::Id::RRO_R:
case OpCode::Id::RRO_IMM: {
LOG_DEBUG(HW_GPU, "(STUBBED) RRO used");
// Currently RRO is only implemented as a register move.
op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b);
SetRegister(bb, instr.gpr0, op_b);
LOG_WARNING(HW_GPU, "RRO instruction is incomplete");
break;
}
default:
@@ -21,8 +21,8 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
if (opcode->get().GetId() == OpCode::Id::HADD2_C ||
opcode->get().GetId() == OpCode::Id::HADD2_R) {
if (instr.alu_half.ftz == 0) {
LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
if (instr.alu_half.ftz != 0) {
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
}
}
@@ -19,12 +19,12 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) {
if (instr.alu_half_imm.ftz == 0) {
LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
if (instr.alu_half_imm.ftz != 0) {
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
}
} else {
if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::FTZ) {
LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None) {
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
}
}
@@ -144,7 +144,7 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
case OpCode::Id::ICMP_IMM: {
const Node zero = Immediate(0);
const auto [op_rhs, test] = [&]() -> std::pair<Node, Node> {
const auto [op_b, test] = [&]() -> std::pair<Node, Node> {
switch (opcode->get().GetId()) {
case OpCode::Id::ICMP_CR:
return {GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset),
@@ -161,10 +161,10 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
return {zero, zero};
}
}();
const Node op_lhs = GetRegister(instr.gpr8);
const Node op_a = GetRegister(instr.gpr8);
const Node comparison =
GetPredicateComparisonInteger(instr.icmp.cond, instr.icmp.is_signed != 0, test, zero);
SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_lhs, op_rhs));
SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_a, op_b));
break;
}
case OpCode::Id::LOP_C:
+2 -2
View File
@@ -19,10 +19,10 @@ u32 ShaderIR::DecodeFfma(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.ffma.cc != 0, "FFMA cc not implemented");
if (instr.ffma.tab5980_0 != 1) {
LOG_DEBUG(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value());
LOG_WARNING(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value());
}
if (instr.ffma.tab5980_1 != 0) {
LOG_DEBUG(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value());
LOG_WARNING(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value());
}
const Node op_a = GetRegister(instr.gpr8);
+2 -2
View File
@@ -20,8 +20,8 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
if (instr.hset2.ftz == 0) {
LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
if (instr.hset2.ftz != 0) {
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
}
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a);
@@ -19,9 +19,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
if (instr.hsetp2.ftz != 0) {
LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
}
LOG_DEBUG(HW_GPU, "ftz={}", static_cast<u32>(instr.hsetp2.ftz));
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a);
op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
+25 -23
View File
@@ -143,37 +143,39 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
}
Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
const auto offset = static_cast<u32>(image.index.Value());
const auto it =
std::find_if(std::begin(used_images), std::end(used_images),
[offset](const Image& entry) { return entry.GetOffset() == offset; });
if (it != std::end(used_images)) {
ASSERT(!it->IsBindless() && it->GetType() == it->GetType());
return *it;
const auto offset{static_cast<std::size_t>(image.index.Value())};
if (const auto image = TryUseExistingImage(offset, type)) {
return *image;
}
const auto next_index = static_cast<u32>(used_images.size());
return used_images.emplace_back(next_index, offset, type);
const std::size_t next_index{used_images.size()};
return used_images.emplace(offset, Image{offset, next_index, type}).first->second;
}
Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) {
const Node image_register = GetRegister(reg);
const auto [base_image, buffer, offset] =
TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()));
const Node image_register{GetRegister(reg)};
const auto [base_image, cbuf_index, cbuf_offset]{
TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))};
const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)};
const auto it =
std::find_if(std::begin(used_images), std::end(used_images),
[buffer = buffer, offset = offset](const Image& entry) {
return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
});
if (it != std::end(used_images)) {
ASSERT(it->IsBindless() && it->GetType() == it->GetType());
return *it;
if (const auto image = TryUseExistingImage(cbuf_key, type)) {
return *image;
}
const auto next_index = static_cast<u32>(used_images.size());
return used_images.emplace_back(next_index, offset, buffer, type);
const std::size_t next_index{used_images.size()};
return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type})
.first->second;
}
Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) {
auto it = used_images.find(offset);
if (it == used_images.end()) {
return nullptr;
}
auto& image = it->second;
ASSERT(image.GetType() == type);
return &image;
}
} // namespace VideoCommon::Shader
Loaded 100 of 122 files, more files were not shown because too many files have changed in this diff. Show more