diff options
79 files changed, 1430 insertions, 713 deletions
diff --git a/.ci/scripts/common/post-upload.sh b/.ci/scripts/common/post-upload.sh index bb4e9d328..b80868635 100644 --- a/.ci/scripts/common/post-upload.sh +++ b/.ci/scripts/common/post-upload.sh @@ -1,12 +1,12 @@ #!/bin/bash -ex # Copy documentation -cp license.txt "$REV_NAME" -cp README.md "$REV_NAME" +cp license.txt "$DIR_NAME" +cp README.md "$DIR_NAME" -tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME" +tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME" -mv "$REV_NAME" $RELEASE_NAME +mv "$DIR_NAME" $RELEASE_NAME 7z a "$REV_NAME.7z" $RELEASE_NAME diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index 090ca75f1..5559a527c 100644 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh @@ -11,5 +11,4 @@ ninja ccache -s -# Ignore zlib's tests, since they aren't gated behind a CMake option. -ctest -VV -E "(example|example64)" -C Release +ctest -VV -C Release diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh index 0d131d1dd..fe4e6b2ac 100644 --- a/.ci/scripts/linux/upload.sh +++ b/.ci/scripts/linux/upload.sh @@ -6,9 +6,15 @@ REV_NAME="yuzu-linux-${GITDATE}-${GITREV}" ARCHIVE_NAME="${REV_NAME}.tar.xz" COMPRESSION_FLAGS="-cJvf" -mkdir "$REV_NAME" +if [ "${RELEASE_NAME}" = "mainline" ]; then + DIR_NAME="${REV_NAME}" +else + DIR_NAME="${REV_NAME}_${RELEASE_NAME}" +fi -cp build/bin/yuzu-cmd "$REV_NAME" -cp build/bin/yuzu "$REV_NAME" +mkdir "$DIR_NAME" + +cp build/bin/yuzu-cmd "$DIR_NAME" +cp build/bin/yuzu "$DIR_NAME" . .ci/scripts/common/post-upload.sh diff --git a/.ci/scripts/windows/upload.ps1 b/.ci/scripts/windows/upload.ps1 index 3cb709924..e34e6681f 100644 --- a/.ci/scripts/windows/upload.ps1 +++ b/.ci/scripts/windows/upload.ps1 @@ -1,6 +1,13 @@ +param($BUILD_NAME) + $GITDATE = $(git show -s --date=short --format='%ad') -replace "-","" $GITREV = $(git show -s --format='%h') -$RELEASE_DIST = "yuzu-windows-msvc" + +if ("$BUILD_NAME" -eq "mainline") { + $RELEASE_DIST = "yuzu-windows-msvc" +} else { + $RELEASE_DIST = "yuzu-windows-msvc-$BUILD_NAME" +} $MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", "" $MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", "" diff --git a/.ci/scripts/windows/upload.sh b/.ci/scripts/windows/upload.sh index de73d3541..ebf5b7dc1 100644 --- a/.ci/scripts/windows/upload.sh +++ b/.ci/scripts/windows/upload.sh @@ -6,8 +6,14 @@ REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}" ARCHIVE_NAME="${REV_NAME}.tar.gz" COMPRESSION_FLAGS="-czvf" -mkdir "$REV_NAME" +if [ "${RELEASE_NAME}" = "mainline" ]; then + DIR_NAME="${REV_NAME}" +else + DIR_NAME="${REV_NAME}_${RELEASE_NAME}" +fi + +mkdir "$DIR_NAME" # get around the permission issues -cp -r package/* "$REV_NAME" +cp -r package/* "$DIR_NAME" . .ci/scripts/common/post-upload.sh diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml index b44a08247..52cebaee0 100644 --- a/.ci/templates/build-msvc.yml +++ b/.ci/templates/build-msvc.yml @@ -17,6 +17,7 @@ steps: inputs: targetType: 'filePath' filePath: './.ci/scripts/windows/upload.ps1' + arguments: '$(BuildName)' - publish: artifacts artifact: 'yuzu-$(BuildName)-windows-msvc' displayName: 'Upload Artifacts' diff --git a/.gitmodules b/.gitmodules index ee0dc6c19..63bf2cda0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -47,8 +47,8 @@ path = externals/sirit url = https://github.com/ReinUsesLisp/sirit [submodule "libzip"] - path = externals/libzip - url = https://github.com/DarkLordZach/libzip + path = externals/libzip/libzip + url = https://github.com/nih-at/libzip.git [submodule "zlib"] - path = externals/zlib - url = https://github.com/madler/zlib + path = externals/zlib/zlib + url = https://github.com/madler/zlib.git diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index ac7529edd..61ad3487a 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -76,6 +76,7 @@ endif() # zlib add_subdirectory(zlib EXCLUDE_FROM_ALL) +set(ZLIB_LIBRARIES z) # libzip add_subdirectory(libzip EXCLUDE_FROM_ALL) diff --git a/externals/libzip b/externals/libzip deleted file mode 160000 -Subproject bd7a8103e96bc6d50164447f6b7b57bb786d8e2 diff --git a/externals/libzip/CMakeLists.txt b/externals/libzip/CMakeLists.txt new file mode 100644 index 000000000..ea5329fa0 --- /dev/null +++ b/externals/libzip/CMakeLists.txt @@ -0,0 +1,564 @@ +# 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} +) + diff --git a/externals/libzip/libzip b/externals/libzip/libzip new file mode 160000 +Subproject 89bd6d63bdea9da7627695f6c82e54f16d368b5 diff --git a/externals/zlib/CMakeLists.txt b/externals/zlib/CMakeLists.txt new file mode 100644 index 000000000..0ca32aae4 --- /dev/null +++ b/externals/zlib/CMakeLists.txt @@ -0,0 +1,81 @@ +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/ +) diff --git a/externals/zlib b/externals/zlib/zlib -Subproject cacf7f1d4e3d44d871b605da3b647f07d718623 +Subproject cacf7f1d4e3d44d871b605da3b647f07d718623 diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9c6f1c07c..9b0c3db68 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -3,17 +3,8 @@ # 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{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() +if (DEFINED ENV{AZURECIREPO}) + set(BUILD_REPOSITORY $ENV{AZURECIREPO}) endif() if (DEFINED ENV{TITLEBARFORMATIDLE}) set(TITLE_BAR_FORMAT_IDLE $ENV{TITLEBARFORMATIDLE}) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 902e668e3..fd2bbbd99 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -36,6 +36,13 @@ #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 * @@ -168,11 +175,11 @@ public: constexpr BitField(BitField&&) noexcept = default; constexpr BitField& operator=(BitField&&) noexcept = default; - constexpr FORCE_INLINE operator T() const { + constexpr operator T() const { return Value(); } - constexpr FORCE_INLINE void Assign(const T& value) { + constexpr void Assign(const T& value) { storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value); } diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 04ecac959..c029dc7b3 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -1,10 +1,11 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project +// Copyright 2019 yuzu emulator team // 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) @@ -16,18 +17,15 @@ #define CONCAT2(x, y) DO_CONCAT2(x, y) #define DO_CONCAT2(x, y) x##y -// 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)] +/// 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__){}; -// Inlining -#ifdef _WIN32 -#define FORCE_INLINE __forceinline -#else -#define FORCE_INLINE inline __attribute__((always_inline)) -#endif +/// 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__); #ifndef _MSC_VER diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index ea5c92f61..b8bbdd1ef 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -32,11 +32,28 @@ 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_PADDING_BYTES(3); + INSERT_UNION_PADDING_BYTES(3); NCASectionFilesystemType filesystem_type; NCASectionCryptoType crypto_type; - INSERT_PADDING_BYTES(3); + INSERT_UNION_PADDING_BYTES(3); }; static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size."); @@ -44,7 +61,7 @@ struct NCASectionRaw { NCASectionHeaderBlock header; std::array<u8, 0x138> block_data; std::array<u8, 0x8> section_ctr; - INSERT_PADDING_BYTES(0xB8); + INSERT_UNION_PADDING_BYTES(0xB8); }; static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size."); @@ -52,19 +69,19 @@ struct PFS0Superblock { NCASectionHeaderBlock header_block; std::array<u8, 0x20> hash; u32_le size; - INSERT_PADDING_BYTES(4); + INSERT_UNION_PADDING_BYTES(4); u64_le hash_table_offset; u64_le hash_table_size; u64_le pfs0_header_offset; u64_le pfs0_size; - INSERT_PADDING_BYTES(0x1B0); + INSERT_UNION_PADDING_BYTES(0x1B0); }; static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); struct RomFSSuperblock { NCASectionHeaderBlock header_block; IVFCHeader ivfc; - INSERT_PADDING_BYTES(0x118); + INSERT_UNION_PADDING_BYTES(0x118); }; static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size."); @@ -72,24 +89,24 @@ struct BKTRHeader { u64_le offset; u64_le size; u32_le magic; - INSERT_PADDING_BYTES(0x4); + INSERT_UNION_PADDING_BYTES(0x4); u32_le number_entries; - INSERT_PADDING_BYTES(0x4); + INSERT_UNION_PADDING_BYTES(0x4); }; static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size."); struct BKTRSuperblock { NCASectionHeaderBlock header_block; IVFCHeader ivfc; - INSERT_PADDING_BYTES(0x18); + INSERT_UNION_PADDING_BYTES(0x18); BKTRHeader relocation; BKTRHeader subsection; - INSERT_PADDING_BYTES(0xC0); + INSERT_UNION_PADDING_BYTES(0xC0); }; static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size."); union NCASectionHeader { - NCASectionRaw raw; + NCASectionRaw raw{}; PFS0Superblock pfs0; RomFSSuperblock romfs; BKTRSuperblock bktr; diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h index 0f35639bc..1c89be8a4 100644 --- a/src/core/file_sys/romfs.h +++ b/src/core/file_sys/romfs.h @@ -13,25 +13,6 @@ 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 diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index fae54bcc7..7ce313190 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -160,7 +160,7 @@ struct DomainMessageHeader { // Used when responding to an IPC request, Server -> Client. struct { u32_le num_objects; - INSERT_PADDING_WORDS(3); + INSERT_UNION_PADDING_WORDS(3); }; // Used when performing an IPC request, Client -> Server. @@ -171,8 +171,10 @@ struct DomainMessageHeader { BitField<16, 16, u32> size; }; u32_le object_id; - INSERT_PADDING_WORDS(2); + INSERT_UNION_PADDING_WORDS(2); }; + + std::array<u32, 4> raw{}; }; }; static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect"); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index f3da525d6..a7b5849b0 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -58,8 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( auto& kernel = Core::System::GetInstance().Kernel(); if (!writable_event) { // Create event if not provided - const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic, - "HLE Pause Event: " + reason); + const auto pair = WritableEvent::CreateEventPair(kernel, "HLE Pause Event: " + reason); writable_event = pair.writable; } diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 2821176a7..a6faeb83b 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -32,11 +32,6 @@ 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); diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index 06463cd26..d8ac97aa1 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp @@ -20,15 +20,13 @@ 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() { - signaled = true; - WakeupAllWaitingThreads(); + if (!signaled) { + signaled = true; + WakeupAllWaitingThreads(); + }; } void ReadableEvent::Clear() { diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h index 84215f572..11ff71c3a 100644 --- a/src/core/hle/kernel/readable_event.h +++ b/src/core/hle/kernel/readable_event.h @@ -27,10 +27,6 @@ public: return name; } - ResetType GetResetType() const { - return reset_type; - } - static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent; HandleType GetHandleType() const override { return HANDLE_TYPE; @@ -55,8 +51,7 @@ private: void Signal(); - ResetType reset_type; - bool signaled; + bool signaled{}; std::string name; ///< Name of event (optional) }; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f64236be1..c63a9ba8b 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -2099,7 +2099,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle auto& kernel = system.Kernel(); const auto [readable_event, writable_event] = - WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent"); + WritableEvent::CreateEventPair(kernel, "CreateEvent"); HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp index a58ea6ec8..c783a34ee 100644 --- a/src/core/hle/kernel/writable_event.cpp +++ b/src/core/hle/kernel/writable_event.cpp @@ -15,8 +15,7 @@ namespace Kernel { WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {} WritableEvent::~WritableEvent() = default; -EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type, - std::string name) { +EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) { SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel)); SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel)); @@ -24,7 +23,6 @@ EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_typ 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)}; } @@ -33,10 +31,6 @@ SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const { return readable; } -ResetType WritableEvent::GetResetType() const { - return readable->reset_type; -} - void WritableEvent::Signal() { readable->Signal(); } diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h index d00c92a6b..f46cf1dd8 100644 --- a/src/core/hle/kernel/writable_event.h +++ b/src/core/hle/kernel/writable_event.h @@ -24,11 +24,9 @@ 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, ResetType reset_type, - std::string name = "Unknown"); + static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown"); std::string GetTypeName() const override { return "WritableEvent"; @@ -44,8 +42,6 @@ public: SharedPtr<ReadableEvent> GetReadableEvent() const; - ResetType GetResetType() const; - void Signal(); void Clear(); bool IsSignaled() const; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3a32d5b41..ba54b3040 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -289,8 +289,8 @@ ISelfController::ISelfController(Core::System& system, RegisterHandlers(functions); auto& kernel = system.Kernel(); - launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, - "ISelfController:LaunchableEvent"); + launchable_event = + Kernel::WritableEvent::CreateEventPair(kernel, "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, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent"); + kernel, "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, Kernel::ResetType::Manual, - "AMMessageQueue:OnMessageRecieved"); - on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged"); + on_new_message = + Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageRecieved"); + on_operation_mode_changed = + Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged"); } AppletMessageQueue::~AppletMessageQueue() = default; @@ -1073,9 +1073,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {71, nullptr, "RequestToReboot"}, {80, nullptr, "ExitAndRequestToShowThanksMessage"}, {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, - {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"}, - {101, nullptr, "SetApplicationCopyrightImage"}, - {102, nullptr, "SetApplicationCopyrightVisibility"}, + {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, + {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, + {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, {110, nullptr, "QueryApplicationPlayStatistics"}, {120, nullptr, "ExecuteProgram"}, {121, nullptr, "ClearUserChannel"}, @@ -1091,7 +1091,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) auto& kernel = system.Kernel(); gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Manual, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); + kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); } IApplicationFunctions::~IApplicationFunctions() = default; @@ -1103,6 +1103,31 @@ 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"); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index ccd053c13..2ae9402a8 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -252,6 +252,9 @@ 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; diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 720fe766f..673ad1f7f 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -24,12 +24,12 @@ namespace Service::AM::Applets { AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) { - state_changed_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent"); - pop_out_data_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopDataOutEvent"); + state_changed_event = + Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent"); + pop_out_data_event = + Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent"); pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); + kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); } AppletDataBroker::~AppletDataBroker() = default; diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index a7db26725..eab0d42c9 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -20,9 +20,9 @@ namespace Service::AM::Applets { struct ShowError { u8 mode; bool jump; - INSERT_PADDING_BYTES(4); + INSERT_UNION_PADDING_BYTES(4); bool use_64bit_error_code; - INSERT_PADDING_BYTES(1); + INSERT_UNION_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_PADDING_BYTES(6); + INSERT_UNION_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_PADDING_BYTES(6); + INSERT_UNION_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_PADDING_BYTES(6); + INSERT_UNION_PADDING_BYTES(6); u32 error_code; std::array<char, 8> language_code; std::array<char, 0x800> main_text; @@ -65,6 +65,7 @@ union Error::ErrorArguments { ShowErrorRecord error_record; SystemErrorArg system_error; ApplicationErrorArg application_error; + std::array<u8, 0x1018> raw{}; }; namespace { diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index e9cf1e840..f36ccbc49 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -67,8 +67,8 @@ AOC_U::AOC_U(Core::System& system) RegisterHandlers(functions); auto& kernel = system.Kernel(); - aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, - "GetAddOnContentListChanged:Event"); + aoc_change_event = + Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event"); } AOC_U::~AOC_U() = default; diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 9afefb5c6..6a29377e3 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -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(), Kernel::ResetType::Manual, "IAudioOutBufferReleased"); + buffer_event = + Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased"); stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, audio_params.channel_count, std::move(unique_name), diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index f162249ed..4ea7ade6e 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -47,8 +47,8 @@ public: // clang-format on RegisterHandlers(functions); - system_event = Kernel::WritableEvent::CreateEventPair( - system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent"); + system_event = + Kernel::WritableEvent::CreateEventPair(system.Kernel(), "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, Kernel::ResetType::Automatic, - "IAudioOutBufferReleasedEvent"); + buffer_event = + Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent"); // Should be similar to audio_output_device_switch_event audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, "IAudioDevice:AudioInputDeviceSwitchedEvent"); + kernel, "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, Kernel::ResetType::Automatic, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); + kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); } private: diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index b86fda29a..dec0849b8 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp @@ -13,8 +13,7 @@ namespace Service::BCAT { ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name) { event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, - std::string("ProgressServiceBackend:UpdateEvent:").append(event_name)); + kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name)); } Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const { diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index afce581e5..4574d9572 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp @@ -34,8 +34,7 @@ public: RegisterHandlers(functions); auto& kernel = system.Kernel(); - register_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent"); + register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent"); } private: diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 920fc6ff7..251b3c9df 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -57,14 +57,12 @@ public: RegisterHandlers(functions); auto& kernel = system.Kernel(); - 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"); + 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"); } private: diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 75dd9043b..1a0214f08 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -162,7 +162,7 @@ public: RegisterHandlers(functions); notification_event = Kernel::WritableEvent::CreateEventPair( - system.Kernel(), Kernel::ResetType::Manual, "INotificationService:NotifyEvent"); + system.Kernel(), "INotificationService:NotifyEvent"); } private: diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 81bd2f3cb..79fff517e 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -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, Kernel::ResetType::Manual, fmt::format("npad:NpadStyleSetChanged_{}", i)); + kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); } if (!IsControllerActivated()) { diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ba1da4181..ecc130f6c 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -203,13 +203,13 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, - {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, + {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"}, {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"}, {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"}, {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"}, {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, - {129, nullptr, "GetNpadHandheldActivationMode"}, + {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"}, {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, @@ -557,10 +557,126 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, applet_resource_user_id); + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { + // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault + IPC::RequestParser rp{ctx}; + const auto npad_id{rp.Pop<u32>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto npad_joy_device_type{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, + "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", + npad_id, applet_resource_user_id, npad_joy_device_type); + + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id{rp.Pop<u32>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, + applet_resource_user_id); + + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto unknown_1{rp.Pop<u32>()}; + const auto unknown_2{rp.Pop<u32>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, + "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}", + unknown_1, unknown_2, applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + controller.StartLRAssignmentMode(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + controller.StopLRAssignmentMode(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto mode{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}", + applet_resource_user_id, mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } +void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_1{rp.Pop<u32>()}; + const auto npad_2{rp.Pop<u32>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", + applet_resource_user_id, npad_1, npad_2); + + auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 2}; + if (controller.SwapNpadAssignment(npad_1, npad_2)) { + rb.Push(RESULT_SUCCESS); + } else { + LOG_ERROR(Service_HID, "Npads are not connected!"); + rb.Push(ERR_NPAD_NOT_CONNECTED); + } +} + void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -635,47 +751,6 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); } -void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, - applet_resource_user_id); - - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto unknown_1{rp.Pop<u32>()}; - const auto unknown_2{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_WARNING(Service_HID, - "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}", - unknown_1, unknown_2, applet_resource_user_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto mode{rp.Pop<u64>()}; - - LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}", - applet_resource_user_id, mode); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); @@ -769,49 +844,6 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.StartLRAssignmentMode(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.StopLRAssignmentMode(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto npad_1{rp.Pop<u32>()}; - const auto npad_2{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", - applet_resource_user_id, npad_1, npad_2); - - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - IPC::ResponseBuilder rb{ctx, 2}; - if (controller.SwapNpadAssignment(npad_1, npad_2)) { - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_HID, "Npads are not connected!"); - rb.Push(ERR_NPAD_NOT_CONNECTED); - } -} - class HidDbg final : public ServiceFramework<HidDbg> { public: explicit HidDbg() : ServiceFramework{"hid:dbg"} { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 01852e019..f08e036a3 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -106,14 +106,19 @@ private: void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); + void SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx); + void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx); + void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx); + void StartLrAssignmentMode(Kernel::HLERequestContext& ctx); + void StopLrAssignmentMode(Kernel::HLERequestContext& ctx); + void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); + void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); + void SwapNpadAssignment(Kernel::HLERequestContext& ctx); void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); void SendVibrationValue(Kernel::HLERequestContext& ctx); void SendVibrationValues(Kernel::HLERequestContext& ctx); void GetActualVibrationValue(Kernel::HLERequestContext& ctx); - void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx); - void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx); - void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); void PermitVibration(Kernel::HLERequestContext& ctx); @@ -123,9 +128,6 @@ private: void StopSixAxisSensor(Kernel::HLERequestContext& ctx); void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); - void StartLrAssignmentMode(Kernel::HLERequestContext& ctx); - void StopLrAssignmentMode(Kernel::HLERequestContext& ctx); - void SwapNpadAssignment(Kernel::HLERequestContext& ctx); std::shared_ptr<IAppletResource> applet_resource; Core::System& system; diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index aa886cd3e..795d7b716 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -26,8 +26,7 @@ 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, Kernel::ResetType::Automatic, - "IUser:NFCTagDetected"); + nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected"); } Module::Interface::~Interface() = default; @@ -66,10 +65,9 @@ public: RegisterHandlers(functions); auto& kernel = system.Kernel(); - deactivate_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent"); - availability_change_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent"); + deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent"); + availability_change_event = + Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent"); } private: diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 756a2af57..01d557c7a 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -69,10 +69,8 @@ public: RegisterHandlers(functions); auto& kernel = system.Kernel(); - event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, - "IRequest:Event1"); - event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, - "IRequest:Event2"); + event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1"); + event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2"); } private: diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 75d414952..7d6cf2070 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -141,8 +141,7 @@ public: auto& kernel = system.Kernel(); finished_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, - "IEnsureNetworkClockAvailabilityService:FinishEvent"); + kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent"); } private: diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 7bfb99e34..cc9cd3fd1 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -40,8 +40,7 @@ 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, Kernel::ResetType::Manual, event_label); + events_interface.events[i] = Kernel::WritableEvent::CreateEventPair(kernel, event_label); events_interface.status[i] = EventState::Free; events_interface.registered[i] = false; } diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 55b68eb0c..1af11e80c 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -16,8 +16,7 @@ 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, Kernel::ResetType::Manual, - "BufferQueue NativeHandle"); + buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle"); } BufferQueue::~BufferQueue() = default; diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 006a6d9ff..07033fb98 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -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, Kernel::ResetType::Manual, - fmt::format("Display VSync Event {}", id)); + vsync_event = + Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id)); } Display::~Display() = default; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 199b30635..611cecc20 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -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. diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 2442ddfd6..4408b5001 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -12,6 +12,10 @@ #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" @@ -30,7 +34,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 is_written = false, bool use_fast_cbuf = false) { std::lock_guard lock{mutex}; auto& memory_manager = system.GPU().MemoryManager(); @@ -43,9 +47,13 @@ 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 (size < max_stream_size) { + if (use_fast_cbuf || size < max_stream_size) { if (!is_written && !IsRegionWritten(cache_addr, cache_addr + size - 1)) { - return StreamBufferUpload(host_ptr, size, alignment); + if (use_fast_cbuf) { + return ConstBufferUpload(host_ptr, size); + } else { + return StreamBufferUpload(host_ptr, size, alignment); + } } } @@ -152,6 +160,10 @@ 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(); diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 7ff44f06d..85d308e26 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -28,6 +28,13 @@ void Fermi2D::CallMethod(const GPU::MethodCall& method_call) { } } +std::pair<u32, u32> DelimitLine(u32 src_1, u32 src_2, u32 dst_1, u32 dst_2, u32 src_line) { + const u32 line_a = src_2 - src_1; + const u32 line_b = dst_2 - dst_1; + const u32 excess = std::max<s32>(0, line_a - src_line + src_1); + return {line_b - (excess * line_b) / line_a, excess}; +} + void Fermi2D::HandleSurfaceCopy() { LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}", static_cast<u32>(regs.operation)); @@ -47,10 +54,27 @@ void Fermi2D::HandleSurfaceCopy() { src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width); src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height); } + u32 dst_blit_x2 = regs.blit_dst_x + regs.blit_dst_width; + u32 dst_blit_y2 = regs.blit_dst_y + regs.blit_dst_height; + const auto [new_dst_w, src_excess_x] = + DelimitLine(src_blit_x1, src_blit_x2, regs.blit_dst_x, dst_blit_x2, regs.src.width); + const auto [new_dst_h, src_excess_y] = + DelimitLine(src_blit_y1, src_blit_y2, regs.blit_dst_y, dst_blit_y2, regs.src.height); + dst_blit_x2 = new_dst_w + regs.blit_dst_x; + src_blit_x2 = src_blit_x2 - src_excess_x; + dst_blit_y2 = new_dst_h + regs.blit_dst_y; + src_blit_y2 = src_blit_y2 - src_excess_y; + const auto [new_src_w, dst_excess_x] = + DelimitLine(regs.blit_dst_x, dst_blit_x2, src_blit_x1, src_blit_x2, regs.dst.width); + const auto [new_src_h, dst_excess_y] = + DelimitLine(regs.blit_dst_y, dst_blit_y2, src_blit_y1, src_blit_y2, regs.dst.height); + src_blit_x2 = new_src_w + src_blit_x1; + dst_blit_x2 = dst_blit_x2 - dst_excess_x; + src_blit_y2 = new_src_h + src_blit_y1; + dst_blit_y2 = dst_blit_y2 - dst_excess_y; const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2}; - const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, - regs.blit_dst_x + regs.blit_dst_width, - regs.blit_dst_y + regs.blit_dst_height}; + const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2, + dst_blit_y2}; Config copy_config; copy_config.operation = regs.operation; copy_config.filter = regs.blit_control.filter; diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 0901cf2fa..dba342c70 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -99,19 +99,19 @@ public: union { struct { - INSERT_PADDING_WORDS(0x80); + INSERT_UNION_PADDING_WORDS(0x80); Surface dst; - INSERT_PADDING_WORDS(2); + INSERT_UNION_PADDING_WORDS(2); Surface src; - INSERT_PADDING_WORDS(0x15); + INSERT_UNION_PADDING_WORDS(0x15); Operation operation; - INSERT_PADDING_WORDS(0x177); + INSERT_UNION_PADDING_WORDS(0x177); union { u32 raw; @@ -119,7 +119,7 @@ public: BitField<4, 1, Filter> filter; } blit_control; - INSERT_PADDING_WORDS(0x8); + INSERT_UNION_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_PADDING_WORDS(0x21); + INSERT_UNION_PADDING_WORDS(0x21); }; std::array<u32, NUM_REGS> reg_array; }; diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index b185c98c7..5259d92bd 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h @@ -51,7 +51,7 @@ public: union { struct { - INSERT_PADDING_WORDS(0x60); + INSERT_UNION_PADDING_WORDS(0x60); Upload::Registers upload; @@ -63,7 +63,7 @@ public: u32 data_upload; - INSERT_PADDING_WORDS(0x3F); + INSERT_UNION_PADDING_WORDS(0x3F); struct { u32 address; @@ -72,11 +72,11 @@ public: } } launch_desc_loc; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); u32 launch; - INSERT_PADDING_WORDS(0x4A7); + INSERT_UNION_PADDING_WORDS(0x4A7); struct { u32 address_high; @@ -88,7 +88,7 @@ public: } } tsc; - INSERT_PADDING_WORDS(0x3); + INSERT_UNION_PADDING_WORDS(0x3); struct { u32 address_high; @@ -100,7 +100,7 @@ public: } } tic; - INSERT_PADDING_WORDS(0x22); + INSERT_UNION_PADDING_WORDS(0x22); struct { u32 address_high; @@ -111,11 +111,11 @@ public: } } code_loc; - INSERT_PADDING_WORDS(0x3FE); + INSERT_UNION_PADDING_WORDS(0x3FE); u32 tex_cb_index; - INSERT_PADDING_WORDS(0x374); + INSERT_UNION_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; diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index e0e25c321..396fb6e86 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h @@ -45,7 +45,7 @@ public: union { struct { - INSERT_PADDING_WORDS(0x60); + INSERT_UNION_PADDING_WORDS(0x60); Upload::Registers upload; @@ -57,7 +57,7 @@ public: u32 data; - INSERT_PADDING_WORDS(0x11); + INSERT_UNION_PADDING_WORDS(0x11); }; std::array<u32, NUM_REGS> reg_array; }; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 8cc842684..1aa7c274f 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -496,7 +496,7 @@ public: Equation equation_a; Factor factor_source_a; Factor factor_dest_a; - INSERT_PADDING_WORDS(1); + INSERT_UNION_PADDING_WORDS(1); }; struct RenderTargetConfig { @@ -517,7 +517,7 @@ public: }; u32 layer_stride; u32 base_layer; - INSERT_PADDING_WORDS(7); + INSERT_UNION_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_PADDING_WORDS(2); + INSERT_UNION_PADDING_WORDS(2); Common::Rectangle<s32> GetRect() const { return { @@ -606,7 +606,7 @@ public: union { struct { - INSERT_PADDING_WORDS(0x45); + INSERT_UNION_PADDING_WORDS(0x45); struct { u32 upload_address; @@ -615,7 +615,7 @@ public: u32 bind; } macros; - INSERT_PADDING_WORDS(0x17); + INSERT_UNION_PADDING_WORDS(0x17); Upload::Registers upload; struct { @@ -626,7 +626,7 @@ public: u32 data_upload; - INSERT_PADDING_WORDS(0x44); + INSERT_UNION_PADDING_WORDS(0x44); struct { union { @@ -636,11 +636,11 @@ public: }; } sync_info; - INSERT_PADDING_WORDS(0x11E); + INSERT_UNION_PADDING_WORDS(0x11E); u32 tfb_enabled; - INSERT_PADDING_WORDS(0x2E); + INSERT_UNION_PADDING_WORDS(0x2E); std::array<RenderTargetConfig, NumRenderTargets> rt; @@ -648,49 +648,49 @@ public: std::array<ViewPort, NumViewports> viewports; - INSERT_PADDING_WORDS(0x1D); + INSERT_UNION_PADDING_WORDS(0x1D); struct { u32 first; u32 count; } vertex_buffer; - INSERT_PADDING_WORDS(1); + INSERT_UNION_PADDING_WORDS(1); float clear_color[4]; float clear_depth; - INSERT_PADDING_WORDS(0x3); + INSERT_UNION_PADDING_WORDS(0x3); s32 clear_stencil; - INSERT_PADDING_WORDS(0x7); + INSERT_UNION_PADDING_WORDS(0x7); u32 polygon_offset_point_enable; u32 polygon_offset_line_enable; u32 polygon_offset_fill_enable; - INSERT_PADDING_WORDS(0xD); + INSERT_UNION_PADDING_WORDS(0xD); std::array<ScissorTest, NumViewports> scissor_test; - INSERT_PADDING_WORDS(0x15); + INSERT_UNION_PADDING_WORDS(0x15); s32 stencil_back_func_ref; u32 stencil_back_mask; u32 stencil_back_func_mask; - INSERT_PADDING_WORDS(0xC); + INSERT_UNION_PADDING_WORDS(0xC); u32 color_mask_common; - INSERT_PADDING_WORDS(0x6); + INSERT_UNION_PADDING_WORDS(0x6); u32 rt_separate_frag_data; f32 depth_bounds[2]; - INSERT_PADDING_WORDS(0xA); + INSERT_UNION_PADDING_WORDS(0xA); struct { u32 address_high; @@ -710,7 +710,7 @@ public: } } zeta; - INSERT_PADDING_WORDS(0x41); + INSERT_UNION_PADDING_WORDS(0x41); union { BitField<0, 4, u32> stencil; @@ -719,11 +719,11 @@ public: BitField<12, 4, u32> viewport; } clear_flags; - INSERT_PADDING_WORDS(0x19); + INSERT_UNION_PADDING_WORDS(0x19); std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; - INSERT_PADDING_WORDS(0xF); + INSERT_UNION_PADDING_WORDS(0xF); struct { union { @@ -746,16 +746,16 @@ public: } } rt_control; - INSERT_PADDING_WORDS(0x2); + INSERT_UNION_PADDING_WORDS(0x2); u32 zeta_width; u32 zeta_height; - INSERT_PADDING_WORDS(0x27); + INSERT_UNION_PADDING_WORDS(0x27); u32 depth_test_enable; - INSERT_PADDING_WORDS(0x5); + INSERT_UNION_PADDING_WORDS(0x5); u32 independent_blend_enable; @@ -763,7 +763,7 @@ public: u32 alpha_test_enabled; - INSERT_PADDING_WORDS(0x6); + INSERT_UNION_PADDING_WORDS(0x6); u32 d3d_cull_mode; @@ -777,7 +777,7 @@ public: float b; float a; } blend_color; - INSERT_PADDING_WORDS(0x4); + INSERT_UNION_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_PADDING_WORDS(1); + INSERT_UNION_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_PADDING_WORDS(0x2); + INSERT_UNION_PADDING_WORDS(0x2); u32 frag_color_clamp; @@ -811,12 +811,12 @@ public: BitField<4, 1, u32> triangle_rast_flip; } screen_y_control; - INSERT_PADDING_WORDS(0x21); + INSERT_UNION_PADDING_WORDS(0x21); u32 vb_element_base; u32 vb_base_instance; - INSERT_PADDING_WORDS(0x35); + INSERT_UNION_PADDING_WORDS(0x35); union { BitField<0, 1, u32> c0; @@ -829,11 +829,11 @@ public: BitField<7, 1, u32> c7; } clip_distance_enabled; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); float point_size; - INSERT_PADDING_WORDS(0x7); + INSERT_UNION_PADDING_WORDS(0x7); u32 zeta_enable; @@ -842,7 +842,7 @@ public: BitField<4, 1, u32> alpha_to_one; } multisample_control; - INSERT_PADDING_WORDS(0x4); + INSERT_UNION_PADDING_WORDS(0x4); struct { u32 address_high; @@ -866,11 +866,11 @@ public: } } tsc; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); float polygon_offset_factor; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); struct { u32 tic_address_high; @@ -883,7 +883,7 @@ public: } } tic; - INSERT_PADDING_WORDS(0x5); + INSERT_UNION_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_PADDING_WORDS(0x4); + INSERT_UNION_PADDING_WORDS(0x4); u32 framebuffer_srgb; float polygon_offset_units; - INSERT_PADDING_WORDS(0x11); + INSERT_UNION_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_PADDING_WORDS(1); + INSERT_UNION_PADDING_WORDS(1); struct { u32 vertex_end_gl; @@ -925,14 +925,14 @@ public: }; } draw; - INSERT_PADDING_WORDS(0xA); + INSERT_UNION_PADDING_WORDS(0xA); struct { u32 enabled; u32 index; } primitive_restart; - INSERT_PADDING_WORDS(0x5F); + INSERT_UNION_PADDING_WORDS(0x5F); struct { u32 start_addr_high; @@ -973,9 +973,9 @@ public: } } index_array; - INSERT_PADDING_WORDS(0x7); + INSERT_UNION_PADDING_WORDS(0x7); - INSERT_PADDING_WORDS(0x1F); + INSERT_UNION_PADDING_WORDS(0x1F); float polygon_offset_clamp; @@ -989,17 +989,17 @@ public: } } instanced_arrays; - INSERT_PADDING_WORDS(0x6); + INSERT_UNION_PADDING_WORDS(0x6); Cull cull; u32 pixel_center_integer; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); u32 viewport_transform_enabled; - INSERT_PADDING_WORDS(0x3); + INSERT_UNION_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_PADDING_WORDS(0x21); + INSERT_UNION_PADDING_WORDS(0x21); struct { u32 enable; LogicOperation operation; } logic_op; - INSERT_PADDING_WORDS(0x1); + INSERT_UNION_PADDING_WORDS(0x1); union { u32 raw; @@ -1026,9 +1026,9 @@ public: BitField<6, 4, u32> RT; BitField<10, 11, u32> layer; } clear_buffers; - INSERT_PADDING_WORDS(0xB); + INSERT_UNION_PADDING_WORDS(0xB); std::array<ColorMask, NumRenderTargets> color_mask; - INSERT_PADDING_WORDS(0x38); + INSERT_UNION_PADDING_WORDS(0x38); struct { u32 query_address_high; @@ -1050,7 +1050,7 @@ public: } } query; - INSERT_PADDING_WORDS(0x3C); + INSERT_UNION_PADDING_WORDS(0x3C); struct { union { @@ -1090,10 +1090,10 @@ public: BitField<4, 4, ShaderProgram> program; }; u32 offset; - INSERT_PADDING_WORDS(14); + INSERT_UNION_PADDING_WORDS(14); } shader_config[MaxShaderProgram]; - INSERT_PADDING_WORDS(0x60); + INSERT_UNION_PADDING_WORDS(0x60); u32 firmware[0x20]; @@ -1110,7 +1110,7 @@ public: } } const_buffer; - INSERT_PADDING_WORDS(0x10); + INSERT_UNION_PADDING_WORDS(0x10); struct { union { @@ -1118,14 +1118,14 @@ public: BitField<0, 1, u32> valid; BitField<4, 5, u32> index; }; - INSERT_PADDING_WORDS(7); + INSERT_UNION_PADDING_WORDS(7); } cb_bind[MaxShaderStage]; - INSERT_PADDING_WORDS(0x56); + INSERT_UNION_PADDING_WORDS(0x56); u32 tex_cb_index; - INSERT_PADDING_WORDS(0x395); + INSERT_UNION_PADDING_WORDS(0x395); struct { /// Compressed address of a buffer that holds information about bound SSBOs. @@ -1137,14 +1137,14 @@ public: } } ssbo_info; - INSERT_PADDING_WORDS(0x11); + INSERT_UNION_PADDING_WORDS(0x11); struct { u32 address[MaxShaderStage]; u32 size[MaxShaderStage]; } tex_info_buffers; - INSERT_PADDING_WORDS(0xCC); + INSERT_UNION_PADDING_WORDS(0xCC); }; std::array<u32, NUM_REGS> reg_array; }; diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 93808a9bb..4f40d1d1f 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -94,7 +94,7 @@ public: union { struct { - INSERT_PADDING_WORDS(0xC0); + INSERT_UNION_PADDING_WORDS(0xC0); struct { union { @@ -112,7 +112,7 @@ public: }; } exec; - INSERT_PADDING_WORDS(0x3F); + INSERT_UNION_PADDING_WORDS(0x3F); struct { u32 address_high; @@ -139,7 +139,7 @@ public: u32 x_count; u32 y_count; - INSERT_PADDING_WORDS(0xB8); + INSERT_UNION_PADDING_WORDS(0xB8); u32 const0; u32 const1; @@ -162,11 +162,11 @@ public: Parameters dst_params; - INSERT_PADDING_WORDS(1); + INSERT_UNION_PADDING_WORDS(1); Parameters src_params; - INSERT_PADDING_WORDS(0x13); + INSERT_UNION_PADDING_WORDS(0x13); }; std::array<u32, NUM_REGS> reg_array; }; diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h index e86a7f04a..bc80661d8 100644 --- a/src/video_core/engines/shader_header.h +++ b/src/video_core/engines/shader_header.h @@ -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_PADDING_BYTES(3); // ImapSystemValuesA - INSERT_PADDING_BYTES(1); // ImapSystemValuesB - INSERT_PADDING_BYTES(16); // ImapGenericVector[32] - INSERT_PADDING_BYTES(2); // ImapColor + 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 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_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 + 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 } vtg; struct { - INSERT_PADDING_BYTES(3); // ImapSystemValuesA - INSERT_PADDING_BYTES(1); // ImapSystemValuesB + INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA + INSERT_UNION_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_PADDING_BYTES(2); // ImapColor - INSERT_PADDING_BYTES(2); // ImapSystemValuesC - INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10] - INSERT_PADDING_BYTES(2); // ImapReserved + 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 struct { u32 target; union { @@ -139,6 +139,8 @@ struct Header { return result; } } ps; + + std::array<u32, 0xF> raw{}; }; u64 GetLocalMemorySize() const { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index dbca19f35..ecc338ae9 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -207,7 +207,7 @@ public: union { struct { - INSERT_PADDING_WORDS(0x4); + INSERT_UNION_PADDING_WORDS(0x4); struct { u32 address_high; u32 address_low; @@ -220,12 +220,12 @@ public: u32 semaphore_sequence; u32 semaphore_trigger; - INSERT_PADDING_WORDS(0xC); + INSERT_UNION_PADDING_WORDS(0xC); // The puser and the puller share the reference counter, the pusher only has read // access u32 reference_count; - INSERT_PADDING_WORDS(0x5); + INSERT_UNION_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_PADDING_WORDS(0xE2); + INSERT_UNION_PADDING_WORDS(0xE2); // Puller state u32 acquire_mode; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index f8a807c84..0375fca17 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp @@ -8,13 +8,17 @@ #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) @@ -26,11 +30,22 @@ CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t siz CachedBufferBlock::~CachedBufferBlock() = default; OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, - std::size_t stream_size) - : VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>{ - rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} {} + const Device& device, std::size_t stream_size) + : GenericBufferCache{rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} { + if (!device.HasFastBufferSubData()) { + return; + } + + 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() = default; +OGLBufferCache::~OGLBufferCache() { + glDeleteBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); +} Buffer OGLBufferCache::CreateBlock(CacheAddr cache_addr, std::size_t size) { return std::make_shared<CachedBufferBlock>(cache_addr, size); @@ -69,4 +84,12 @@ 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 diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 022e7bfa9..8c7145443 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -4,10 +4,12 @@ #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" @@ -18,12 +20,14 @@ 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: @@ -38,14 +42,18 @@ private: OGLBuffer gl_buffer{}; }; -class OGLBufferCache final : public VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer> { +class OGLBufferCache final : public GenericBufferCache { public: explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, - std::size_t stream_size); + const Device& device, 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; @@ -61,6 +69,14 @@ 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 diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 64de7e425..c65b24c69 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -51,8 +51,11 @@ 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); @@ -64,6 +67,7 @@ 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); diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index bb273c3d6..bf35bd0b6 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -54,6 +54,10 @@ public: return has_precise_bug; } + bool HasFastBufferSubData() const { + return has_fast_buffer_sub_data; + } + private: static bool TestVariableAoffi(); static bool TestComponentIndexingBug(); @@ -69,6 +73,7 @@ private: bool has_variable_aoffi{}; bool has_component_indexing_bug{}; bool has_precise_bug{}; + bool has_fast_buffer_sub_data{}; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 6a4d2c83a..e560d70d5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -67,7 +67,7 @@ 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, STREAM_BUFFER_SIZE} { + system{system}, screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { shader_program_manager = std::make_unique<GLShader::ProgramManager>(); state.draw.shader_program = 0; state.Apply(); @@ -558,6 +558,8 @@ void RasterizerOpenGL::DrawPrelude() { SyncPolygonOffset(); SyncAlphaTest(); + buffer_cache.Acquire(); + // Draw the vertex batch const bool is_indexed = accelerate_draw == AccelDraw::Indexed; @@ -879,7 +881,8 @@ 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); + const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false, + device.HasFastBufferSubData()); bind_ubo_pushbuffer.Push(cbuf, offset, size); } @@ -935,10 +938,9 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag if (!entry.IsBindless()) { return maxwell3d.GetStageTexture(stage, entry.GetOffset()); } - 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); + 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); }(); @@ -966,10 +968,8 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) if (!entry.IsBindless()) { return compute.GetTexture(entry.GetOffset()); } - const auto cbuf = entry.GetBindlessCBuf(); - Tegra::Texture::TextureHandle tex_handle; - tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute, - cbuf.first, cbuf.second); + const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( + Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); return compute.GetTextureInfo(tex_handle); }(); @@ -1012,10 +1012,8 @@ void RasterizerOpenGL::SetupComputeImages(const Shader& shader) { if (!entry.IsBindless()) { return compute.GetTexture(entry.GetOffset()).tic; } - const auto cbuf = entry.GetBindlessCBuf(); - Tegra::Texture::TextureHandle tex_handle; - tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute, - cbuf.first, cbuf.second); + const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( + Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); return compute.GetTextureInfo(tex_handle).tic; }(); SetupImage(bindpoint, tic, entry); diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8a514cb8a..0ce59a852 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -735,7 +735,7 @@ private: void DeclareImages() { const auto& images{ir.GetImages()}; - for (const auto& [offset, image] : images) { + for (const auto& image : images) { std::string qualifier = "coherent volatile"; if (image.IsRead() && !image.IsWritten()) { qualifier += " readonly"; @@ -2466,16 +2466,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& [offset, image] : ir.GetImages()) { + for (const auto& 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; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index fead2a51e..b1e75e6cc 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h @@ -82,10 +82,9 @@ 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{}; }; diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index d47c63d9f..b427ac873 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -16,7 +16,9 @@ #include "video_core/shader/shader_ir.h" namespace VideoCommon::Shader { + namespace { + using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; @@ -68,15 +70,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 }; @@ -109,7 +111,7 @@ BlockInfo& CreateBlockInfo(CFGRebuildState& state, u32 start, u32 end) { } Pred GetPredicate(u32 index, bool negated) { - return static_cast<Pred>(index + (negated ? 8 : 0)); + return static_cast<Pred>(static_cast<u64>(index) + (negated ? 8ULL : 0ULL)); } /** @@ -136,15 +138,13 @@ struct BranchIndirectInfo { s32 relative_position{}; }; -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; +struct BufferInfo { + u32 index; + u32 offset; +}; - // Step 0 Get BRX Info - const Instruction instr = {state.program_code[pos]}; +std::optional<std::pair<s32, u64>> GetBRXInfo(const CFGRebuildState& state, u32& pos) { + const Instruction instr = state.program_code[pos]; const auto opcode = OpCode::Decode(instr); if (opcode->get().GetId() != OpCode::Id::BRX) { return std::nullopt; @@ -152,86 +152,94 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& if (instr.brx.constant_buffer != 0) { return std::nullopt; } - track_register = instr.gpr8.Value(); - result.relative_position = instr.brx.GetBranchExtend(); - pos--; - bool found_track = false; + --pos; + return std::make_pair(instr.brx.GetBranchExtend(), instr.gpr8.Value()); +} - // Step 1 Track LDC - while (pos >= shader_start) { - if (IsSchedInstruction(pos, shader_start)) { - pos--; +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)) { continue; } - const Instruction instr = {state.program_code[pos]}; + const Instruction instr = state.program_code[pos]; const auto opcode = OpCode::Decode(instr); - 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.Value(); - result.offset = static_cast<u32>(instr.cbuf36.GetOffset()); - track_register = instr.gpr8.Value(); - pos--; - found_track = true; - break; - } + if (!opcode) { + continue; + } + if (test(instr, opcode->get())) { + --pos; + return std::make_optional(pack(instr, opcode->get())); } - pos--; } + return std::nullopt; +} - if (!found_track) { - return std::nullopt; - } - found_track = false; +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()); + }); +} - // Step 2 Track SHL - 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::SHL_IMM) { - if (instr.gpr0.Value() == track_register) { - track_register = instr.gpr8.Value(); - pos--; - found_track = true; - break; - } - } - pos--; +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) { + return std::nullopt; } + const auto [relative_position, brx_tracked_register] = *brx_info; - if (!found_track) { + const auto ldc_info = TrackLDC(state, pos, brx_tracked_register); + if (!ldc_info) { return std::nullopt; } - found_track = false; + const auto [buffer_info, ldc_tracked_register] = *ldc_info; - // 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 shl_tracked_register = TrackSHLRegister(state, pos, ldc_tracked_register); + if (!shl_tracked_register) { + return std::nullopt; } - if (!found_track) { + const auto entries = TrackIMNMXValue(state, pos, *shl_tracked_register); + if (!entries) { return std::nullopt; } - return result; + + return BranchIndirectInfo{buffer_info.index, buffer_info.offset, *entries, relative_position}; } std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { @@ -420,30 +428,30 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) break; } case OpCode::Id::BRX: { - 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); - } - 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}; - } else { + const auto tmp = TrackBranchIndirectInfo(state, offset); + if (!tmp) { LOG_WARNING(HW_GPU, "BRX Track Unsuccesful"); + return {ParseResult::AbnormalFlow, parse_info}; } - 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}; + } + 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)); + + return {ParseResult::ControlCaught, parse_info}; } default: break; diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 1473c282a..fcedd2af6 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -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_WARNING(HW_GPU, "FMUL tab5cb8_2({}) is not implemented", - instr.fmul.tab5cb8_2.Value()); + LOG_DEBUG(HW_GPU, "FMUL tab5cb8_2({}) is not implemented", + instr.fmul.tab5cb8_2.Value()); } if (instr.fmul.tab5c68_0 != 1) { - LOG_WARNING(HW_GPU, "FMUL tab5cb8_0({}) is not implemented", - instr.fmul.tab5c68_0.Value()); + LOG_DEBUG(HW_GPU, "FMUL tab5cb8_0({}) is not implemented", + instr.fmul.tab5c68_0.Value()); } op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b); @@ -144,10 +144,11 @@ 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: diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp index b06cbe441..ee7d9a29d 100644 --- a/src/video_core/shader/decode/arithmetic_half.cpp +++ b/src/video_core/shader/decode/arithmetic_half.cpp @@ -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_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); + if (instr.alu_half.ftz == 0) { + LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); } } diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp index 6466fc011..d179b9873 100644 --- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp +++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp @@ -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_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); + if (instr.alu_half_imm.ftz == 0) { + LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); } } else { - if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None) { - LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); + if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::FTZ) { + LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); } } diff --git a/src/video_core/shader/decode/ffma.cpp b/src/video_core/shader/decode/ffma.cpp index ca2f39e8d..5973588d6 100644 --- a/src/video_core/shader/decode/ffma.cpp +++ b/src/video_core/shader/decode/ffma.cpp @@ -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_WARNING(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value()); + LOG_DEBUG(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value()); } if (instr.ffma.tab5980_1 != 0) { - LOG_WARNING(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value()); + LOG_DEBUG(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value()); } const Node op_a = GetRegister(instr.gpr8); diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp index 48ca7a4af..848e46874 100644 --- a/src/video_core/shader/decode/half_set.cpp +++ b/src/video_core/shader/decode/half_set.cpp @@ -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_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); + if (instr.hset2.ftz == 0) { + LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); } Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp index fec8f2dbe..310655619 100644 --- a/src/video_core/shader/decode/half_set_predicate.cpp +++ b/src/video_core/shader/decode/half_set_predicate.cpp @@ -19,7 +19,9 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); - LOG_DEBUG(HW_GPU, "ftz={}", static_cast<u32>(instr.hsetp2.ftz)); + if (instr.hsetp2.ftz != 0) { + LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); + } Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a); op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a); diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index b02d2cb95..d2fe4ec5d 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp @@ -143,39 +143,37 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { } Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { - const auto offset{static_cast<std::size_t>(image.index.Value())}; - if (const auto existing_image = TryUseExistingImage(offset, type)) { - return *existing_image; + 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 std::size_t next_index{used_images.size()}; - return used_images.emplace(offset, Image{offset, next_index, type}).first->second; + const auto next_index = static_cast<u32>(used_images.size()); + return used_images.emplace_back(next_index, offset, type); } Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { - 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)}; - - if (const auto image = TryUseExistingImage(cbuf_key, type)) { - return *image; - } - - 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; + const Node image_register = GetRegister(reg); + const auto [base_image, buffer, offset] = + TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size())); + + 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; } - auto& image = it->second; - ASSERT(image.GetType() == type); - return ℑ + const auto next_index = static_cast<u32>(used_images.size()); + return used_images.emplace_back(next_index, offset, buffer, type); } } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 0599ef34f..bb926a132 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -44,10 +44,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { bool is_bindless = false; switch (opcode->get().GetId()) { case OpCode::Id::TEX: { - if (instr.tex.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TEX.NODEP implementation is incomplete"); - } - const TextureType texture_type{instr.tex.texture_type}; const bool is_array = instr.tex.array != 0; const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI); @@ -62,10 +58,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(TextureMiscMode::AOFFI), "AOFFI is not implemented"); - if (instr.tex.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TEX.NODEP implementation is incomplete"); - } - const TextureType texture_type{instr.tex_b.texture_type}; const bool is_array = instr.tex_b.array != 0; const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI); @@ -82,10 +74,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const bool depth_compare = instr.texs.UsesMiscMode(TextureMiscMode::DC); const auto process_mode = instr.texs.GetTextureProcessMode(); - if (instr.texs.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TEXS.NODEP implementation is incomplete"); - } - const Node4 components = GetTexsCode(instr, texture_type, process_mode, depth_compare, is_array); @@ -107,10 +95,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::PTP), "PTP is not implemented"); - if (instr.tld4.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TLD4.NODEP implementation is incomplete"); - } - const auto texture_type = instr.tld4.texture_type.Value(); const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC) : instr.tld4.UsesMiscMode(TextureMiscMode::DC); @@ -119,15 +103,12 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI); WriteTexInstructionFloat( bb, instr, - GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless), true); + GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless)); break; } case OpCode::Id::TLD4S: { UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), "AOFFI is not implemented"); - if (instr.tld4s.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TLD4S.NODEP implementation is incomplete"); - } const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); const Node op_a = GetRegister(instr.gpr8); @@ -164,10 +145,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { is_bindless = true; [[fallthrough]]; case OpCode::Id::TXQ: { - if (instr.txq.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TXQ.NODEP implementation is incomplete"); - } - // TODO: The new commits on the texture refactor, change the way samplers work. // Sadly, not all texture instructions specify the type of texture their sampler // uses. This must be fixed at a later instance. @@ -205,10 +182,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), "NDV is not implemented"); - if (instr.tmml.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TMML.NODEP implementation is incomplete"); - } - auto texture_type = instr.tmml.texture_type.Value(); const bool is_array = instr.tmml.array != 0; const auto& sampler = @@ -254,25 +227,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG(instr.tld.ms, "MS is not implemented"); UNIMPLEMENTED_IF_MSG(instr.tld.cl, "CL is not implemented"); - if (instr.tld.nodep_flag) { - LOG_WARNING(HW_GPU, "TLD.NODEP implementation is incomplete"); - } - WriteTexInstructionFloat(bb, instr, GetTldCode(instr)); break; } case OpCode::Id::TLDS: { - const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; + const TextureType texture_type{instr.tlds.GetTextureType()}; const bool is_array{instr.tlds.IsArrayTexture()}; UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), "AOFFI is not implemented"); UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented"); - if (instr.tlds.UsesMiscMode(TextureMiscMode::NODEP)) { - LOG_WARNING(HW_GPU, "TLDS.NODEP implementation is incomplete"); - } - const Node4 components = GetTldsCode(instr, texture_type, is_array); if (instr.tlds.fp32_flag) { @@ -293,84 +258,86 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, std::optional<SamplerInfo> sampler_info) { const auto offset = static_cast<u32>(sampler.index.Value()); - Tegra::Shader::TextureType type; + TextureType type; bool is_array; bool is_shadow; if (sampler_info) { type = sampler_info->type; is_array = sampler_info->is_array; is_shadow = sampler_info->is_shadow; - } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { + } else if (const auto sampler = locker.ObtainBoundSampler(offset)) { type = sampler->texture_type.Value(); is_array = sampler->is_array.Value() != 0; is_shadow = sampler->is_shadow.Value() != 0; } else { - type = Tegra::Shader::TextureType::Texture2D; + LOG_WARNING(HW_GPU, "Unknown sampler info"); + type = TextureType::Texture2D; is_array = false; is_shadow = false; } // If this sampler has already been used, return the existing mapping. - const auto itr = + const auto it = std::find_if(used_samplers.begin(), used_samplers.end(), - [&](const Sampler& entry) { return entry.GetOffset() == offset; }); - if (itr != used_samplers.end()) { - ASSERT(itr->GetType() == type && itr->IsArray() == is_array && - itr->IsShadow() == is_shadow); - return *itr; + [offset](const Sampler& entry) { return entry.GetOffset() == offset; }); + if (it != used_samplers.end()) { + ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && + it->IsShadow() == is_shadow); + return *it; } // Otherwise create a new mapping for this sampler - const std::size_t next_index = used_samplers.size(); - const Sampler entry{offset, next_index, type, is_array, is_shadow}; - return *used_samplers.emplace(entry).first; -} // namespace VideoCommon::Shader + const auto next_index = static_cast<u32>(used_samplers.size()); + return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow)); +} const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, std::optional<SamplerInfo> sampler_info) { const Node sampler_register = GetRegister(reg); - const auto [base_sampler, cbuf_index, cbuf_offset] = + const auto [base_sampler, buffer, offset] = TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); ASSERT(base_sampler != nullptr); - const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); - Tegra::Shader::TextureType type; + + TextureType type; bool is_array; bool is_shadow; if (sampler_info) { type = sampler_info->type; is_array = sampler_info->is_array; is_shadow = sampler_info->is_shadow; - } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { + } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) { type = sampler->texture_type.Value(); is_array = sampler->is_array.Value() != 0; is_shadow = sampler->is_shadow.Value() != 0; } else { - type = Tegra::Shader::TextureType::Texture2D; + LOG_WARNING(HW_GPU, "Unknown sampler info"); + type = TextureType::Texture2D; is_array = false; is_shadow = false; } // If this sampler has already been used, return the existing mapping. - const auto itr = + const auto it = std::find_if(used_samplers.begin(), used_samplers.end(), - [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); - if (itr != used_samplers.end()) { - ASSERT(itr->GetType() == type && itr->IsArray() == is_array && - itr->IsShadow() == is_shadow); - return *itr; + [buffer = buffer, offset = offset](const Sampler& entry) { + return entry.GetBuffer() == buffer && entry.GetOffset() == offset; + }); + if (it != used_samplers.end()) { + ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && + it->IsShadow() == is_shadow); + return *it; } // Otherwise create a new mapping for this sampler - const std::size_t next_index = used_samplers.size(); - const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; - return *used_samplers.emplace(entry).first; + const auto next_index = static_cast<u32>(used_samplers.size()); + return used_samplers.emplace_back( + Sampler(next_index, offset, buffer, type, is_array, is_shadow)); } -void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components, - bool is_tld4) { +void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { u32 dest_elem = 0; for (u32 elem = 0; elem < 4; ++elem) { - if (!is_tld4 && !instr.tex.IsComponentEnabled(elem)) { + if (!instr.tex.IsComponentEnabled(elem)) { // Skip disabled components continue; } diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 447fb5c1d..4300d9ff4 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -230,62 +230,49 @@ using NodeBlock = std::vector<Node>; class Sampler { public: /// This constructor is for bound samplers - explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, - bool is_array, bool is_shadow) - : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, - is_bindless{false} {} + constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type, + bool is_array, bool is_shadow) + : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} /// This constructor is for bindless samplers - explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, - Tegra::Shader::TextureType type, bool is_array, bool is_shadow) - : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, - is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {} - - /// This constructor is for serialization/deserialization - explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, - bool is_array, bool is_shadow, bool is_bindless) - : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, - is_bindless{is_bindless} {} - - std::size_t GetOffset() const { + constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type, + bool is_array, bool is_shadow) + : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array}, + is_shadow{is_shadow}, is_bindless{true} {} + + constexpr u32 GetIndex() const { + return index; + } + + constexpr u32 GetOffset() const { return offset; } - std::size_t GetIndex() const { - return index; + constexpr u32 GetBuffer() const { + return buffer; } - Tegra::Shader::TextureType GetType() const { + constexpr Tegra::Shader::TextureType GetType() const { return type; } - bool IsArray() const { + constexpr bool IsArray() const { return is_array; } - bool IsShadow() const { + constexpr bool IsShadow() const { return is_shadow; } - bool IsBindless() const { + constexpr bool IsBindless() const { return is_bindless; } - std::pair<u32, u32> GetBindlessCBuf() const { - return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; - } - - bool operator<(const Sampler& rhs) const { - return std::tie(index, offset, type, is_array, is_shadow, is_bindless) < - std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow, - rhs.is_bindless); - } - private: - /// Offset in TSC memory from which to read the sampler object, as specified by the sampling - /// instruction. - std::size_t offset{}; - std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. + u32 index{}; ///< Emulated index given for the this sampler. + u32 offset{}; ///< Offset in the const buffer from where the sampler is being read. + u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers). + Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. @@ -294,18 +281,13 @@ private: class Image final { public: - constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type) - : offset{offset}, index{index}, type{type}, is_bindless{false} {} - - constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, - Tegra::Shader::ImageType type) - : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, - is_bindless{true} {} + /// This constructor is for bound images + constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type) + : index{index}, offset{offset}, type{type} {} - constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, - bool is_bindless, bool is_written, bool is_read, bool is_atomic) - : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, - is_written{is_written}, is_read{is_read}, is_atomic{is_atomic} {} + /// This constructor is for bindless samplers + constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type) + : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {} void MarkWrite() { is_written = true; @@ -321,12 +303,16 @@ public: is_atomic = true; } - constexpr std::size_t GetOffset() const { + constexpr u32 GetIndex() const { + return index; + } + + constexpr u32 GetOffset() const { return offset; } - constexpr std::size_t GetIndex() const { - return index; + constexpr u32 GetBuffer() const { + return buffer; } constexpr Tegra::Shader::ImageType GetType() const { @@ -349,18 +335,11 @@ public: return is_atomic; } - constexpr std::pair<u32, u32> GetBindlessCBuf() const { - return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; - } - - constexpr bool operator<(const Image& rhs) const { - return std::tie(offset, index, type, is_bindless) < - std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless); - } - private: - u64 offset{}; - std::size_t index{}; + u32 index{}; + u32 offset{}; + u32 buffer{}; + Tegra::Shader::ImageType type{}; bool is_bindless{}; bool is_written{}; diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 7582999a5..26c8fde22 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <list> #include <map> #include <optional> #include <set> @@ -95,11 +96,11 @@ public: return used_cbufs; } - const std::set<Sampler>& GetSamplers() const { + const std::list<Sampler>& GetSamplers() const { return used_samplers; } - const std::map<u64, Image>& GetImages() const { + const std::list<Image>& GetImages() const { return used_images; } @@ -316,9 +317,6 @@ private: /// Access a bindless image sampler. Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); - /// Tries to access an existing image, updating it's state as needed - Image* TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type); - /// Extracts a sequence of bits from a node Node BitfieldExtract(Node value, u32 offset, u32 bits); @@ -326,7 +324,7 @@ private: Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, - const Node4& components, bool is_tld4 = false); + const Node4& components); void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, const Node4& components, bool ignore_mask = false); @@ -402,8 +400,8 @@ private: std::set<Tegra::Shader::Attribute::Index> used_input_attributes; std::set<Tegra::Shader::Attribute::Index> used_output_attributes; std::map<u32, ConstBuffer> used_cbufs; - std::set<Sampler> used_samplers; - std::map<u64, Image> used_images; + std::list<Sampler> used_samplers; + std::list<Image> used_images; std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; bool uses_layer{}; diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 0429af9c1..27c8ce975 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -132,6 +132,8 @@ enum class SwizzleSource : u32 { }; union TextureHandle { + TextureHandle(u32 raw) : raw{raw} {} + u32 raw; BitField<0, 20, u32> tic_id; BitField<20, 12, u32> tsc_id; diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index c5b9aa08f..188f798c0 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -172,17 +172,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() con return list; } -QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) { - switch (reset_type) { - case Kernel::ResetType::Automatic: - return tr("automatic reset"); - case Kernel::ResetType::Manual: - return tr("manual reset"); - } - UNREACHABLE(); - return {}; -} - WaitTreeObjectList::WaitTreeObjectList( const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list, bool w_all) : object_list(list), wait_all(w_all) {} @@ -336,16 +325,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {} WaitTreeEvent::~WaitTreeEvent() = default; -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const { - std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren()); - - list.push_back(std::make_unique<WaitTreeText>( - tr("reset type = %1") - .arg(GetResetTypeQString( - static_cast<const Kernel::ReadableEvent&>(object).GetResetType())))); - return list; -} - WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) : thread_list(list) {} WaitTreeThreadList::~WaitTreeThreadList() = default; diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 62886609d..f2b13be24 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h @@ -111,8 +111,6 @@ public: protected: const Kernel::WaitObject& object; - - static QString GetResetTypeQString(Kernel::ResetType reset_type); }; class WaitTreeObjectList : public WaitTreeExpandableItem { @@ -146,8 +144,6 @@ class WaitTreeEvent : public WaitTreeWaitObject { public: explicit WaitTreeEvent(const Kernel::ReadableEvent& object); ~WaitTreeEvent() override; - - std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; class WaitTreeThreadList : public WaitTreeExpandableItem { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d6bb18d24..160613ee1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1839,6 +1839,10 @@ void GMainWindow::OnLoadAmiibo() { return; } + LoadAmiibo(filename); +} + +void GMainWindow::LoadAmiibo(const QString& filename) { Core::System& system{Core::System::GetInstance()}; Service::SM::ServiceManager& sm = system.ServiceManager(); auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user"); @@ -2189,10 +2193,19 @@ static bool IsSingleFileDropEvent(QDropEvent* event) { } void GMainWindow::dropEvent(QDropEvent* event) { - if (IsSingleFileDropEvent(event) && ConfirmChangeGame()) { - const QMimeData* mimeData = event->mimeData(); - QString filename = mimeData->urls().at(0).toLocalFile(); - BootGame(filename); + if (!IsSingleFileDropEvent(event)) { + return; + } + + const QMimeData* mime_data = event->mimeData(); + const QString filename = mime_data->urls().at(0).toLocalFile(); + + if (emulation_running && QFileInfo(filename).suffix() == QStringLiteral("bin")) { + LoadAmiibo(filename); + } else { + if (ConfirmChangeGame()) { + BootGame(filename); + } } } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index fd4b9ccf5..7f46bea2b 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -142,6 +142,7 @@ private: void ShowTelemetryCallout(); void SetDiscordEnabled(bool state); + void LoadAmiibo(const QString& filename); void SelectAndSetCurrentUser(); |