summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/scripts/common/post-upload.sh8
-rw-r--r--.ci/scripts/linux/docker.sh3
-rw-r--r--.ci/scripts/linux/upload.sh12
-rw-r--r--.ci/scripts/windows/upload.ps19
-rw-r--r--.ci/scripts/windows/upload.sh10
-rw-r--r--.ci/templates/build-msvc.yml1
-rw-r--r--.gitmodules8
-rw-r--r--externals/CMakeLists.txt1
m---------externals/libzip0
-rw-r--r--externals/libzip/CMakeLists.txt564
m---------externals/libzip/libzip0
-rw-r--r--externals/zlib/CMakeLists.txt81
m---------externals/zlib/zlib (renamed from externals/zlib)0
-rw-r--r--src/common/bit_field.h11
-rw-r--r--src/common/common_funcs.h22
-rw-r--r--src/core/file_sys/content_archive.cpp39
-rw-r--r--src/core/file_sys/romfs.h19
-rw-r--r--src/core/file_sys/savedata_factory.cpp12
-rw-r--r--src/core/hle/ipc.h6
-rw-r--r--src/core/hle/kernel/scheduler.cpp55
-rw-r--r--src/core/hle/kernel/scheduler.h109
-rw-r--r--src/core/hle/service/am/am.cpp31
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/error.cpp11
-rw-r--r--src/core/hle/service/hid/hid.cpp204
-rw-r--r--src/core/hle/service/hid/hid.h14
-rw-r--r--src/core/hle/service/vi/vi.cpp2
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/engines/fermi_2d.cpp30
-rw-r--r--src/video_core/engines/fermi_2d.h12
-rw-r--r--src/video_core/engines/kepler_compute.h18
-rw-r--r--src/video_core/engines/kepler_memory.h4
-rw-r--r--src/video_core/engines/maxwell_3d.h116
-rw-r--r--src/video_core/engines/maxwell_dma.h10
-rw-r--r--src/video_core/engines/shader_bytecode.h30
-rw-r--r--src/video_core/engines/shader_header.h50
-rw-r--r--src/video_core/gpu.h8
-rw-r--r--src/video_core/rasterizer_accelerated.cpp63
-rw-r--r--src/video_core/rasterizer_accelerated.h31
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp38
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h11
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp223
-rw-r--r--src/video_core/renderer_opengl/gl_state.h222
-rw-r--r--src/video_core/shader/decode/texture.cpp27
-rw-r--r--src/video_core/shader/shader_ir.h2
-rw-r--r--src/yuzu/main.cpp21
-rw-r--r--src/yuzu/main.h1
47 files changed, 1441 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 @@
1#!/bin/bash -ex 1#!/bin/bash -ex
2 2
3# Copy documentation 3# Copy documentation
4cp license.txt "$REV_NAME" 4cp license.txt "$DIR_NAME"
5cp README.md "$REV_NAME" 5cp README.md "$DIR_NAME"
6 6
7tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME" 7tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME"
8 8
9mv "$REV_NAME" $RELEASE_NAME 9mv "$DIR_NAME" $RELEASE_NAME
10 10
117z a "$REV_NAME.7z" $RELEASE_NAME 117z a "$REV_NAME.7z" $RELEASE_NAME
12 12
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
11 11
12ccache -s 12ccache -s
13 13
14# Ignore zlib's tests, since they aren't gated behind a CMake option. 14ctest -VV -C Release
15ctest -VV -E "(example|example64)" -C Release
diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh
index 0d131d1dd..ecd77e267 100644
--- a/.ci/scripts/linux/upload.sh
+++ b/.ci/scripts/linux/upload.sh
@@ -6,9 +6,15 @@ REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
6ARCHIVE_NAME="${REV_NAME}.tar.xz" 6ARCHIVE_NAME="${REV_NAME}.tar.xz"
7COMPRESSION_FLAGS="-cJvf" 7COMPRESSION_FLAGS="-cJvf"
8 8
9mkdir "$REV_NAME" 9if [ "${RELEASE_NAME}" = "mainline" ]; then
10 DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
11else
12 DIR_NAME="${REV_NAME}"
13fi
10 14
11cp build/bin/yuzu-cmd "$REV_NAME" 15mkdir "$DIR_NAME"
12cp build/bin/yuzu "$REV_NAME" 16
17cp build/bin/yuzu-cmd "$DIR_NAME"
18cp build/bin/yuzu "$DIR_NAME"
13 19
14. .ci/scripts/common/post-upload.sh 20. .ci/scripts/common/post-upload.sh
diff --git a/.ci/scripts/windows/upload.ps1 b/.ci/scripts/windows/upload.ps1
index 3cb709924..9fb99eaa3 100644
--- a/.ci/scripts/windows/upload.ps1
+++ b/.ci/scripts/windows/upload.ps1
@@ -1,6 +1,13 @@
1param($BUILD_NAME)
2
1$GITDATE = $(git show -s --date=short --format='%ad') -replace "-","" 3$GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
2$GITREV = $(git show -s --format='%h') 4$GITREV = $(git show -s --format='%h')
3$RELEASE_DIST = "yuzu-windows-msvc" 5
6if ("$BUILD_NAME" -eq "mainline") {
7 $RELEASE_DIST = "yuzu-windows-msvc-$BUILD_NAME"
8} else {
9 $RELEASE_DIST = "yuzu-windows-msvc"
10}
4 11
5$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", "" 12$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
6$MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", "" 13$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..41d87159f 100644
--- a/.ci/scripts/windows/upload.sh
+++ b/.ci/scripts/windows/upload.sh
@@ -6,8 +6,14 @@ REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}"
6ARCHIVE_NAME="${REV_NAME}.tar.gz" 6ARCHIVE_NAME="${REV_NAME}.tar.gz"
7COMPRESSION_FLAGS="-czvf" 7COMPRESSION_FLAGS="-czvf"
8 8
9mkdir "$REV_NAME" 9if [ "${RELEASE_NAME}" = "mainline" ]; then
10 DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
11else
12 DIR_NAME="${REV_NAME}"
13fi
14
15mkdir "$DIR_NAME"
10# get around the permission issues 16# get around the permission issues
11cp -r package/* "$REV_NAME" 17cp -r package/* "$DIR_NAME"
12 18
13. .ci/scripts/common/post-upload.sh 19. .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:
17 inputs: 17 inputs:
18 targetType: 'filePath' 18 targetType: 'filePath'
19 filePath: './.ci/scripts/windows/upload.ps1' 19 filePath: './.ci/scripts/windows/upload.ps1'
20 arguments: '$(BuildName)'
20- publish: artifacts 21- publish: artifacts
21 artifact: 'yuzu-$(BuildName)-windows-msvc' 22 artifact: 'yuzu-$(BuildName)-windows-msvc'
22 displayName: 'Upload Artifacts' 23 displayName: 'Upload Artifacts'
diff --git a/.gitmodules b/.gitmodules
index ee0dc6c19..63bf2cda0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -47,8 +47,8 @@
47 path = externals/sirit 47 path = externals/sirit
48 url = https://github.com/ReinUsesLisp/sirit 48 url = https://github.com/ReinUsesLisp/sirit
49[submodule "libzip"] 49[submodule "libzip"]
50 path = externals/libzip 50 path = externals/libzip/libzip
51 url = https://github.com/DarkLordZach/libzip 51 url = https://github.com/nih-at/libzip.git
52[submodule "zlib"] 52[submodule "zlib"]
53 path = externals/zlib 53 path = externals/zlib/zlib
54 url = https://github.com/madler/zlib 54 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()
76 76
77# zlib 77# zlib
78add_subdirectory(zlib EXCLUDE_FROM_ALL) 78add_subdirectory(zlib EXCLUDE_FROM_ALL)
79set(ZLIB_LIBRARIES z)
79 80
80# libzip 81# libzip
81add_subdirectory(libzip EXCLUDE_FROM_ALL) 82add_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 @@
1# TODO:
2# create usable libtool .la file
3
4CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
5
6LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libzip")
7
8PROJECT(libzip C)
9
10OPTION(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" ON)
11OPTION(ENABLE_GNUTLS "Enable use of GnuTLS" ON)
12OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" ON)
13OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
14OPTION(ENABLE_WINDOWS_CRYPTO "Enable use of Windows cryptography libraries" ON)
15
16OPTION(ENABLE_BZIP2 "Enable use of BZip2" OFF)
17OPTION(ENABLE_LZMA "Enable use of LZMA" OFF)
18
19INCLUDE(CheckFunctionExists)
20INCLUDE(CheckIncludeFiles)
21INCLUDE(CheckSymbolExists)
22INCLUDE(CheckTypeSize)
23INCLUDE(CheckCSourceRuns)
24INCLUDE(CheckCSourceCompiles)
25INCLUDE(CheckStructHasMember)
26INCLUDE(TestBigEndian)
27INCLUDE(GNUInstallDirs)
28IF(ENABLE_COMMONCRYPTO)
29 CHECK_INCLUDE_FILES(CommonCrypto/CommonCrypto.h COMMONCRYPTO_FOUND)
30ELSE()
31 SET(COMMONCRYPTO_FOUND FALSE)
32ENDIF()
33IF(ENABLE_GNUTLS)
34 INCLUDE(FindNettle)
35 INCLUDE(FindGnuTLS)
36ELSE()
37 SET(GNUTLS_FOUND FALSE)
38ENDIF()
39IF(ENABLE_MBEDTLS)
40 FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/aes.h)
41 FIND_LIBRARY(MBEDTLS_LIBRARIES NAMES mbedcrypto)
42ELSE()
43 SET(MBEDTLS_LIBRARIES FALSE)
44ENDIF()
45IF(ENABLE_OPENSSL)
46 INCLUDE(FindOpenSSL)
47ELSE()
48 SET(OPENSSL_FOUND FALSE)
49ENDIF()
50IF(WIN32)
51 IF(ENABLE_WINDOWS_CRYPTO)
52 SET(WINDOWS_CRYPTO_FOUND TRUE)
53 ENDIF()
54ELSE()
55 SET(WINDOWS_CRYPTO_FOUND FALSE)
56ENDIF()
57
58OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
59OPTION(SHARED_LIB_VERSIONNING "Add SO version in .so build" ON)
60
61SET(PACKAGE "libzip")
62SET(PACKAGE_NAME ${PACKAGE})
63SET(PACKAGE_VERSION_MAJOR "1")
64SET(PACKAGE_VERSION_MINOR "5")
65SET(PACKAGE_VERSION_MICRO "2a")
66#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
67SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_MICRO}")
68SET(PACKAGE_VERSION ${VERSION})
69SET(LIBZIP_VERSION ${PACKAGE_VERSION})
70SET(LIBZIP_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR})
71SET(LIBZIP_VERSION_MINOR ${PACKAGE_VERSION_MINOR})
72SET(LIBZIP_VERSION_MICRO ${PACKAGE_VERSION_MICRO})
73SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
74
75SET(ARCHIVE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
76IF(NOT TARGET dist)
77ADD_CUSTOM_TARGET(dist
78 COMMAND git config tar.tar.xz.command "xz -c"
79 COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.gz HEAD
80 COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.xz HEAD
81 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
82 )
83ADD_CUSTOM_TARGET(distcheck
84 COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest 2>/dev/null || true
85 COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
86 COMMAND cmake -E tar xf ${ARCHIVE_NAME}.tar.gz
87 COMMAND chmod -R u-w ${ARCHIVE_NAME}
88 COMMAND mkdir ${ARCHIVE_NAME}-build
89 COMMAND mkdir ${ARCHIVE_NAME}-dest
90 COMMAND cd ${ARCHIVE_NAME}-build && cmake -DCMAKE_INSTALL_PREFIX=../${ARCHIVE_NAME}-dest ../${ARCHIVE_NAME}
91 COMMAND cd ${ARCHIVE_NAME}-build && make -j4
92 COMMAND cd ${ARCHIVE_NAME}-build && make test
93 COMMAND cd ${ARCHIVE_NAME}-build && make install
94# COMMAND cd ${ARCHIVE_NAME}-build && make uninstall
95# COMMAND if [ `find ${ARCHIVE_NAME}-dest ! -type d | wc -l` -ne 0 ]; then echo leftover files in ${ARCHIVE_NAME}-dest; false; fi
96 COMMAND cd ${ARCHIVE_NAME}-build && make clean
97 COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
98 COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
99 COMMAND echo "${ARCHIVE_NAME}.tar.gz is ready for distribution."
100 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
101 )
102ADD_DEPENDENCIES(distcheck dist)
103ENDIF(NOT TARGET dist)
104
105IF(BUILD_SHARED_LIBS)
106 SET(HAVE_SHARED TRUE)
107ELSE()
108 SET(ZIP_STATIC TRUE)
109ENDIF()
110
111# Checks
112
113CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD)
114CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE)
115CHECK_FUNCTION_EXISTS(_dup HAVE__DUP)
116CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN)
117CHECK_FUNCTION_EXISTS(_fileno HAVE__FILENO)
118CHECK_FUNCTION_EXISTS(_open HAVE__OPEN)
119CHECK_FUNCTION_EXISTS(_setmode HAVE__SETMODE)
120CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
121CHECK_FUNCTION_EXISTS(_strdup HAVE__STRDUP)
122CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
123CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64)
124CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64)
125CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK)
126CHECK_FUNCTION_EXISTS(arc4random HAVE_ARC4RANDOM)
127CHECK_FUNCTION_EXISTS(clonefile HAVE_CLONEFILE)
128CHECK_FUNCTION_EXISTS(explicit_bzero HAVE_EXPLICIT_BZERO)
129CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET)
130CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO)
131CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
132CHECK_FUNCTION_EXISTS(ftello HAVE_FTELLO)
133CHECK_FUNCTION_EXISTS(getprogname HAVE_GETPROGNAME)
134CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
135CHECK_FUNCTION_EXISTS(open HAVE_OPEN)
136CHECK_FUNCTION_EXISTS(setmode HAVE_SETMODE)
137CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
138CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
139CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP)
140CHECK_FUNCTION_EXISTS(stricmp HAVE_STRICMP)
141CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL)
142CHECK_FUNCTION_EXISTS(strtoull HAVE_STRTOULL)
143
144CHECK_INCLUDE_FILES("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H)
145CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
146CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)
147CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
148
149CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H_LIBZIP)
150CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H_LIBZIP)
151CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H_LIBZIP)
152
153# TODO: fix test
154# this test does not find __progname even when it exists
155#CHECK_SYMBOL_EXISTS(__progname stdlib.h HAVE___PROGNAME)
156
157CHECK_TYPE_SIZE(__int8 __INT8_LIBZIP)
158CHECK_TYPE_SIZE(int8_t INT8_T_LIBZIP)
159CHECK_TYPE_SIZE(uint8_t UINT8_T_LIBZIP)
160CHECK_TYPE_SIZE(__int16 __INT16_LIBZIP)
161CHECK_TYPE_SIZE(int16_t INT16_T_LIBZIP)
162CHECK_TYPE_SIZE(uint16_t UINT16_T_LIBZIP)
163CHECK_TYPE_SIZE(__int32 __INT32_LIBZIP)
164CHECK_TYPE_SIZE(int32_t INT32_T_LIBZIP)
165CHECK_TYPE_SIZE(uint32_t UINT32_T_LIBZIP)
166CHECK_TYPE_SIZE(__int64 __INT64_LIBZIP)
167CHECK_TYPE_SIZE(int64_t INT64_T_LIBZIP)
168CHECK_TYPE_SIZE(uint64_t UINT64_T_LIBZIP)
169CHECK_TYPE_SIZE("short" SHORT_LIBZIP)
170CHECK_TYPE_SIZE("int" INT_LIBZIP)
171CHECK_TYPE_SIZE("long" LONG_LIBZIP)
172CHECK_TYPE_SIZE("long long" LONG_LONG_LIBZIP)
173CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T)
174CHECK_TYPE_SIZE("size_t" SIZE_T_LIBZIP)
175CHECK_TYPE_SIZE("ssize_t" SSIZE_T_LIBZIP)
176
177CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
178#include <linux/fs.h>
179int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE)
180
181CHECK_C_SOURCE_COMPILES("
182int foo(char * _Nullable bar);
183int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
184
185TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
186
187#FIND_PACKAGE(ZLIB 1.1.2 REQUIRED)
188INCLUDE_DIRECTORIES(../zlib/zlib)
189SET(CMAKE_REQUIRED_INCLUDES ../zlib/zlib)
190
191IF(ENABLE_BZIP2)
192 FIND_PACKAGE(BZip2)
193 IF(BZIP2_FOUND)
194 SET (HAVE_LIBBZ2 1)
195
196 INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
197 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${BZIP2_LIBRARIES})
198 ELSE()
199 MESSAGE(WARNING "-- bzip2 library not found; bzip2 support disabled")
200 ENDIF(BZIP2_FOUND)
201ENDIF(ENABLE_BZIP2)
202
203IF(ENABLE_LZMA)
204 FIND_PACKAGE(LibLZMA)
205 IF(LIBLZMA_FOUND)
206 SET (HAVE_LIBLZMA 1)
207
208 INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIR})
209 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${LIBLZMA_LIBRARY})
210 ELSE()
211 MESSAGE(WARNING "-- lzma library not found; lzma support disabled")
212 ENDIF(LIBLZMA_FOUND)
213ENDIF(ENABLE_LZMA)
214
215
216IF (COMMONCRYPTO_FOUND)
217 SET (HAVE_CRYPTO 1)
218 SET (HAVE_COMMONCRYPTO 1)
219ELSEIF (WINDOWS_CRYPTO_FOUND)
220 SET (HAVE_CRYPTO 1)
221 SET (HAVE_WINDOWS_CRYPTO 1)
222ELSEIF (GNUTLS_FOUND AND NETTLE_FOUND)
223 SET (HAVE_CRYPTO 1)
224 SET (HAVE_GNUTLS 1)
225 INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR} ${NETTLE_INCLUDE_DIR})
226 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${GNUTLS_LIBRARY} ${NETTLE_LIBRARY})
227ELSEIF (OPENSSL_FOUND)
228 SET (HAVE_CRYPTO 1)
229 SET (HAVE_OPENSSL 1)
230 INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
231 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${OPENSSL_LIBRARIES})
232ELSEIF (MBEDTLS_LIBRARIES)
233 SET (HAVE_CRYPTO 1)
234 SET (HAVE_MBEDTLS 1)
235 INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
236 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${MBEDTLS_LIBRARIES})
237ENDIF()
238
239IF (NOT HAVE_CRYPTO)
240 MESSAGE(WARNING "-- neither Common Crypto, GnuTLS, mbed TLS, OpenSSL, nor Windows Cryptography found; AES support disabled")
241ENDIF()
242
243IF(MSVC)
244ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS")
245ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE")
246ENDIF(MSVC)
247
248if(WIN32)
249 if(HAVE_WINDOWS_CRYPTO)
250 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} bcrypt)
251 endif()
252 if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
253 ADD_DEFINITIONS(-DMS_UWP)
254 else(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
255 SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} advapi32)
256 endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
257endif(WIN32)
258
259ADD_DEFINITIONS("-DHAVE_CONFIG_H")
260
261# rpath handling: use rpath in installed binaries
262IF(NOT CMAKE_SYSTEM_NAME MATCHES Linux)
263 SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
264 SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
265ENDIF()
266
267# fixed size integral types
268
269IF(HAVE_INTTYPES_H_LIBZIP)
270 SET(LIBZIP_TYPES_INCLUDE "#define __STDC_FORMAT_MACROS 1
271#include <inttypes.h>")
272ELSEIF(HAVE_STDINT_H_LIBZIP)
273 SET(LIBZIP_TYPES_INCLUDE "#include <stdint.h>")
274ELSEIF(HAVE_SYS_TYPES_H_LIBZIP)
275 SET(LIBZIP_TYPES_INCLUDE "#include <sys/types.h>")
276ENDIF()
277
278IF(HAVE_INT8_T_LIBZIP)
279 SET(ZIP_INT8_T int8_t)
280ELSEIF(HAVE___INT8_LIBZIP)
281 SET(ZIP_INT8_T __int8)
282ELSE()
283 SET(ZIP_INT8_T "signed char")
284ENDIF()
285
286IF(HAVE_UINT8_T_LIBZIP)
287 SET(ZIP_UINT8_T uint8_t)
288ELSEIF(HAVE___INT8_LIBZIP)
289 SET(ZIP_UINT8_T "unsigned __int8")
290ELSE()
291 SET(ZIP_UINT8_T "unsigned char")
292ENDIF()
293
294IF(HAVE_INT16_T_LIBZIP)
295 SET(ZIP_INT16_T int16_t)
296ELSEIF(HAVE___INT16_LIBZIP)
297 SET(INT16_T_LIBZIP __int16)
298ELSEIF(SHORT_LIBZIP EQUAL 2)
299 SET(INT16_T_LIBZIP short)
300ENDIF()
301
302IF(HAVE_UINT16_T_LIBZIP)
303 SET(ZIP_UINT16_T uint16_t)
304ELSEIF(HAVE___INT16_LIBZIP)
305 SET(UINT16_T_LIBZIP "unsigned __int16")
306ELSEIF(SHORT_LIBZIP EQUAL 2)
307 SET(UINT16_T_LIBZIP "unsigned short")
308ENDIF()
309
310IF(HAVE_INT32_T_LIBZIP)
311 SET(ZIP_INT32_T int32_t)
312ELSEIF(HAVE___INT32_LIBZIP)
313 SET(ZIP_INT32_T __int32)
314ELSEIF(INT_LIBZIP EQUAL 4)
315 SET(ZIP_INT32_T int)
316ELSEIF(LONG_LIBZIP EQUAL 4)
317 SET(ZIP_INT32_T long)
318ENDIF()
319
320IF(HAVE_UINT32_T_LIBZIP)
321SET(ZIP_UINT32_T uint32_t)
322ELSEIF(HAVE___INT32_LIBZIP)
323SET(ZIP_UINT32_T "unsigned __int32")
324ELSEIF(INT_LIBZIP EQUAL 4)
325SET(ZIP_UINT32_T "unsigned int")
326ELSEIF(LONG_LIBZIP EQUAL 4)
327SET(ZIP_UINT32_T "unsigned long")
328ENDIF()
329
330IF(HAVE_INT64_T_LIBZIP)
331 SET(ZIP_INT64_T int64_t)
332ELSEIF(HAVE___INT64_LIBZIP)
333 SET(ZIP_INT64_T __int64)
334ELSEIF(LONG_LIBZIP EQUAL 8)
335 SET(ZIP_INT64_T long)
336ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
337 SET(ZIP_INT64_T "long long")
338ENDIF()
339
340IF(HAVE_UINT64_T_LIBZIP)
341 SET(ZIP_UINT64_T uint64_t)
342ELSEIF(HAVE___INT64_LIBZIP)
343 SET(ZIP_UINT64_T "unsigned __int64")
344ELSEIF(LONG_LIBZIP EQUAL 8)
345 SET(ZIP_UINT64_T "unsigned long")
346ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
347 SET(ZIP_UINT64_T "unsigned long long")
348ENDIF()
349
350IF(HAVE_NULLABLE)
351 SET(ZIP_NULLABLE_DEFINES)
352ELSE()
353 SET(ZIP_NULLABLE_DEFINES "#define _Nullable
354#define _Nonnull")
355ENDIF()
356
357# write out config file
358CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/config.h)
359CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-zipconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h)
360
361# installation
362INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
363INSTALL(FILES libzip/lib/zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
364
365SET(CMAKE_C_VISIBILITY_PRESET hidden)
366
367ADD_LIBRARY(zip
368 libzip/lib/zip_add.c
369 libzip/lib/zip_add_dir.c
370 libzip/lib/zip_add_entry.c
371 libzip/lib/zip_algorithm_deflate.c
372 libzip/lib/zip_buffer.c
373 libzip/lib/zip_close.c
374 libzip/lib/zip_delete.c
375 libzip/lib/zip_dir_add.c
376 libzip/lib/zip_dirent.c
377 libzip/lib/zip_discard.c
378 libzip/lib/zip_entry.c
379 libzip/lib/zip_err_str.c
380 libzip/lib/zip_error.c
381 libzip/lib/zip_error_clear.c
382 libzip/lib/zip_error_get.c
383 libzip/lib/zip_error_get_sys_type.c
384 libzip/lib/zip_error_strerror.c
385 libzip/lib/zip_error_to_str.c
386 libzip/lib/zip_extra_field.c
387 libzip/lib/zip_extra_field_api.c
388 libzip/lib/zip_fclose.c
389 libzip/lib/zip_fdopen.c
390 libzip/lib/zip_file_add.c
391 libzip/lib/zip_file_error_clear.c
392 libzip/lib/zip_file_error_get.c
393 libzip/lib/zip_file_get_comment.c
394 libzip/lib/zip_file_get_external_attributes.c
395 libzip/lib/zip_file_get_offset.c
396 libzip/lib/zip_file_rename.c
397 libzip/lib/zip_file_replace.c
398 libzip/lib/zip_file_set_comment.c
399 libzip/lib/zip_file_set_encryption.c
400 libzip/lib/zip_file_set_external_attributes.c
401 libzip/lib/zip_file_set_mtime.c
402 libzip/lib/zip_file_strerror.c
403 libzip/lib/zip_filerange_crc.c
404 libzip/lib/zip_fopen.c
405 libzip/lib/zip_fopen_encrypted.c
406 libzip/lib/zip_fopen_index.c
407 libzip/lib/zip_fopen_index_encrypted.c
408 libzip/lib/zip_fread.c
409 libzip/lib/zip_fseek.c
410 libzip/lib/zip_ftell.c
411 libzip/lib/zip_get_archive_comment.c
412 libzip/lib/zip_get_archive_flag.c
413 libzip/lib/zip_get_encryption_implementation.c
414 libzip/lib/zip_get_file_comment.c
415 libzip/lib/zip_get_name.c
416 libzip/lib/zip_get_num_entries.c
417 libzip/lib/zip_get_num_files.c
418 libzip/lib/zip_hash.c
419 libzip/lib/zip_io_util.c
420 libzip/lib/zip_libzip_version.c
421 libzip/lib/zip_memdup.c
422 libzip/lib/zip_name_locate.c
423 libzip/lib/zip_new.c
424 libzip/lib/zip_open.c
425 libzip/lib/zip_progress.c
426 libzip/lib/zip_rename.c
427 libzip/lib/zip_replace.c
428 libzip/lib/zip_set_archive_comment.c
429 libzip/lib/zip_set_archive_flag.c
430 libzip/lib/zip_set_default_password.c
431 libzip/lib/zip_set_file_comment.c
432 libzip/lib/zip_set_file_compression.c
433 libzip/lib/zip_set_name.c
434 libzip/lib/zip_source_accept_empty.c
435 libzip/lib/zip_source_begin_write.c
436 libzip/lib/zip_source_begin_write_cloning.c
437 libzip/lib/zip_source_buffer.c
438 libzip/lib/zip_source_call.c
439 libzip/lib/zip_source_close.c
440 libzip/lib/zip_source_commit_write.c
441 libzip/lib/zip_source_compress.c
442 libzip/lib/zip_source_crc.c
443 libzip/lib/zip_source_error.c
444 libzip/lib/zip_source_filep.c
445 libzip/lib/zip_source_free.c
446 libzip/lib/zip_source_function.c
447 libzip/lib/zip_source_get_compression_flags.c
448 libzip/lib/zip_source_is_deleted.c
449 libzip/lib/zip_source_layered.c
450 libzip/lib/zip_source_open.c
451 libzip/lib/zip_source_pkware.c
452 libzip/lib/zip_source_read.c
453 libzip/lib/zip_source_remove.c
454 libzip/lib/zip_source_rollback_write.c
455 libzip/lib/zip_source_seek.c
456 libzip/lib/zip_source_seek_write.c
457 libzip/lib/zip_source_stat.c
458 libzip/lib/zip_source_supports.c
459 libzip/lib/zip_source_tell.c
460 libzip/lib/zip_source_tell_write.c
461 libzip/lib/zip_source_window.c
462 libzip/lib/zip_source_write.c
463 libzip/lib/zip_source_zip.c
464 libzip/lib/zip_source_zip_new.c
465 libzip/lib/zip_stat.c
466 libzip/lib/zip_stat_index.c
467 libzip/lib/zip_stat_init.c
468 libzip/lib/zip_strerror.c
469 libzip/lib/zip_string.c
470 libzip/lib/zip_unchange.c
471 libzip/lib/zip_unchange_all.c
472 libzip/lib/zip_unchange_archive.c
473 libzip/lib/zip_unchange_data.c
474 libzip/lib/zip_utf-8.c
475)
476
477IF(WIN32)
478 target_sources(zip PRIVATE
479 libzip/lib/zip_source_win32handle.c
480 libzip/lib/zip_source_win32utf8.c
481 libzip/lib/zip_source_win32w.c
482 )
483 IF(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
484 ELSE()
485 target_sources(zip PRIVATE libzip/lib/zip_source_win32a.c)
486 ENDIF()
487ELSE()
488 target_sources(zip PRIVATE
489 libzip/lib/zip_mkstempm.c
490 libzip/lib/zip_source_file.c
491 libzip/lib/zip_random_unix.c
492 )
493ENDIF()
494
495IF(HAVE_LIBBZ2)
496 target_sources(zip PRIVATE libzip/lib/zip_algorithm_bzip2.c)
497ENDIF()
498
499IF(HAVE_LIBLZMA)
500 target_sources(zip PRIVATE libzip/lib/zip_algorithm_xz.c)
501ENDIF()
502
503IF(HAVE_COMMONCRYPTO)
504 target_sources(zip PRIVATE libzip/lib/zip_crypto_commoncrypto.c)
505ELSEIF(HAVE_WINDOWS_CRYPTO)
506 target_sources(zip PRIVATE libzip/lib/zip_crypto_win.c)
507ELSEIF(HAVE_GNUTLS)
508 target_sources(zip PRIVATE libzip/lib/zip_crypto_gnutls.c)
509ELSEIF(HAVE_OPENSSL)
510 target_sources(zip PRIVATE libzip/lib/zip_crypto_openssl.c)
511ELSEIF(HAVE_MBEDTLS)
512 target_sources(zip PRIVATE libzip/lib/zip_crypto_mbedtls.c)
513ENDIF()
514
515IF(HAVE_CRYPTO)
516 target_sources(zip PRIVATE
517 libzip/lib/zip_winzip_aes.c
518 libzip/lib/zip_source_winzip_aes_decode.c
519 libzip/lib/zip_source_winzip_aes_encode.c
520 )
521ENDIF()
522
523target_include_directories(zip
524PUBLIC
525 libzip/lib
526 ${CMAKE_CURRENT_BINARY_DIR}/libzip
527)
528
529# pkgconfig file
530SET(prefix ${CMAKE_INSTALL_PREFIX})
531SET(exec_prefix \${prefix})
532SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
533SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
534SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
535IF(CMAKE_SYSTEM_NAME MATCHES BSD)
536 SET(PKG_CONFIG_RPATH "-Wl,-R\${libdir}")
537ENDIF(CMAKE_SYSTEM_NAME MATCHES BSD)
538get_target_property(LIBS_PRIVATE zip LINK_LIBRARIES)
539foreach(LIB ${LIBS_PRIVATE})
540 if(LIB MATCHES "^/")
541 get_filename_component(LIB ${LIB} NAME_WE)
542 string(REGEX REPLACE "^lib" "" LIB ${LIB})
543 endif()
544 set(LIBS "${LIBS} -l${LIB}")
545endforeach()
546CONFIGURE_FILE(libzip/libzip.pc.in libzip/libzip.pc @ONLY)
547INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
548
549ADD_CUSTOM_TARGET(update_zip_err_str
550 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
551 DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh
552)
553
554IF(SHARED_LIB_VERSIONNING)
555SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 5.0 SOVERSION 5)
556ENDIF()
557
558TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARIES} ${OPTIONAL_LIBRARY})
559INSTALL(TARGETS zip
560 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
561 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
562 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
563)
564
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 @@
1project(zlib C)
2
3include(CheckTypeSize)
4include(CheckFunctionExists)
5include(CheckIncludeFile)
6
7check_include_file(sys/types.h HAVE_SYS_TYPES_H)
8check_include_file(stdint.h HAVE_STDINT_H)
9check_include_file(stddef.h HAVE_STDDEF_H)
10
11# Check to see if we have large file support
12set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
13# We add these other definitions here because CheckTypeSize.cmake
14# in CMake 2.4.x does not automatically do so and we want
15# compatibility with CMake 2.4.x.
16if(HAVE_SYS_TYPES_H)
17 list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
18endif()
19if(HAVE_STDINT_H)
20 list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
21endif()
22if(HAVE_STDDEF_H)
23 list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
24endif()
25check_type_size(off64_t OFF64_T)
26if(HAVE_OFF64_T)
27 add_definitions(-D_LARGEFILE64_SOURCE=1)
28endif()
29set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
30
31# Check for fseeko
32check_function_exists(fseeko HAVE_FSEEKO)
33if(NOT HAVE_FSEEKO)
34 add_definitions(-DNO_FSEEKO)
35endif()
36
37# Check for unistd.h
38check_include_file(unistd.h HAVE_UNISTD_H)
39if(HAVE_UNISTD_H)
40 add_definitions(-DHAVE_UNISTD_H)
41endif()
42
43if(MSVC)
44 add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
45 add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
46endif()
47
48add_library(z STATIC
49 zlib/adler32.c
50 zlib/compress.c
51 zlib/crc32.c
52 zlib/crc32.h
53 zlib/deflate.c
54 zlib/deflate.h
55 zlib/gzclose.c
56 zlib/gzguts.h
57 zlib/gzlib.c
58 zlib/gzread.c
59 zlib/gzwrite.c
60 zlib/inffast.h
61 zlib/inffixed.h
62 zlib/inflate.c
63 zlib/inflate.h
64 zlib/infback.c
65 zlib/inftrees.c
66 zlib/inftrees.h
67 zlib/inffast.c
68 zlib/trees.c
69 zlib/trees.h
70 zlib/uncompr.c
71 zlib/zconf.h
72 zlib/zlib.h
73 zlib/zutil.c
74 zlib/zutil.h
75)
76add_library(ZLIB::ZLIB ALIAS z)
77
78target_include_directories(z
79PUBLIC
80 zlib/
81)
diff --git a/externals/zlib b/externals/zlib/zlib
Subproject cacf7f1d4e3d44d871b605da3b647f07d718623 Subproject cacf7f1d4e3d44d871b605da3b647f07d718623
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 @@
36#include "common/common_funcs.h" 36#include "common/common_funcs.h"
37#include "common/swap.h" 37#include "common/swap.h"
38 38
39// Inlining
40#ifdef _WIN32
41#define FORCE_INLINE __forceinline
42#else
43#define FORCE_INLINE inline __attribute__((always_inline))
44#endif
45
39/* 46/*
40 * Abstract bitfield class 47 * Abstract bitfield class
41 * 48 *
@@ -168,11 +175,11 @@ public:
168 constexpr BitField(BitField&&) noexcept = default; 175 constexpr BitField(BitField&&) noexcept = default;
169 constexpr BitField& operator=(BitField&&) noexcept = default; 176 constexpr BitField& operator=(BitField&&) noexcept = default;
170 177
171 constexpr FORCE_INLINE operator T() const { 178 constexpr operator T() const {
172 return Value(); 179 return Value();
173 } 180 }
174 181
175 constexpr FORCE_INLINE void Assign(const T& value) { 182 constexpr void Assign(const T& value) {
176 storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value); 183 storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value);
177 } 184 }
178 185
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 @@
1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project 1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <array>
8#include <string> 9#include <string>
9 10
10#if !defined(ARCHITECTURE_x86_64) 11#if !defined(ARCHITECTURE_x86_64)
@@ -16,18 +17,15 @@
16#define CONCAT2(x, y) DO_CONCAT2(x, y) 17#define CONCAT2(x, y) DO_CONCAT2(x, y)
17#define DO_CONCAT2(x, y) x##y 18#define DO_CONCAT2(x, y) x##y
18 19
19// helper macro to properly align structure members. 20/// Helper macros to insert unused bytes or words to properly align structs. These values will be
20// Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121", 21/// zero-initialized.
21// depending on the current source line to make sure variable names are unique. 22#define INSERT_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__){};
22#define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] 23#define INSERT_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__){};
23#define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)]
24 24
25// Inlining 25/// These are similar to the INSERT_PADDING_* macros, but are needed for padding unions. This is
26#ifdef _WIN32 26/// because unions can only be initialized by one member.
27#define FORCE_INLINE __forceinline 27#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__);
28#else 28#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__);
29#define FORCE_INLINE inline __attribute__((always_inline))
30#endif
31 29
32#ifndef _MSC_VER 30#ifndef _MSC_VER
33 31
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 {
32 ROMFS = 0x3, 32 ROMFS = 0x3,
33}; 33};
34 34
35struct IVFCLevel {
36 u64_le offset;
37 u64_le size;
38 u32_le block_size;
39 u32_le reserved;
40};
41static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
42
43struct IVFCHeader {
44 u32_le magic;
45 u32_le magic_number;
46 INSERT_UNION_PADDING_BYTES(8);
47 std::array<IVFCLevel, 6> levels;
48 INSERT_UNION_PADDING_BYTES(64);
49};
50static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
51
35struct NCASectionHeaderBlock { 52struct NCASectionHeaderBlock {
36 INSERT_PADDING_BYTES(3); 53 INSERT_UNION_PADDING_BYTES(3);
37 NCASectionFilesystemType filesystem_type; 54 NCASectionFilesystemType filesystem_type;
38 NCASectionCryptoType crypto_type; 55 NCASectionCryptoType crypto_type;
39 INSERT_PADDING_BYTES(3); 56 INSERT_UNION_PADDING_BYTES(3);
40}; 57};
41static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size."); 58static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size.");
42 59
@@ -44,7 +61,7 @@ struct NCASectionRaw {
44 NCASectionHeaderBlock header; 61 NCASectionHeaderBlock header;
45 std::array<u8, 0x138> block_data; 62 std::array<u8, 0x138> block_data;
46 std::array<u8, 0x8> section_ctr; 63 std::array<u8, 0x8> section_ctr;
47 INSERT_PADDING_BYTES(0xB8); 64 INSERT_UNION_PADDING_BYTES(0xB8);
48}; 65};
49static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size."); 66static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size.");
50 67
@@ -52,19 +69,19 @@ struct PFS0Superblock {
52 NCASectionHeaderBlock header_block; 69 NCASectionHeaderBlock header_block;
53 std::array<u8, 0x20> hash; 70 std::array<u8, 0x20> hash;
54 u32_le size; 71 u32_le size;
55 INSERT_PADDING_BYTES(4); 72 INSERT_UNION_PADDING_BYTES(4);
56 u64_le hash_table_offset; 73 u64_le hash_table_offset;
57 u64_le hash_table_size; 74 u64_le hash_table_size;
58 u64_le pfs0_header_offset; 75 u64_le pfs0_header_offset;
59 u64_le pfs0_size; 76 u64_le pfs0_size;
60 INSERT_PADDING_BYTES(0x1B0); 77 INSERT_UNION_PADDING_BYTES(0x1B0);
61}; 78};
62static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); 79static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
63 80
64struct RomFSSuperblock { 81struct RomFSSuperblock {
65 NCASectionHeaderBlock header_block; 82 NCASectionHeaderBlock header_block;
66 IVFCHeader ivfc; 83 IVFCHeader ivfc;
67 INSERT_PADDING_BYTES(0x118); 84 INSERT_UNION_PADDING_BYTES(0x118);
68}; 85};
69static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size."); 86static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size.");
70 87
@@ -72,24 +89,24 @@ struct BKTRHeader {
72 u64_le offset; 89 u64_le offset;
73 u64_le size; 90 u64_le size;
74 u32_le magic; 91 u32_le magic;
75 INSERT_PADDING_BYTES(0x4); 92 INSERT_UNION_PADDING_BYTES(0x4);
76 u32_le number_entries; 93 u32_le number_entries;
77 INSERT_PADDING_BYTES(0x4); 94 INSERT_UNION_PADDING_BYTES(0x4);
78}; 95};
79static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size."); 96static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size.");
80 97
81struct BKTRSuperblock { 98struct BKTRSuperblock {
82 NCASectionHeaderBlock header_block; 99 NCASectionHeaderBlock header_block;
83 IVFCHeader ivfc; 100 IVFCHeader ivfc;
84 INSERT_PADDING_BYTES(0x18); 101 INSERT_UNION_PADDING_BYTES(0x18);
85 BKTRHeader relocation; 102 BKTRHeader relocation;
86 BKTRHeader subsection; 103 BKTRHeader subsection;
87 INSERT_PADDING_BYTES(0xC0); 104 INSERT_UNION_PADDING_BYTES(0xC0);
88}; 105};
89static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size."); 106static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size.");
90 107
91union NCASectionHeader { 108union NCASectionHeader {
92 NCASectionRaw raw; 109 NCASectionRaw raw{};
93 PFS0Superblock pfs0; 110 PFS0Superblock pfs0;
94 RomFSSuperblock romfs; 111 RomFSSuperblock romfs;
95 BKTRSuperblock bktr; 112 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 @@
13 13
14namespace FileSys { 14namespace FileSys {
15 15
16struct RomFSHeader;
17
18struct IVFCLevel {
19 u64_le offset;
20 u64_le size;
21 u32_le block_size;
22 u32_le reserved;
23};
24static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
25
26struct IVFCHeader {
27 u32_le magic;
28 u32_le magic_number;
29 INSERT_PADDING_BYTES(8);
30 std::array<IVFCLevel, 6> levels;
31 INSERT_PADDING_BYTES(64);
32};
33static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
34
35enum class RomFSExtractionType { 16enum class RomFSExtractionType {
36 Full, // Includes data directory 17 Full, // Includes data directory
37 Truncated, // Traverses into data directory 18 Truncated, // Traverses into data directory
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index fc8755c78..e2a7eaf7b 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -16,6 +16,7 @@ namespace FileSys {
16constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size"; 16constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
17 17
18namespace { 18namespace {
19
19void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) { 20void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
20 if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) { 21 if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
21 if (meta.zero_1 != 0) { 22 if (meta.zero_1 != 0) {
@@ -52,6 +53,13 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
52 meta.user_id[1], meta.user_id[0]); 53 meta.user_id[1], meta.user_id[0]);
53 } 54 }
54} 55}
56
57bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
58 return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
59 (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
60 desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
61}
62
55} // Anonymous namespace 63} // Anonymous namespace
56 64
57std::string SaveDataDescriptor::DebugInfo() const { 65std::string SaveDataDescriptor::DebugInfo() const {
@@ -96,6 +104,10 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
96 104
97 auto out = dir->GetDirectoryRelative(save_directory); 105 auto out = dir->GetDirectoryRelative(save_directory);
98 106
107 if (out == nullptr && ShouldSaveDataBeAutomaticallyCreated(space, meta)) {
108 return Create(space, meta);
109 }
110
99 // Return an error if the save data doesn't actually exist. 111 // Return an error if the save data doesn't actually exist.
100 if (out == nullptr) { 112 if (out == nullptr) {
101 // TODO(Subv): Find out correct error code. 113 // TODO(Subv): Find out correct error code.
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 {
160 // Used when responding to an IPC request, Server -> Client. 160 // Used when responding to an IPC request, Server -> Client.
161 struct { 161 struct {
162 u32_le num_objects; 162 u32_le num_objects;
163 INSERT_PADDING_WORDS(3); 163 INSERT_UNION_PADDING_WORDS(3);
164 }; 164 };
165 165
166 // Used when performing an IPC request, Client -> Server. 166 // Used when performing an IPC request, Client -> Server.
@@ -171,8 +171,10 @@ struct DomainMessageHeader {
171 BitField<16, 16, u32> size; 171 BitField<16, 16, u32> size;
172 }; 172 };
173 u32_le object_id; 173 u32_le object_id;
174 INSERT_PADDING_WORDS(2); 174 INSERT_UNION_PADDING_WORDS(2);
175 }; 175 };
176
177 std::array<u32, 4> raw{};
176 }; 178 };
177}; 179};
178static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect"); 180static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect");
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index e6dcb9639..0e2dbf13e 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -22,9 +22,9 @@
22 22
23namespace Kernel { 23namespace Kernel {
24 24
25GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} { 25GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {}
26 is_reselection_pending = false; 26
27} 27GlobalScheduler::~GlobalScheduler() = default;
28 28
29void GlobalScheduler::AddThread(SharedPtr<Thread> thread) { 29void GlobalScheduler::AddThread(SharedPtr<Thread> thread) {
30 thread_list.push_back(std::move(thread)); 30 thread_list.push_back(std::move(thread));
@@ -35,24 +35,11 @@ void GlobalScheduler::RemoveThread(const Thread* thread) {
35 thread_list.end()); 35 thread_list.end());
36} 36}
37 37
38/*
39 * UnloadThread selects a core and forces it to unload its current thread's context
40 */
41void GlobalScheduler::UnloadThread(s32 core) { 38void GlobalScheduler::UnloadThread(s32 core) {
42 Scheduler& sched = system.Scheduler(core); 39 Scheduler& sched = system.Scheduler(core);
43 sched.UnloadThread(); 40 sched.UnloadThread();
44} 41}
45 42
46/*
47 * SelectThread takes care of selecting the new scheduled thread.
48 * It does it in 3 steps:
49 * - First a thread is selected from the top of the priority queue. If no thread
50 * is obtained then we move to step two, else we are done.
51 * - Second we try to get a suggested thread that's not assigned to any core or
52 * that is not the top thread in that core.
53 * - Third is no suggested thread is found, we do a second pass and pick a running
54 * thread in another core and swap it with its current thread.
55 */
56void GlobalScheduler::SelectThread(u32 core) { 43void GlobalScheduler::SelectThread(u32 core) {
57 const auto update_thread = [](Thread* thread, Scheduler& sched) { 44 const auto update_thread = [](Thread* thread, Scheduler& sched) {
58 if (thread != sched.selected_thread) { 45 if (thread != sched.selected_thread) {
@@ -114,30 +101,19 @@ void GlobalScheduler::SelectThread(u32 core) {
114 update_thread(current_thread, sched); 101 update_thread(current_thread, sched);
115} 102}
116 103
117/*
118 * YieldThread takes a thread and moves it to the back of the it's priority list
119 * This operation can be redundant and no scheduling is changed if marked as so.
120 */
121bool GlobalScheduler::YieldThread(Thread* yielding_thread) { 104bool GlobalScheduler::YieldThread(Thread* yielding_thread) {
122 // Note: caller should use critical section, etc. 105 // Note: caller should use critical section, etc.
123 const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); 106 const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID());
124 const u32 priority = yielding_thread->GetPriority(); 107 const u32 priority = yielding_thread->GetPriority();
125 108
126 // Yield the thread 109 // Yield the thread
127 ASSERT_MSG(yielding_thread == scheduled_queue[core_id].front(priority), 110 const Thread* const winner = scheduled_queue[core_id].front(priority);
128 "Thread yielding without being in front"); 111 ASSERT_MSG(yielding_thread == winner, "Thread yielding without being in front");
129 scheduled_queue[core_id].yield(priority); 112 scheduled_queue[core_id].yield(priority);
130 113
131 Thread* winner = scheduled_queue[core_id].front(priority);
132 return AskForReselectionOrMarkRedundant(yielding_thread, winner); 114 return AskForReselectionOrMarkRedundant(yielding_thread, winner);
133} 115}
134 116
135/*
136 * YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list.
137 * Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
138 * a better priority than the next thread in the core.
139 * This operation can be redundant and no scheduling is changed if marked as so.
140 */
141bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { 117bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
142 // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section, 118 // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
143 // etc. 119 // etc.
@@ -189,12 +165,6 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
189 return AskForReselectionOrMarkRedundant(yielding_thread, winner); 165 return AskForReselectionOrMarkRedundant(yielding_thread, winner);
190} 166}
191 167
192/*
193 * YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue
194 * and into the suggested queue. If no thread can be squeduled afterwards in that core,
195 * a suggested thread is obtained instead.
196 * This operation can be redundant and no scheduling is changed if marked as so.
197 */
198bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread) { 168bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread) {
199 // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section, 169 // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
200 // etc. 170 // etc.
@@ -280,7 +250,7 @@ void GlobalScheduler::PreemptThreads() {
280 if (winner->IsRunning()) { 250 if (winner->IsRunning()) {
281 UnloadThread(winner->GetProcessorID()); 251 UnloadThread(winner->GetProcessorID());
282 } 252 }
283 TransferToCore(winner->GetPriority(), core_id, winner); 253 TransferToCore(winner->GetPriority(), s32(core_id), winner);
284 current_thread = 254 current_thread =
285 winner->GetPriority() <= current_thread->GetPriority() ? winner : current_thread; 255 winner->GetPriority() <= current_thread->GetPriority() ? winner : current_thread;
286 } 256 }
@@ -313,7 +283,7 @@ void GlobalScheduler::PreemptThreads() {
313 if (winner->IsRunning()) { 283 if (winner->IsRunning()) {
314 UnloadThread(winner->GetProcessorID()); 284 UnloadThread(winner->GetProcessorID());
315 } 285 }
316 TransferToCore(winner->GetPriority(), core_id, winner); 286 TransferToCore(winner->GetPriority(), s32(core_id), winner);
317 current_thread = winner; 287 current_thread = winner;
318 } 288 }
319 } 289 }
@@ -331,12 +301,12 @@ void GlobalScheduler::Unsuggest(u32 priority, u32 core, Thread* thread) {
331} 301}
332 302
333void GlobalScheduler::Schedule(u32 priority, u32 core, Thread* thread) { 303void GlobalScheduler::Schedule(u32 priority, u32 core, Thread* thread) {
334 ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); 304 ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
335 scheduled_queue[core].add(thread, priority); 305 scheduled_queue[core].add(thread, priority);
336} 306}
337 307
338void GlobalScheduler::SchedulePrepend(u32 priority, u32 core, Thread* thread) { 308void GlobalScheduler::SchedulePrepend(u32 priority, u32 core, Thread* thread) {
339 ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); 309 ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
340 scheduled_queue[core].add(thread, priority, false); 310 scheduled_queue[core].add(thread, priority, false);
341} 311}
342 312
@@ -368,7 +338,8 @@ void GlobalScheduler::TransferToCore(u32 priority, s32 destination_core, Thread*
368 } 338 }
369} 339}
370 340
371bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner) { 341bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread,
342 const Thread* winner) {
372 if (current_thread == winner) { 343 if (current_thread == winner) {
373 current_thread->IncrementYieldCount(); 344 current_thread->IncrementYieldCount();
374 return true; 345 return true;
@@ -386,8 +357,6 @@ void GlobalScheduler::Shutdown() {
386 thread_list.clear(); 357 thread_list.clear();
387} 358}
388 359
389GlobalScheduler::~GlobalScheduler() = default;
390
391Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id) 360Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id)
392 : system(system), cpu_core(cpu_core), core_id(core_id) {} 361 : system(system), cpu_core(cpu_core), core_id(core_id) {}
393 362
@@ -470,7 +439,7 @@ void Scheduler::SwitchContext() {
470 439
471 // Load context of new thread 440 // Load context of new thread
472 if (new_thread) { 441 if (new_thread) {
473 ASSERT_MSG(new_thread->GetProcessorID() == this->core_id, 442 ASSERT_MSG(new_thread->GetProcessorID() == s32(this->core_id),
474 "Thread must be assigned to this core."); 443 "Thread must be assigned to this core.");
475 ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready, 444 ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready,
476 "Thread must be ready to become running."); 445 "Thread must be ready to become running.");
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index fcae28e0a..f2d6311b8 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -26,6 +26,7 @@ public:
26 26
27 explicit GlobalScheduler(Core::System& system); 27 explicit GlobalScheduler(Core::System& system);
28 ~GlobalScheduler(); 28 ~GlobalScheduler();
29
29 /// Adds a new thread to the scheduler 30 /// Adds a new thread to the scheduler
30 void AddThread(SharedPtr<Thread> thread); 31 void AddThread(SharedPtr<Thread> thread);
31 32
@@ -37,47 +38,57 @@ public:
37 return thread_list; 38 return thread_list;
38 } 39 }
39 40
40 // Add a thread to the suggested queue of a cpu core. Suggested threads may be 41 /**
41 // picked if no thread is scheduled to run on the core. 42 * Add a thread to the suggested queue of a cpu core. Suggested threads may be
43 * picked if no thread is scheduled to run on the core.
44 */
42 void Suggest(u32 priority, u32 core, Thread* thread); 45 void Suggest(u32 priority, u32 core, Thread* thread);
43 46
44 // Remove a thread to the suggested queue of a cpu core. Suggested threads may be 47 /**
45 // picked if no thread is scheduled to run on the core. 48 * Remove a thread to the suggested queue of a cpu core. Suggested threads may be
49 * picked if no thread is scheduled to run on the core.
50 */
46 void Unsuggest(u32 priority, u32 core, Thread* thread); 51 void Unsuggest(u32 priority, u32 core, Thread* thread);
47 52
48 // Add a thread to the scheduling queue of a cpu core. The thread is added at the 53 /**
49 // back the queue in its priority level 54 * Add a thread to the scheduling queue of a cpu core. The thread is added at the
55 * back the queue in its priority level.
56 */
50 void Schedule(u32 priority, u32 core, Thread* thread); 57 void Schedule(u32 priority, u32 core, Thread* thread);
51 58
52 // Add a thread to the scheduling queue of a cpu core. The thread is added at the 59 /**
53 // front the queue in its priority level 60 * Add a thread to the scheduling queue of a cpu core. The thread is added at the
61 * front the queue in its priority level.
62 */
54 void SchedulePrepend(u32 priority, u32 core, Thread* thread); 63 void SchedulePrepend(u32 priority, u32 core, Thread* thread);
55 64
56 // Reschedule an already scheduled thread based on a new priority 65 /// Reschedule an already scheduled thread based on a new priority
57 void Reschedule(u32 priority, u32 core, Thread* thread); 66 void Reschedule(u32 priority, u32 core, Thread* thread);
58 67
59 // Unschedule a thread. 68 /// Unschedules a thread.
60 void Unschedule(u32 priority, u32 core, Thread* thread); 69 void Unschedule(u32 priority, u32 core, Thread* thread);
61 70
62 // Transfers a thread into an specific core. If the destination_core is -1 71 /**
63 // it will be unscheduled from its source code and added into its suggested 72 * Transfers a thread into an specific core. If the destination_core is -1
64 // queue. 73 * it will be unscheduled from its source code and added into its suggested
74 * queue.
75 */
65 void TransferToCore(u32 priority, s32 destination_core, Thread* thread); 76 void TransferToCore(u32 priority, s32 destination_core, Thread* thread);
66 77
67 /* 78 /// Selects a core and forces it to unload its current thread's context
68 * UnloadThread selects a core and forces it to unload its current thread's context
69 */
70 void UnloadThread(s32 core); 79 void UnloadThread(s32 core);
71 80
72 /* 81 /**
73 * SelectThread takes care of selecting the new scheduled thread. 82 * Takes care of selecting the new scheduled thread in three steps:
74 * It does it in 3 steps: 83 *
75 * - First a thread is selected from the top of the priority queue. If no thread 84 * 1. First a thread is selected from the top of the priority queue. If no thread
76 * is obtained then we move to step two, else we are done. 85 * is obtained then we move to step two, else we are done.
77 * - Second we try to get a suggested thread that's not assigned to any core or 86 *
78 * that is not the top thread in that core. 87 * 2. Second we try to get a suggested thread that's not assigned to any core or
79 * - Third is no suggested thread is found, we do a second pass and pick a running 88 * that is not the top thread in that core.
80 * thread in another core and swap it with its current thread. 89 *
90 * 3. Third is no suggested thread is found, we do a second pass and pick a running
91 * thread in another core and swap it with its current thread.
81 */ 92 */
82 void SelectThread(u32 core); 93 void SelectThread(u32 core);
83 94
@@ -85,33 +96,37 @@ public:
85 return !scheduled_queue[core_id].empty(); 96 return !scheduled_queue[core_id].empty();
86 } 97 }
87 98
88 /* 99 /**
89 * YieldThread takes a thread and moves it to the back of the it's priority list 100 * Takes a thread and moves it to the back of the it's priority list.
90 * This operation can be redundant and no scheduling is changed if marked as so. 101 *
102 * @note This operation can be redundant and no scheduling is changed if marked as so.
91 */ 103 */
92 bool YieldThread(Thread* thread); 104 bool YieldThread(Thread* thread);
93 105
94 /* 106 /**
95 * YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list. 107 * Takes a thread and moves it to the back of the it's priority list.
96 * Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or 108 * Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
97 * a better priority than the next thread in the core. 109 * a better priority than the next thread in the core.
98 * This operation can be redundant and no scheduling is changed if marked as so. 110 *
111 * @note This operation can be redundant and no scheduling is changed if marked as so.
99 */ 112 */
100 bool YieldThreadAndBalanceLoad(Thread* thread); 113 bool YieldThreadAndBalanceLoad(Thread* thread);
101 114
102 /* 115 /**
103 * YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue 116 * Takes a thread and moves it out of the scheduling queue.
104 * and into the suggested queue. If no thread can be squeduled afterwards in that core, 117 * and into the suggested queue. If no thread can be scheduled afterwards in that core,
105 * a suggested thread is obtained instead. 118 * a suggested thread is obtained instead.
106 * This operation can be redundant and no scheduling is changed if marked as so. 119 *
120 * @note This operation can be redundant and no scheduling is changed if marked as so.
107 */ 121 */
108 bool YieldThreadAndWaitForLoadBalancing(Thread* thread); 122 bool YieldThreadAndWaitForLoadBalancing(Thread* thread);
109 123
110 /* 124 /**
111 * PreemptThreads this operation rotates the scheduling queues of threads at 125 * Rotates the scheduling queues of threads at a preemption priority and then does
112 * a preemption priority and then does some core rebalancing. Preemption priorities 126 * some core rebalancing. Preemption priorities can be found in the array
113 * can be found in the array 'preemption_priorities'. This operation happens 127 * 'preemption_priorities'.
114 * every 10ms. 128 *
129 * @note This operation happens every 10ms.
115 */ 130 */
116 void PreemptThreads(); 131 void PreemptThreads();
117 132
@@ -130,15 +145,15 @@ public:
130 void Shutdown(); 145 void Shutdown();
131 146
132private: 147private:
133 bool AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner); 148 bool AskForReselectionOrMarkRedundant(Thread* current_thread, const Thread* winner);
134 149
135 static constexpr u32 min_regular_priority = 2; 150 static constexpr u32 min_regular_priority = 2;
136 std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> scheduled_queue; 151 std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> scheduled_queue;
137 std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> suggested_queue; 152 std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> suggested_queue;
138 std::atomic<bool> is_reselection_pending; 153 std::atomic<bool> is_reselection_pending{false};
139 154
140 // `preemption_priorities` are the priority levels at which the global scheduler 155 // The priority levels at which the global scheduler preempts threads every 10 ms. They are
141 // preempts threads every 10 ms. They are ordered from Core 0 to Core 3 156 // ordered from Core 0 to Core 3.
142 std::array<u32, NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; 157 std::array<u32, NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
143 158
144 /// Lists all thread ids that aren't deleted/etc. 159 /// Lists all thread ids that aren't deleted/etc.
@@ -181,10 +196,8 @@ public:
181 196
182private: 197private:
183 friend class GlobalScheduler; 198 friend class GlobalScheduler;
184 /** 199
185 * Switches the CPU's active thread context to that of the specified thread 200 /// Switches the CPU's active thread context to that of the specified thread
186 * @param new_thread The thread to switch to
187 */
188 void SwitchContext(); 201 void SwitchContext();
189 202
190 /** 203 /**
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3a32d5b41..3d8a91d22 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1073,9 +1073,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1073 {71, nullptr, "RequestToReboot"}, 1073 {71, nullptr, "RequestToReboot"},
1074 {80, nullptr, "ExitAndRequestToShowThanksMessage"}, 1074 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
1075 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, 1075 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
1076 {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"}, 1076 {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
1077 {101, nullptr, "SetApplicationCopyrightImage"}, 1077 {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
1078 {102, nullptr, "SetApplicationCopyrightVisibility"}, 1078 {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
1079 {110, nullptr, "QueryApplicationPlayStatistics"}, 1079 {110, nullptr, "QueryApplicationPlayStatistics"},
1080 {120, nullptr, "ExecuteProgram"}, 1080 {120, nullptr, "ExecuteProgram"},
1081 {121, nullptr, "ClearUserChannel"}, 1081 {121, nullptr, "ClearUserChannel"},
@@ -1103,6 +1103,31 @@ void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestConte
1103 rb.Push(RESULT_SUCCESS); 1103 rb.Push(RESULT_SUCCESS);
1104} 1104}
1105 1105
1106void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
1107 Kernel::HLERequestContext& ctx) {
1108 LOG_WARNING(Service_AM, "(STUBBED) called");
1109
1110 IPC::ResponseBuilder rb{ctx, 2};
1111 rb.Push(RESULT_SUCCESS);
1112}
1113
1114void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) {
1115 LOG_WARNING(Service_AM, "(STUBBED) called");
1116
1117 IPC::ResponseBuilder rb{ctx, 2};
1118 rb.Push(RESULT_SUCCESS);
1119}
1120
1121void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) {
1122 IPC::RequestParser rp{ctx};
1123 const auto is_visible = rp.Pop<bool>();
1124
1125 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
1126
1127 IPC::ResponseBuilder rb{ctx, 2};
1128 rb.Push(RESULT_SUCCESS);
1129}
1130
1106void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed( 1131void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
1107 Kernel::HLERequestContext& ctx) { 1132 Kernel::HLERequestContext& ctx) {
1108 LOG_WARNING(Service_AM, "(STUBBED) called"); 1133 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:
252 void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx); 252 void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
253 void EndBlockingHomeButton(Kernel::HLERequestContext& ctx); 253 void EndBlockingHomeButton(Kernel::HLERequestContext& ctx);
254 void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx); 254 void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
255 void InitializeApplicationCopyrightFrameBuffer(Kernel::HLERequestContext& ctx);
256 void SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx);
257 void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
255 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); 258 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
256 259
257 bool launch_popped_application_specific = false; 260 bool launch_popped_application_specific = false;
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 {
20struct ShowError { 20struct ShowError {
21 u8 mode; 21 u8 mode;
22 bool jump; 22 bool jump;
23 INSERT_PADDING_BYTES(4); 23 INSERT_UNION_PADDING_BYTES(4);
24 bool use_64bit_error_code; 24 bool use_64bit_error_code;
25 INSERT_PADDING_BYTES(1); 25 INSERT_UNION_PADDING_BYTES(1);
26 u64 error_code_64; 26 u64 error_code_64;
27 u32 error_code_32; 27 u32 error_code_32;
28}; 28};
@@ -32,7 +32,7 @@ static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
32struct ShowErrorRecord { 32struct ShowErrorRecord {
33 u8 mode; 33 u8 mode;
34 bool jump; 34 bool jump;
35 INSERT_PADDING_BYTES(6); 35 INSERT_UNION_PADDING_BYTES(6);
36 u64 error_code_64; 36 u64 error_code_64;
37 u64 posix_time; 37 u64 posix_time;
38}; 38};
@@ -41,7 +41,7 @@ static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect si
41struct SystemErrorArg { 41struct SystemErrorArg {
42 u8 mode; 42 u8 mode;
43 bool jump; 43 bool jump;
44 INSERT_PADDING_BYTES(6); 44 INSERT_UNION_PADDING_BYTES(6);
45 u64 error_code_64; 45 u64 error_code_64;
46 std::array<char, 8> language_code; 46 std::array<char, 8> language_code;
47 std::array<char, 0x800> main_text; 47 std::array<char, 0x800> main_text;
@@ -52,7 +52,7 @@ static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect si
52struct ApplicationErrorArg { 52struct ApplicationErrorArg {
53 u8 mode; 53 u8 mode;
54 bool jump; 54 bool jump;
55 INSERT_PADDING_BYTES(6); 55 INSERT_UNION_PADDING_BYTES(6);
56 u32 error_code; 56 u32 error_code;
57 std::array<char, 8> language_code; 57 std::array<char, 8> language_code;
58 std::array<char, 0x800> main_text; 58 std::array<char, 0x800> main_text;
@@ -65,6 +65,7 @@ union Error::ErrorArguments {
65 ShowErrorRecord error_record; 65 ShowErrorRecord error_record;
66 SystemErrorArg system_error; 66 SystemErrorArg system_error;
67 ApplicationErrorArg application_error; 67 ApplicationErrorArg application_error;
68 std::array<u8, 0x1018> raw{};
68}; 69};
69 70
70namespace { 71namespace {
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) {
203 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, 203 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
204 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, 204 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
205 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, 205 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
206 {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, 206 {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
207 {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, 207 {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
208 {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"}, 208 {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
209 {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"}, 209 {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
210 {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"}, 210 {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
211 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, 211 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
212 {129, nullptr, "GetNpadHandheldActivationMode"}, 212 {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
213 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, 213 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
214 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, 214 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
215 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, 215 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
@@ -557,10 +557,126 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
557 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, 557 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
558 applet_resource_user_id); 558 applet_resource_user_id);
559 559
560 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
561 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
562
563 IPC::ResponseBuilder rb{ctx, 2};
564 rb.Push(RESULT_SUCCESS);
565}
566
567void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
568 // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
569 IPC::RequestParser rp{ctx};
570 const auto npad_id{rp.Pop<u32>()};
571 const auto applet_resource_user_id{rp.Pop<u64>()};
572 const auto npad_joy_device_type{rp.Pop<u64>()};
573
574 LOG_WARNING(Service_HID,
575 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
576 npad_id, applet_resource_user_id, npad_joy_device_type);
577
578 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
579 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
580
581 IPC::ResponseBuilder rb{ctx, 2};
582 rb.Push(RESULT_SUCCESS);
583}
584
585void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
586 IPC::RequestParser rp{ctx};
587 const auto npad_id{rp.Pop<u32>()};
588 const auto applet_resource_user_id{rp.Pop<u64>()};
589
590 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
591 applet_resource_user_id);
592
593 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
594 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
595
596 IPC::ResponseBuilder rb{ctx, 2};
597 rb.Push(RESULT_SUCCESS);
598}
599
600void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
601 IPC::RequestParser rp{ctx};
602 const auto unknown_1{rp.Pop<u32>()};
603 const auto unknown_2{rp.Pop<u32>()};
604 const auto applet_resource_user_id{rp.Pop<u64>()};
605
606 LOG_WARNING(Service_HID,
607 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
608 unknown_1, unknown_2, applet_resource_user_id);
609
610 IPC::ResponseBuilder rb{ctx, 2};
611 rb.Push(RESULT_SUCCESS);
612}
613
614void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
615 IPC::RequestParser rp{ctx};
616 const auto applet_resource_user_id{rp.Pop<u64>()};
617
618 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
619 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
620 controller.StartLRAssignmentMode();
621
622 IPC::ResponseBuilder rb{ctx, 2};
623 rb.Push(RESULT_SUCCESS);
624}
625
626void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
627 IPC::RequestParser rp{ctx};
628 const auto applet_resource_user_id{rp.Pop<u64>()};
629
630 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
631 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
632 controller.StopLRAssignmentMode();
633
634 IPC::ResponseBuilder rb{ctx, 2};
635 rb.Push(RESULT_SUCCESS);
636}
637
638void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
639 IPC::RequestParser rp{ctx};
640 const auto applet_resource_user_id{rp.Pop<u64>()};
641 const auto mode{rp.Pop<u64>()};
642
643 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
644 applet_resource_user_id, mode);
645
646 IPC::ResponseBuilder rb{ctx, 2};
647 rb.Push(RESULT_SUCCESS);
648}
649
650void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
651 IPC::RequestParser rp{ctx};
652 const auto applet_resource_user_id{rp.Pop<u64>()};
653
654 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
655 applet_resource_user_id);
656
560 IPC::ResponseBuilder rb{ctx, 2}; 657 IPC::ResponseBuilder rb{ctx, 2};
561 rb.Push(RESULT_SUCCESS); 658 rb.Push(RESULT_SUCCESS);
562} 659}
563 660
661void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
662 IPC::RequestParser rp{ctx};
663 const auto npad_1{rp.Pop<u32>()};
664 const auto npad_2{rp.Pop<u32>()};
665 const auto applet_resource_user_id{rp.Pop<u64>()};
666
667 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
668 applet_resource_user_id, npad_1, npad_2);
669
670 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
671 IPC::ResponseBuilder rb{ctx, 2};
672 if (controller.SwapNpadAssignment(npad_1, npad_2)) {
673 rb.Push(RESULT_SUCCESS);
674 } else {
675 LOG_ERROR(Service_HID, "Npads are not connected!");
676 rb.Push(ERR_NPAD_NOT_CONNECTED);
677 }
678}
679
564void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { 680void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
565 IPC::RequestParser rp{ctx}; 681 IPC::RequestParser rp{ctx};
566 const auto applet_resource_user_id{rp.Pop<u64>()}; 682 const auto applet_resource_user_id{rp.Pop<u64>()};
@@ -635,47 +751,6 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
635 applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); 751 applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration());
636} 752}
637 753
638void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
639 IPC::RequestParser rp{ctx};
640 const auto npad_id{rp.Pop<u32>()};
641 const auto applet_resource_user_id{rp.Pop<u64>()};
642
643 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
644 applet_resource_user_id);
645
646 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
647 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
648
649 IPC::ResponseBuilder rb{ctx, 2};
650 rb.Push(RESULT_SUCCESS);
651}
652
653void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
654 IPC::RequestParser rp{ctx};
655 const auto unknown_1{rp.Pop<u32>()};
656 const auto unknown_2{rp.Pop<u32>()};
657 const auto applet_resource_user_id{rp.Pop<u64>()};
658
659 LOG_WARNING(Service_HID,
660 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
661 unknown_1, unknown_2, applet_resource_user_id);
662
663 IPC::ResponseBuilder rb{ctx, 2};
664 rb.Push(RESULT_SUCCESS);
665}
666
667void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
668 IPC::RequestParser rp{ctx};
669 const auto applet_resource_user_id{rp.Pop<u64>()};
670 const auto mode{rp.Pop<u64>()};
671
672 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
673 applet_resource_user_id, mode);
674
675 IPC::ResponseBuilder rb{ctx, 2};
676 rb.Push(RESULT_SUCCESS);
677}
678
679void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 754void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
680 LOG_DEBUG(Service_HID, "called"); 755 LOG_DEBUG(Service_HID, "called");
681 756
@@ -769,49 +844,6 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
769 rb.Push(RESULT_SUCCESS); 844 rb.Push(RESULT_SUCCESS);
770} 845}
771 846
772void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
773 IPC::RequestParser rp{ctx};
774 const auto applet_resource_user_id{rp.Pop<u64>()};
775
776 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
777 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
778 controller.StartLRAssignmentMode();
779
780 IPC::ResponseBuilder rb{ctx, 2};
781 rb.Push(RESULT_SUCCESS);
782}
783
784void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
785 IPC::RequestParser rp{ctx};
786 const auto applet_resource_user_id{rp.Pop<u64>()};
787
788 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
789 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
790 controller.StopLRAssignmentMode();
791
792 IPC::ResponseBuilder rb{ctx, 2};
793 rb.Push(RESULT_SUCCESS);
794}
795
796void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
797 IPC::RequestParser rp{ctx};
798 const auto npad_1{rp.Pop<u32>()};
799 const auto npad_2{rp.Pop<u32>()};
800 const auto applet_resource_user_id{rp.Pop<u64>()};
801
802 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
803 applet_resource_user_id, npad_1, npad_2);
804
805 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
806 IPC::ResponseBuilder rb{ctx, 2};
807 if (controller.SwapNpadAssignment(npad_1, npad_2)) {
808 rb.Push(RESULT_SUCCESS);
809 } else {
810 LOG_ERROR(Service_HID, "Npads are not connected!");
811 rb.Push(ERR_NPAD_NOT_CONNECTED);
812 }
813}
814
815class HidDbg final : public ServiceFramework<HidDbg> { 847class HidDbg final : public ServiceFramework<HidDbg> {
816public: 848public:
817 explicit HidDbg() : ServiceFramework{"hid:dbg"} { 849 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:
106 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); 106 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
107 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); 107 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
108 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); 108 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx);
109 void SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx);
110 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
111 void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
112 void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
113 void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
114 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
115 void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
116 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
109 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); 117 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
110 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); 118 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
111 void SendVibrationValue(Kernel::HLERequestContext& ctx); 119 void SendVibrationValue(Kernel::HLERequestContext& ctx);
112 void SendVibrationValues(Kernel::HLERequestContext& ctx); 120 void SendVibrationValues(Kernel::HLERequestContext& ctx);
113 void GetActualVibrationValue(Kernel::HLERequestContext& ctx); 121 void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
114 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
115 void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
116 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
117 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); 122 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
118 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); 123 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx);
119 void PermitVibration(Kernel::HLERequestContext& ctx); 124 void PermitVibration(Kernel::HLERequestContext& ctx);
@@ -123,9 +128,6 @@ private:
123 void StopSixAxisSensor(Kernel::HLERequestContext& ctx); 128 void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
124 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); 129 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
125 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); 130 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
126 void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
127 void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
128 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
129 131
130 std::shared_ptr<IAppletResource> applet_resource; 132 std::shared_ptr<IAppletResource> applet_resource;
131 Core::System& system; 133 Core::System& system;
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 {
45 45
46 /// Whether or not the display has a limited number of layers. 46 /// Whether or not the display has a limited number of layers.
47 u8 has_limited_layers{1}; 47 u8 has_limited_layers{1};
48 INSERT_PADDING_BYTES(7){}; 48 INSERT_PADDING_BYTES(7);
49 49
50 /// Indicates the total amount of layers supported by the display. 50 /// Indicates the total amount of layers supported by the display.
51 /// @note This is only valid if has_limited_layers is set. 51 /// @note This is only valid if has_limited_layers is set.
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index cb6eda1b8..c911c6ec4 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -36,6 +36,8 @@ add_library(video_core STATIC
36 memory_manager.h 36 memory_manager.h
37 morton.cpp 37 morton.cpp
38 morton.h 38 morton.h
39 rasterizer_accelerated.cpp
40 rasterizer_accelerated.h
39 rasterizer_cache.cpp 41 rasterizer_cache.cpp
40 rasterizer_cache.h 42 rasterizer_cache.h
41 rasterizer_interface.h 43 rasterizer_interface.h
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) {
28 } 28 }
29} 29}
30 30
31std::pair<u32, u32> DelimitLine(u32 src_1, u32 src_2, u32 dst_1, u32 dst_2, u32 src_line) {
32 const u32 line_a = src_2 - src_1;
33 const u32 line_b = dst_2 - dst_1;
34 const u32 excess = std::max<s32>(0, line_a - src_line + src_1);
35 return {line_b - (excess * line_b) / line_a, excess};
36}
37
31void Fermi2D::HandleSurfaceCopy() { 38void Fermi2D::HandleSurfaceCopy() {
32 LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}", 39 LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}",
33 static_cast<u32>(regs.operation)); 40 static_cast<u32>(regs.operation));
@@ -47,10 +54,27 @@ void Fermi2D::HandleSurfaceCopy() {
47 src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width); 54 src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width);
48 src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height); 55 src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height);
49 } 56 }
57 u32 dst_blit_x2 = regs.blit_dst_x + regs.blit_dst_width;
58 u32 dst_blit_y2 = regs.blit_dst_y + regs.blit_dst_height;
59 const auto [new_dst_w, src_excess_x] =
60 DelimitLine(src_blit_x1, src_blit_x2, regs.blit_dst_x, dst_blit_x2, regs.src.width);
61 const auto [new_dst_h, src_excess_y] =
62 DelimitLine(src_blit_y1, src_blit_y2, regs.blit_dst_y, dst_blit_y2, regs.src.height);
63 dst_blit_x2 = new_dst_w + regs.blit_dst_x;
64 src_blit_x2 = src_blit_x2 - src_excess_x;
65 dst_blit_y2 = new_dst_h + regs.blit_dst_y;
66 src_blit_y2 = src_blit_y2 - src_excess_y;
67 const auto [new_src_w, dst_excess_x] =
68 DelimitLine(regs.blit_dst_x, dst_blit_x2, src_blit_x1, src_blit_x2, regs.dst.width);
69 const auto [new_src_h, dst_excess_y] =
70 DelimitLine(regs.blit_dst_y, dst_blit_y2, src_blit_y1, src_blit_y2, regs.dst.height);
71 src_blit_x2 = new_src_w + src_blit_x1;
72 dst_blit_x2 = dst_blit_x2 - dst_excess_x;
73 src_blit_y2 = new_src_h + src_blit_y1;
74 dst_blit_y2 = dst_blit_y2 - dst_excess_y;
50 const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2}; 75 const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
51 const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, 76 const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2,
52 regs.blit_dst_x + regs.blit_dst_width, 77 dst_blit_y2};
53 regs.blit_dst_y + regs.blit_dst_height};
54 Config copy_config; 78 Config copy_config;
55 copy_config.operation = regs.operation; 79 copy_config.operation = regs.operation;
56 copy_config.filter = regs.blit_control.filter; 80 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:
99 99
100 union { 100 union {
101 struct { 101 struct {
102 INSERT_PADDING_WORDS(0x80); 102 INSERT_UNION_PADDING_WORDS(0x80);
103 103
104 Surface dst; 104 Surface dst;
105 105
106 INSERT_PADDING_WORDS(2); 106 INSERT_UNION_PADDING_WORDS(2);
107 107
108 Surface src; 108 Surface src;
109 109
110 INSERT_PADDING_WORDS(0x15); 110 INSERT_UNION_PADDING_WORDS(0x15);
111 111
112 Operation operation; 112 Operation operation;
113 113
114 INSERT_PADDING_WORDS(0x177); 114 INSERT_UNION_PADDING_WORDS(0x177);
115 115
116 union { 116 union {
117 u32 raw; 117 u32 raw;
@@ -119,7 +119,7 @@ public:
119 BitField<4, 1, Filter> filter; 119 BitField<4, 1, Filter> filter;
120 } blit_control; 120 } blit_control;
121 121
122 INSERT_PADDING_WORDS(0x8); 122 INSERT_UNION_PADDING_WORDS(0x8);
123 123
124 u32 blit_dst_x; 124 u32 blit_dst_x;
125 u32 blit_dst_y; 125 u32 blit_dst_y;
@@ -130,7 +130,7 @@ public:
130 u64 blit_src_x; 130 u64 blit_src_x;
131 u64 blit_src_y; 131 u64 blit_src_y;
132 132
133 INSERT_PADDING_WORDS(0x21); 133 INSERT_UNION_PADDING_WORDS(0x21);
134 }; 134 };
135 std::array<u32, NUM_REGS> reg_array; 135 std::array<u32, NUM_REGS> reg_array;
136 }; 136 };
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:
51 51
52 union { 52 union {
53 struct { 53 struct {
54 INSERT_PADDING_WORDS(0x60); 54 INSERT_UNION_PADDING_WORDS(0x60);
55 55
56 Upload::Registers upload; 56 Upload::Registers upload;
57 57
@@ -63,7 +63,7 @@ public:
63 63
64 u32 data_upload; 64 u32 data_upload;
65 65
66 INSERT_PADDING_WORDS(0x3F); 66 INSERT_UNION_PADDING_WORDS(0x3F);
67 67
68 struct { 68 struct {
69 u32 address; 69 u32 address;
@@ -72,11 +72,11 @@ public:
72 } 72 }
73 } launch_desc_loc; 73 } launch_desc_loc;
74 74
75 INSERT_PADDING_WORDS(0x1); 75 INSERT_UNION_PADDING_WORDS(0x1);
76 76
77 u32 launch; 77 u32 launch;
78 78
79 INSERT_PADDING_WORDS(0x4A7); 79 INSERT_UNION_PADDING_WORDS(0x4A7);
80 80
81 struct { 81 struct {
82 u32 address_high; 82 u32 address_high;
@@ -88,7 +88,7 @@ public:
88 } 88 }
89 } tsc; 89 } tsc;
90 90
91 INSERT_PADDING_WORDS(0x3); 91 INSERT_UNION_PADDING_WORDS(0x3);
92 92
93 struct { 93 struct {
94 u32 address_high; 94 u32 address_high;
@@ -100,7 +100,7 @@ public:
100 } 100 }
101 } tic; 101 } tic;
102 102
103 INSERT_PADDING_WORDS(0x22); 103 INSERT_UNION_PADDING_WORDS(0x22);
104 104
105 struct { 105 struct {
106 u32 address_high; 106 u32 address_high;
@@ -111,11 +111,11 @@ public:
111 } 111 }
112 } code_loc; 112 } code_loc;
113 113
114 INSERT_PADDING_WORDS(0x3FE); 114 INSERT_UNION_PADDING_WORDS(0x3FE);
115 115
116 u32 tex_cb_index; 116 u32 tex_cb_index;
117 117
118 INSERT_PADDING_WORDS(0x374); 118 INSERT_UNION_PADDING_WORDS(0x374);
119 }; 119 };
120 std::array<u32, NUM_REGS> reg_array; 120 std::array<u32, NUM_REGS> reg_array;
121 }; 121 };
@@ -179,7 +179,7 @@ public:
179 }; 179 };
180 180
181 INSERT_PADDING_WORDS(0x11); 181 INSERT_PADDING_WORDS(0x11);
182 } launch_description; 182 } launch_description{};
183 183
184 struct { 184 struct {
185 u32 write_offset = 0; 185 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:
45 45
46 union { 46 union {
47 struct { 47 struct {
48 INSERT_PADDING_WORDS(0x60); 48 INSERT_UNION_PADDING_WORDS(0x60);
49 49
50 Upload::Registers upload; 50 Upload::Registers upload;
51 51
@@ -57,7 +57,7 @@ public:
57 57
58 u32 data; 58 u32 data;
59 59
60 INSERT_PADDING_WORDS(0x11); 60 INSERT_UNION_PADDING_WORDS(0x11);
61 }; 61 };
62 std::array<u32, NUM_REGS> reg_array; 62 std::array<u32, NUM_REGS> reg_array;
63 }; 63 };
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:
496 Equation equation_a; 496 Equation equation_a;
497 Factor factor_source_a; 497 Factor factor_source_a;
498 Factor factor_dest_a; 498 Factor factor_dest_a;
499 INSERT_PADDING_WORDS(1); 499 INSERT_UNION_PADDING_WORDS(1);
500 }; 500 };
501 501
502 struct RenderTargetConfig { 502 struct RenderTargetConfig {
@@ -517,7 +517,7 @@ public:
517 }; 517 };
518 u32 layer_stride; 518 u32 layer_stride;
519 u32 base_layer; 519 u32 base_layer;
520 INSERT_PADDING_WORDS(7); 520 INSERT_UNION_PADDING_WORDS(7);
521 521
522 GPUVAddr Address() const { 522 GPUVAddr Address() const {
523 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | 523 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -542,7 +542,7 @@ public:
542 f32 translate_x; 542 f32 translate_x;
543 f32 translate_y; 543 f32 translate_y;
544 f32 translate_z; 544 f32 translate_z;
545 INSERT_PADDING_WORDS(2); 545 INSERT_UNION_PADDING_WORDS(2);
546 546
547 Common::Rectangle<s32> GetRect() const { 547 Common::Rectangle<s32> GetRect() const {
548 return { 548 return {
@@ -606,7 +606,7 @@ public:
606 606
607 union { 607 union {
608 struct { 608 struct {
609 INSERT_PADDING_WORDS(0x45); 609 INSERT_UNION_PADDING_WORDS(0x45);
610 610
611 struct { 611 struct {
612 u32 upload_address; 612 u32 upload_address;
@@ -615,7 +615,7 @@ public:
615 u32 bind; 615 u32 bind;
616 } macros; 616 } macros;
617 617
618 INSERT_PADDING_WORDS(0x17); 618 INSERT_UNION_PADDING_WORDS(0x17);
619 619
620 Upload::Registers upload; 620 Upload::Registers upload;
621 struct { 621 struct {
@@ -626,7 +626,7 @@ public:
626 626
627 u32 data_upload; 627 u32 data_upload;
628 628
629 INSERT_PADDING_WORDS(0x44); 629 INSERT_UNION_PADDING_WORDS(0x44);
630 630
631 struct { 631 struct {
632 union { 632 union {
@@ -636,11 +636,11 @@ public:
636 }; 636 };
637 } sync_info; 637 } sync_info;
638 638
639 INSERT_PADDING_WORDS(0x11E); 639 INSERT_UNION_PADDING_WORDS(0x11E);
640 640
641 u32 tfb_enabled; 641 u32 tfb_enabled;
642 642
643 INSERT_PADDING_WORDS(0x2E); 643 INSERT_UNION_PADDING_WORDS(0x2E);
644 644
645 std::array<RenderTargetConfig, NumRenderTargets> rt; 645 std::array<RenderTargetConfig, NumRenderTargets> rt;
646 646
@@ -648,49 +648,49 @@ public:
648 648
649 std::array<ViewPort, NumViewports> viewports; 649 std::array<ViewPort, NumViewports> viewports;
650 650
651 INSERT_PADDING_WORDS(0x1D); 651 INSERT_UNION_PADDING_WORDS(0x1D);
652 652
653 struct { 653 struct {
654 u32 first; 654 u32 first;
655 u32 count; 655 u32 count;
656 } vertex_buffer; 656 } vertex_buffer;
657 657
658 INSERT_PADDING_WORDS(1); 658 INSERT_UNION_PADDING_WORDS(1);
659 659
660 float clear_color[4]; 660 float clear_color[4];
661 float clear_depth; 661 float clear_depth;
662 662
663 INSERT_PADDING_WORDS(0x3); 663 INSERT_UNION_PADDING_WORDS(0x3);
664 664
665 s32 clear_stencil; 665 s32 clear_stencil;
666 666
667 INSERT_PADDING_WORDS(0x7); 667 INSERT_UNION_PADDING_WORDS(0x7);
668 668
669 u32 polygon_offset_point_enable; 669 u32 polygon_offset_point_enable;
670 u32 polygon_offset_line_enable; 670 u32 polygon_offset_line_enable;
671 u32 polygon_offset_fill_enable; 671 u32 polygon_offset_fill_enable;
672 672
673 INSERT_PADDING_WORDS(0xD); 673 INSERT_UNION_PADDING_WORDS(0xD);
674 674
675 std::array<ScissorTest, NumViewports> scissor_test; 675 std::array<ScissorTest, NumViewports> scissor_test;
676 676
677 INSERT_PADDING_WORDS(0x15); 677 INSERT_UNION_PADDING_WORDS(0x15);
678 678
679 s32 stencil_back_func_ref; 679 s32 stencil_back_func_ref;
680 u32 stencil_back_mask; 680 u32 stencil_back_mask;
681 u32 stencil_back_func_mask; 681 u32 stencil_back_func_mask;
682 682
683 INSERT_PADDING_WORDS(0xC); 683 INSERT_UNION_PADDING_WORDS(0xC);
684 684
685 u32 color_mask_common; 685 u32 color_mask_common;
686 686
687 INSERT_PADDING_WORDS(0x6); 687 INSERT_UNION_PADDING_WORDS(0x6);
688 688
689 u32 rt_separate_frag_data; 689 u32 rt_separate_frag_data;
690 690
691 f32 depth_bounds[2]; 691 f32 depth_bounds[2];
692 692
693 INSERT_PADDING_WORDS(0xA); 693 INSERT_UNION_PADDING_WORDS(0xA);
694 694
695 struct { 695 struct {
696 u32 address_high; 696 u32 address_high;
@@ -710,7 +710,7 @@ public:
710 } 710 }
711 } zeta; 711 } zeta;
712 712
713 INSERT_PADDING_WORDS(0x41); 713 INSERT_UNION_PADDING_WORDS(0x41);
714 714
715 union { 715 union {
716 BitField<0, 4, u32> stencil; 716 BitField<0, 4, u32> stencil;
@@ -719,11 +719,11 @@ public:
719 BitField<12, 4, u32> viewport; 719 BitField<12, 4, u32> viewport;
720 } clear_flags; 720 } clear_flags;
721 721
722 INSERT_PADDING_WORDS(0x19); 722 INSERT_UNION_PADDING_WORDS(0x19);
723 723
724 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; 724 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
725 725
726 INSERT_PADDING_WORDS(0xF); 726 INSERT_UNION_PADDING_WORDS(0xF);
727 727
728 struct { 728 struct {
729 union { 729 union {
@@ -746,16 +746,16 @@ public:
746 } 746 }
747 } rt_control; 747 } rt_control;
748 748
749 INSERT_PADDING_WORDS(0x2); 749 INSERT_UNION_PADDING_WORDS(0x2);
750 750
751 u32 zeta_width; 751 u32 zeta_width;
752 u32 zeta_height; 752 u32 zeta_height;
753 753
754 INSERT_PADDING_WORDS(0x27); 754 INSERT_UNION_PADDING_WORDS(0x27);
755 755
756 u32 depth_test_enable; 756 u32 depth_test_enable;
757 757
758 INSERT_PADDING_WORDS(0x5); 758 INSERT_UNION_PADDING_WORDS(0x5);
759 759
760 u32 independent_blend_enable; 760 u32 independent_blend_enable;
761 761
@@ -763,7 +763,7 @@ public:
763 763
764 u32 alpha_test_enabled; 764 u32 alpha_test_enabled;
765 765
766 INSERT_PADDING_WORDS(0x6); 766 INSERT_UNION_PADDING_WORDS(0x6);
767 767
768 u32 d3d_cull_mode; 768 u32 d3d_cull_mode;
769 769
@@ -777,7 +777,7 @@ public:
777 float b; 777 float b;
778 float a; 778 float a;
779 } blend_color; 779 } blend_color;
780 INSERT_PADDING_WORDS(0x4); 780 INSERT_UNION_PADDING_WORDS(0x4);
781 781
782 struct { 782 struct {
783 u32 separate_alpha; 783 u32 separate_alpha;
@@ -786,7 +786,7 @@ public:
786 Blend::Factor factor_dest_rgb; 786 Blend::Factor factor_dest_rgb;
787 Blend::Equation equation_a; 787 Blend::Equation equation_a;
788 Blend::Factor factor_source_a; 788 Blend::Factor factor_source_a;
789 INSERT_PADDING_WORDS(1); 789 INSERT_UNION_PADDING_WORDS(1);
790 Blend::Factor factor_dest_a; 790 Blend::Factor factor_dest_a;
791 791
792 u32 enable_common; 792 u32 enable_common;
@@ -802,7 +802,7 @@ public:
802 u32 stencil_front_func_mask; 802 u32 stencil_front_func_mask;
803 u32 stencil_front_mask; 803 u32 stencil_front_mask;
804 804
805 INSERT_PADDING_WORDS(0x2); 805 INSERT_UNION_PADDING_WORDS(0x2);
806 806
807 u32 frag_color_clamp; 807 u32 frag_color_clamp;
808 808
@@ -811,12 +811,12 @@ public:
811 BitField<4, 1, u32> triangle_rast_flip; 811 BitField<4, 1, u32> triangle_rast_flip;
812 } screen_y_control; 812 } screen_y_control;
813 813
814 INSERT_PADDING_WORDS(0x21); 814 INSERT_UNION_PADDING_WORDS(0x21);
815 815
816 u32 vb_element_base; 816 u32 vb_element_base;
817 u32 vb_base_instance; 817 u32 vb_base_instance;
818 818
819 INSERT_PADDING_WORDS(0x35); 819 INSERT_UNION_PADDING_WORDS(0x35);
820 820
821 union { 821 union {
822 BitField<0, 1, u32> c0; 822 BitField<0, 1, u32> c0;
@@ -829,11 +829,11 @@ public:
829 BitField<7, 1, u32> c7; 829 BitField<7, 1, u32> c7;
830 } clip_distance_enabled; 830 } clip_distance_enabled;
831 831
832 INSERT_PADDING_WORDS(0x1); 832 INSERT_UNION_PADDING_WORDS(0x1);
833 833
834 float point_size; 834 float point_size;
835 835
836 INSERT_PADDING_WORDS(0x7); 836 INSERT_UNION_PADDING_WORDS(0x7);
837 837
838 u32 zeta_enable; 838 u32 zeta_enable;
839 839
@@ -842,7 +842,7 @@ public:
842 BitField<4, 1, u32> alpha_to_one; 842 BitField<4, 1, u32> alpha_to_one;
843 } multisample_control; 843 } multisample_control;
844 844
845 INSERT_PADDING_WORDS(0x4); 845 INSERT_UNION_PADDING_WORDS(0x4);
846 846
847 struct { 847 struct {
848 u32 address_high; 848 u32 address_high;
@@ -866,11 +866,11 @@ public:
866 } 866 }
867 } tsc; 867 } tsc;
868 868
869 INSERT_PADDING_WORDS(0x1); 869 INSERT_UNION_PADDING_WORDS(0x1);
870 870
871 float polygon_offset_factor; 871 float polygon_offset_factor;
872 872
873 INSERT_PADDING_WORDS(0x1); 873 INSERT_UNION_PADDING_WORDS(0x1);
874 874
875 struct { 875 struct {
876 u32 tic_address_high; 876 u32 tic_address_high;
@@ -883,7 +883,7 @@ public:
883 } 883 }
884 } tic; 884 } tic;
885 885
886 INSERT_PADDING_WORDS(0x5); 886 INSERT_UNION_PADDING_WORDS(0x5);
887 887
888 u32 stencil_two_side_enable; 888 u32 stencil_two_side_enable;
889 StencilOp stencil_back_op_fail; 889 StencilOp stencil_back_op_fail;
@@ -891,13 +891,13 @@ public:
891 StencilOp stencil_back_op_zpass; 891 StencilOp stencil_back_op_zpass;
892 ComparisonOp stencil_back_func_func; 892 ComparisonOp stencil_back_func_func;
893 893
894 INSERT_PADDING_WORDS(0x4); 894 INSERT_UNION_PADDING_WORDS(0x4);
895 895
896 u32 framebuffer_srgb; 896 u32 framebuffer_srgb;
897 897
898 float polygon_offset_units; 898 float polygon_offset_units;
899 899
900 INSERT_PADDING_WORDS(0x11); 900 INSERT_UNION_PADDING_WORDS(0x11);
901 901
902 union { 902 union {
903 BitField<2, 1, u32> coord_origin; 903 BitField<2, 1, u32> coord_origin;
@@ -913,7 +913,7 @@ public:
913 (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low); 913 (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
914 } 914 }
915 } code_address; 915 } code_address;
916 INSERT_PADDING_WORDS(1); 916 INSERT_UNION_PADDING_WORDS(1);
917 917
918 struct { 918 struct {
919 u32 vertex_end_gl; 919 u32 vertex_end_gl;
@@ -925,14 +925,14 @@ public:
925 }; 925 };
926 } draw; 926 } draw;
927 927
928 INSERT_PADDING_WORDS(0xA); 928 INSERT_UNION_PADDING_WORDS(0xA);
929 929
930 struct { 930 struct {
931 u32 enabled; 931 u32 enabled;
932 u32 index; 932 u32 index;
933 } primitive_restart; 933 } primitive_restart;
934 934
935 INSERT_PADDING_WORDS(0x5F); 935 INSERT_UNION_PADDING_WORDS(0x5F);
936 936
937 struct { 937 struct {
938 u32 start_addr_high; 938 u32 start_addr_high;
@@ -973,9 +973,9 @@ public:
973 } 973 }
974 } index_array; 974 } index_array;
975 975
976 INSERT_PADDING_WORDS(0x7); 976 INSERT_UNION_PADDING_WORDS(0x7);
977 977
978 INSERT_PADDING_WORDS(0x1F); 978 INSERT_UNION_PADDING_WORDS(0x1F);
979 979
980 float polygon_offset_clamp; 980 float polygon_offset_clamp;
981 981
@@ -989,17 +989,17 @@ public:
989 } 989 }
990 } instanced_arrays; 990 } instanced_arrays;
991 991
992 INSERT_PADDING_WORDS(0x6); 992 INSERT_UNION_PADDING_WORDS(0x6);
993 993
994 Cull cull; 994 Cull cull;
995 995
996 u32 pixel_center_integer; 996 u32 pixel_center_integer;
997 997
998 INSERT_PADDING_WORDS(0x1); 998 INSERT_UNION_PADDING_WORDS(0x1);
999 999
1000 u32 viewport_transform_enabled; 1000 u32 viewport_transform_enabled;
1001 1001
1002 INSERT_PADDING_WORDS(0x3); 1002 INSERT_UNION_PADDING_WORDS(0x3);
1003 1003
1004 union { 1004 union {
1005 BitField<0, 1, u32> depth_range_0_1; 1005 BitField<0, 1, u32> depth_range_0_1;
@@ -1007,13 +1007,13 @@ public:
1007 BitField<4, 1, u32> depth_clamp_far; 1007 BitField<4, 1, u32> depth_clamp_far;
1008 } view_volume_clip_control; 1008 } view_volume_clip_control;
1009 1009
1010 INSERT_PADDING_WORDS(0x21); 1010 INSERT_UNION_PADDING_WORDS(0x21);
1011 struct { 1011 struct {
1012 u32 enable; 1012 u32 enable;
1013 LogicOperation operation; 1013 LogicOperation operation;
1014 } logic_op; 1014 } logic_op;
1015 1015
1016 INSERT_PADDING_WORDS(0x1); 1016 INSERT_UNION_PADDING_WORDS(0x1);
1017 1017
1018 union { 1018 union {
1019 u32 raw; 1019 u32 raw;
@@ -1026,9 +1026,9 @@ public:
1026 BitField<6, 4, u32> RT; 1026 BitField<6, 4, u32> RT;
1027 BitField<10, 11, u32> layer; 1027 BitField<10, 11, u32> layer;
1028 } clear_buffers; 1028 } clear_buffers;
1029 INSERT_PADDING_WORDS(0xB); 1029 INSERT_UNION_PADDING_WORDS(0xB);
1030 std::array<ColorMask, NumRenderTargets> color_mask; 1030 std::array<ColorMask, NumRenderTargets> color_mask;
1031 INSERT_PADDING_WORDS(0x38); 1031 INSERT_UNION_PADDING_WORDS(0x38);
1032 1032
1033 struct { 1033 struct {
1034 u32 query_address_high; 1034 u32 query_address_high;
@@ -1050,7 +1050,7 @@ public:
1050 } 1050 }
1051 } query; 1051 } query;
1052 1052
1053 INSERT_PADDING_WORDS(0x3C); 1053 INSERT_UNION_PADDING_WORDS(0x3C);
1054 1054
1055 struct { 1055 struct {
1056 union { 1056 union {
@@ -1090,10 +1090,10 @@ public:
1090 BitField<4, 4, ShaderProgram> program; 1090 BitField<4, 4, ShaderProgram> program;
1091 }; 1091 };
1092 u32 offset; 1092 u32 offset;
1093 INSERT_PADDING_WORDS(14); 1093 INSERT_UNION_PADDING_WORDS(14);
1094 } shader_config[MaxShaderProgram]; 1094 } shader_config[MaxShaderProgram];
1095 1095
1096 INSERT_PADDING_WORDS(0x60); 1096 INSERT_UNION_PADDING_WORDS(0x60);
1097 1097
1098 u32 firmware[0x20]; 1098 u32 firmware[0x20];
1099 1099
@@ -1110,7 +1110,7 @@ public:
1110 } 1110 }
1111 } const_buffer; 1111 } const_buffer;
1112 1112
1113 INSERT_PADDING_WORDS(0x10); 1113 INSERT_UNION_PADDING_WORDS(0x10);
1114 1114
1115 struct { 1115 struct {
1116 union { 1116 union {
@@ -1118,14 +1118,14 @@ public:
1118 BitField<0, 1, u32> valid; 1118 BitField<0, 1, u32> valid;
1119 BitField<4, 5, u32> index; 1119 BitField<4, 5, u32> index;
1120 }; 1120 };
1121 INSERT_PADDING_WORDS(7); 1121 INSERT_UNION_PADDING_WORDS(7);
1122 } cb_bind[MaxShaderStage]; 1122 } cb_bind[MaxShaderStage];
1123 1123
1124 INSERT_PADDING_WORDS(0x56); 1124 INSERT_UNION_PADDING_WORDS(0x56);
1125 1125
1126 u32 tex_cb_index; 1126 u32 tex_cb_index;
1127 1127
1128 INSERT_PADDING_WORDS(0x395); 1128 INSERT_UNION_PADDING_WORDS(0x395);
1129 1129
1130 struct { 1130 struct {
1131 /// Compressed address of a buffer that holds information about bound SSBOs. 1131 /// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1137,14 +1137,14 @@ public:
1137 } 1137 }
1138 } ssbo_info; 1138 } ssbo_info;
1139 1139
1140 INSERT_PADDING_WORDS(0x11); 1140 INSERT_UNION_PADDING_WORDS(0x11);
1141 1141
1142 struct { 1142 struct {
1143 u32 address[MaxShaderStage]; 1143 u32 address[MaxShaderStage];
1144 u32 size[MaxShaderStage]; 1144 u32 size[MaxShaderStage];
1145 } tex_info_buffers; 1145 } tex_info_buffers;
1146 1146
1147 INSERT_PADDING_WORDS(0xCC); 1147 INSERT_UNION_PADDING_WORDS(0xCC);
1148 }; 1148 };
1149 std::array<u32, NUM_REGS> reg_array; 1149 std::array<u32, NUM_REGS> reg_array;
1150 }; 1150 };
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:
94 94
95 union { 95 union {
96 struct { 96 struct {
97 INSERT_PADDING_WORDS(0xC0); 97 INSERT_UNION_PADDING_WORDS(0xC0);
98 98
99 struct { 99 struct {
100 union { 100 union {
@@ -112,7 +112,7 @@ public:
112 }; 112 };
113 } exec; 113 } exec;
114 114
115 INSERT_PADDING_WORDS(0x3F); 115 INSERT_UNION_PADDING_WORDS(0x3F);
116 116
117 struct { 117 struct {
118 u32 address_high; 118 u32 address_high;
@@ -139,7 +139,7 @@ public:
139 u32 x_count; 139 u32 x_count;
140 u32 y_count; 140 u32 y_count;
141 141
142 INSERT_PADDING_WORDS(0xB8); 142 INSERT_UNION_PADDING_WORDS(0xB8);
143 143
144 u32 const0; 144 u32 const0;
145 u32 const1; 145 u32 const1;
@@ -162,11 +162,11 @@ public:
162 162
163 Parameters dst_params; 163 Parameters dst_params;
164 164
165 INSERT_PADDING_WORDS(1); 165 INSERT_UNION_PADDING_WORDS(1);
166 166
167 Parameters src_params; 167 Parameters src_params;
168 168
169 INSERT_PADDING_WORDS(0x13); 169 INSERT_UNION_PADDING_WORDS(0x13);
170 }; 170 };
171 std::array<u32, NUM_REGS> reg_array; 171 std::array<u32, NUM_REGS> reg_array;
172 }; 172 };
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d3d05a866..8f6bc76eb 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1238,6 +1238,32 @@ union Instruction {
1238 } tld4; 1238 } tld4;
1239 1239
1240 union { 1240 union {
1241 BitField<35, 1, u64> ndv_flag;
1242 BitField<49, 1, u64> nodep_flag;
1243 BitField<50, 1, u64> dc_flag;
1244 BitField<33, 2, u64> info;
1245 BitField<37, 2, u64> component;
1246
1247 bool UsesMiscMode(TextureMiscMode mode) const {
1248 switch (mode) {
1249 case TextureMiscMode::NDV:
1250 return ndv_flag != 0;
1251 case TextureMiscMode::NODEP:
1252 return nodep_flag != 0;
1253 case TextureMiscMode::DC:
1254 return dc_flag != 0;
1255 case TextureMiscMode::AOFFI:
1256 return info == 1;
1257 case TextureMiscMode::PTP:
1258 return info == 2;
1259 default:
1260 break;
1261 }
1262 return false;
1263 }
1264 } tld4_b;
1265
1266 union {
1241 BitField<49, 1, u64> nodep_flag; 1267 BitField<49, 1, u64> nodep_flag;
1242 BitField<50, 1, u64> dc_flag; 1268 BitField<50, 1, u64> dc_flag;
1243 BitField<51, 1, u64> aoffi_flag; 1269 BitField<51, 1, u64> aoffi_flag;
@@ -1590,7 +1616,8 @@ public:
1590 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations 1616 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
1591 TLD, // Texture Load 1617 TLD, // Texture Load
1592 TLDS, // Texture Load with scalar/non-vec4 source/destinations 1618 TLDS, // Texture Load with scalar/non-vec4 source/destinations
1593 TLD4, // Texture Load 4 1619 TLD4, // Texture Gather 4
1620 TLD4_B, // Texture Gather 4 Bindless
1594 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations 1621 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
1595 TMML_B, // Texture Mip Map Level 1622 TMML_B, // Texture Mip Map Level
1596 TMML, // Texture Mip Map Level 1623 TMML, // Texture Mip Map Level
@@ -1881,6 +1908,7 @@ private:
1881 INST("11011100--11----", Id::TLD, Type::Texture, "TLD"), 1908 INST("11011100--11----", Id::TLD, Type::Texture, "TLD"),
1882 INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"), 1909 INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"),
1883 INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"), 1910 INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"),
1911 INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"),
1884 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), 1912 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
1885 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), 1913 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
1886 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), 1914 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
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 {
38 BitField<26, 1, u32> does_load_or_store; 38 BitField<26, 1, u32> does_load_or_store;
39 BitField<27, 1, u32> does_fp64; 39 BitField<27, 1, u32> does_fp64;
40 BitField<28, 4, u32> stream_out_mask; 40 BitField<28, 4, u32> stream_out_mask;
41 } common0; 41 } common0{};
42 42
43 union { 43 union {
44 BitField<0, 24, u32> shader_local_memory_low_size; 44 BitField<0, 24, u32> shader_local_memory_low_size;
45 BitField<24, 8, u32> per_patch_attribute_count; 45 BitField<24, 8, u32> per_patch_attribute_count;
46 } common1; 46 } common1{};
47 47
48 union { 48 union {
49 BitField<0, 24, u32> shader_local_memory_high_size; 49 BitField<0, 24, u32> shader_local_memory_high_size;
50 BitField<24, 8, u32> threads_per_input_primitive; 50 BitField<24, 8, u32> threads_per_input_primitive;
51 } common2; 51 } common2{};
52 52
53 union { 53 union {
54 BitField<0, 24, u32> shader_local_memory_crs_size; 54 BitField<0, 24, u32> shader_local_memory_crs_size;
55 BitField<24, 4, OutputTopology> output_topology; 55 BitField<24, 4, OutputTopology> output_topology;
56 BitField<28, 4, u32> reserved; 56 BitField<28, 4, u32> reserved;
57 } common3; 57 } common3{};
58 58
59 union { 59 union {
60 BitField<0, 12, u32> max_output_vertices; 60 BitField<0, 12, u32> max_output_vertices;
61 BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders. 61 BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
62 BitField<24, 4, u32> reserved; 62 BitField<24, 4, u32> reserved;
63 BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders. 63 BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
64 } common4; 64 } common4{};
65 65
66 union { 66 union {
67 struct { 67 struct {
68 INSERT_PADDING_BYTES(3); // ImapSystemValuesA 68 INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
69 INSERT_PADDING_BYTES(1); // ImapSystemValuesB 69 INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
70 INSERT_PADDING_BYTES(16); // ImapGenericVector[32] 70 INSERT_UNION_PADDING_BYTES(16); // ImapGenericVector[32]
71 INSERT_PADDING_BYTES(2); // ImapColor 71 INSERT_UNION_PADDING_BYTES(2); // ImapColor
72 union { 72 union {
73 BitField<0, 8, u16> clip_distances; 73 BitField<0, 8, u16> clip_distances;
74 BitField<8, 1, u16> point_sprite_s; 74 BitField<8, 1, u16> point_sprite_s;
@@ -79,20 +79,20 @@ struct Header {
79 BitField<14, 1, u16> instance_id; 79 BitField<14, 1, u16> instance_id;
80 BitField<15, 1, u16> vertex_id; 80 BitField<15, 1, u16> vertex_id;
81 }; 81 };
82 INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10] 82 INSERT_UNION_PADDING_BYTES(5); // ImapFixedFncTexture[10]
83 INSERT_PADDING_BYTES(1); // ImapReserved 83 INSERT_UNION_PADDING_BYTES(1); // ImapReserved
84 INSERT_PADDING_BYTES(3); // OmapSystemValuesA 84 INSERT_UNION_PADDING_BYTES(3); // OmapSystemValuesA
85 INSERT_PADDING_BYTES(1); // OmapSystemValuesB 85 INSERT_UNION_PADDING_BYTES(1); // OmapSystemValuesB
86 INSERT_PADDING_BYTES(16); // OmapGenericVector[32] 86 INSERT_UNION_PADDING_BYTES(16); // OmapGenericVector[32]
87 INSERT_PADDING_BYTES(2); // OmapColor 87 INSERT_UNION_PADDING_BYTES(2); // OmapColor
88 INSERT_PADDING_BYTES(2); // OmapSystemValuesC 88 INSERT_UNION_PADDING_BYTES(2); // OmapSystemValuesC
89 INSERT_PADDING_BYTES(5); // OmapFixedFncTexture[10] 89 INSERT_UNION_PADDING_BYTES(5); // OmapFixedFncTexture[10]
90 INSERT_PADDING_BYTES(1); // OmapReserved 90 INSERT_UNION_PADDING_BYTES(1); // OmapReserved
91 } vtg; 91 } vtg;
92 92
93 struct { 93 struct {
94 INSERT_PADDING_BYTES(3); // ImapSystemValuesA 94 INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
95 INSERT_PADDING_BYTES(1); // ImapSystemValuesB 95 INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
96 union { 96 union {
97 BitField<0, 2, AttributeUse> x; 97 BitField<0, 2, AttributeUse> x;
98 BitField<2, 2, AttributeUse> y; 98 BitField<2, 2, AttributeUse> y;
@@ -100,10 +100,10 @@ struct Header {
100 BitField<6, 2, AttributeUse> z; 100 BitField<6, 2, AttributeUse> z;
101 u8 raw; 101 u8 raw;
102 } imap_generic_vector[32]; 102 } imap_generic_vector[32];
103 INSERT_PADDING_BYTES(2); // ImapColor 103 INSERT_UNION_PADDING_BYTES(2); // ImapColor
104 INSERT_PADDING_BYTES(2); // ImapSystemValuesC 104 INSERT_UNION_PADDING_BYTES(2); // ImapSystemValuesC
105 INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10] 105 INSERT_UNION_PADDING_BYTES(10); // ImapFixedFncTexture[10]
106 INSERT_PADDING_BYTES(2); // ImapReserved 106 INSERT_UNION_PADDING_BYTES(2); // ImapReserved
107 struct { 107 struct {
108 u32 target; 108 u32 target;
109 union { 109 union {
@@ -139,6 +139,8 @@ struct Header {
139 return result; 139 return result;
140 } 140 }
141 } ps; 141 } ps;
142
143 std::array<u32, 0xF> raw{};
142 }; 144 };
143 145
144 u64 GetLocalMemorySize() const { 146 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:
207 207
208 union { 208 union {
209 struct { 209 struct {
210 INSERT_PADDING_WORDS(0x4); 210 INSERT_UNION_PADDING_WORDS(0x4);
211 struct { 211 struct {
212 u32 address_high; 212 u32 address_high;
213 u32 address_low; 213 u32 address_low;
@@ -220,12 +220,12 @@ public:
220 220
221 u32 semaphore_sequence; 221 u32 semaphore_sequence;
222 u32 semaphore_trigger; 222 u32 semaphore_trigger;
223 INSERT_PADDING_WORDS(0xC); 223 INSERT_UNION_PADDING_WORDS(0xC);
224 224
225 // The puser and the puller share the reference counter, the pusher only has read 225 // The puser and the puller share the reference counter, the pusher only has read
226 // access 226 // access
227 u32 reference_count; 227 u32 reference_count;
228 INSERT_PADDING_WORDS(0x5); 228 INSERT_UNION_PADDING_WORDS(0x5);
229 229
230 u32 semaphore_acquire; 230 u32 semaphore_acquire;
231 u32 semaphore_release; 231 u32 semaphore_release;
@@ -234,7 +234,7 @@ public:
234 BitField<4, 4, u32> operation; 234 BitField<4, 4, u32> operation;
235 BitField<8, 8, u32> id; 235 BitField<8, 8, u32> id;
236 } fence_action; 236 } fence_action;
237 INSERT_PADDING_WORDS(0xE2); 237 INSERT_UNION_PADDING_WORDS(0xE2);
238 238
239 // Puller state 239 // Puller state
240 u32 acquire_mode; 240 u32 acquire_mode;
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
new file mode 100644
index 000000000..b230dcc18
--- /dev/null
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -0,0 +1,63 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <mutex>
6
7#include <boost/icl/interval_map.hpp>
8
9#include "common/assert.h"
10#include "common/common_types.h"
11#include "core/memory.h"
12#include "video_core/rasterizer_accelerated.h"
13
14namespace VideoCore {
15
16namespace {
17
18template <typename Map, typename Interval>
19constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
20 return boost::make_iterator_range(map.equal_range(interval));
21}
22
23} // Anonymous namespace
24
25RasterizerAccelerated::RasterizerAccelerated() = default;
26
27RasterizerAccelerated::~RasterizerAccelerated() = default;
28
29void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
30 std::lock_guard lock{pages_mutex};
31 const u64 page_start{addr >> Memory::PAGE_BITS};
32 const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
33
34 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
35 // subtract after iterating
36 const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
37 if (delta > 0) {
38 cached_pages.add({pages_interval, delta});
39 }
40
41 for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
42 const auto interval = pair.first & pages_interval;
43 const int count = pair.second;
44
45 const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
46 const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
47 const u64 interval_size = interval_end_addr - interval_start_addr;
48
49 if (delta > 0 && count == delta) {
50 Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
51 } else if (delta < 0 && count == -delta) {
52 Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
53 } else {
54 ASSERT(count >= 0);
55 }
56 }
57
58 if (delta < 0) {
59 cached_pages.add({pages_interval, delta});
60 }
61}
62
63} // namespace VideoCore
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
new file mode 100644
index 000000000..8f7e3547e
--- /dev/null
+++ b/src/video_core/rasterizer_accelerated.h
@@ -0,0 +1,31 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <mutex>
8
9#include <boost/icl/interval_map.hpp>
10
11#include "common/common_types.h"
12#include "video_core/rasterizer_interface.h"
13
14namespace VideoCore {
15
16/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
17class RasterizerAccelerated : public RasterizerInterface {
18public:
19 explicit RasterizerAccelerated();
20 ~RasterizerAccelerated() override;
21
22 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
23
24private:
25 using CachedPageMap = boost::icl::interval_map<u64, int>;
26 CachedPageMap cached_pages;
27
28 std::mutex pages_mutex;
29};
30
31} // namespace VideoCore
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 35fc094a8..d1e147db8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -68,8 +68,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
68 ScreenInfo& info) 68 ScreenInfo& info)
69 : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device}, 69 : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device},
70 system{system}, screen_info{info}, buffer_cache{*this, system, STREAM_BUFFER_SIZE} { 70 system{system}, screen_info{info}, buffer_cache{*this, system, STREAM_BUFFER_SIZE} {
71 OpenGLState::ApplyDefaultState();
72
73 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 71 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
74 state.draw.shader_program = 0; 72 state.draw.shader_program = 0;
75 state.Apply(); 73 state.Apply();
@@ -342,42 +340,6 @@ std::size_t RasterizerOpenGL::CalculateIndexBufferSize() const {
342 static_cast<std::size_t>(regs.index_array.FormatSizeInBytes()); 340 static_cast<std::size_t>(regs.index_array.FormatSizeInBytes());
343} 341}
344 342
345template <typename Map, typename Interval>
346static constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
347 return boost::make_iterator_range(map.equal_range(interval));
348}
349
350void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
351 std::lock_guard lock{pages_mutex};
352 const u64 page_start{addr >> Memory::PAGE_BITS};
353 const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
354
355 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
356 // subtract after iterating
357 const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
358 if (delta > 0)
359 cached_pages.add({pages_interval, delta});
360
361 for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
362 const auto interval = pair.first & pages_interval;
363 const int count = pair.second;
364
365 const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
366 const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
367 const u64 interval_size = interval_end_addr - interval_start_addr;
368
369 if (delta > 0 && count == delta)
370 Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
371 else if (delta < 0 && count == -delta)
372 Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
373 else
374 ASSERT(count >= 0);
375 }
376
377 if (delta < 0)
378 cached_pages.add({pages_interval, delta});
379}
380
381void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, 343void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
382 const VideoCore::DiskResourceLoadCallback& callback) { 344 const VideoCore::DiskResourceLoadCallback& callback) {
383 shader_cache.LoadDiskCache(stop_loading, callback); 345 shader_cache.LoadDiskCache(stop_loading, callback);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index c24a02d71..bd6fe5c3a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -9,17 +9,16 @@
9#include <cstddef> 9#include <cstddef>
10#include <map> 10#include <map>
11#include <memory> 11#include <memory>
12#include <mutex>
13#include <optional> 12#include <optional>
14#include <tuple> 13#include <tuple>
15#include <utility> 14#include <utility>
16 15
17#include <boost/icl/interval_map.hpp>
18#include <glad/glad.h> 16#include <glad/glad.h>
19 17
20#include "common/common_types.h" 18#include "common/common_types.h"
21#include "video_core/engines/const_buffer_info.h" 19#include "video_core/engines/const_buffer_info.h"
22#include "video_core/engines/maxwell_3d.h" 20#include "video_core/engines/maxwell_3d.h"
21#include "video_core/rasterizer_accelerated.h"
23#include "video_core/rasterizer_cache.h" 22#include "video_core/rasterizer_cache.h"
24#include "video_core/rasterizer_interface.h" 23#include "video_core/rasterizer_interface.h"
25#include "video_core/renderer_opengl/gl_buffer_cache.h" 24#include "video_core/renderer_opengl/gl_buffer_cache.h"
@@ -52,7 +51,7 @@ namespace OpenGL {
52struct ScreenInfo; 51struct ScreenInfo;
53struct DrawParameters; 52struct DrawParameters;
54 53
55class RasterizerOpenGL : public VideoCore::RasterizerInterface { 54class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
56public: 55public:
57 explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 56 explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
58 ScreenInfo& info); 57 ScreenInfo& info);
@@ -73,7 +72,6 @@ public:
73 const Tegra::Engines::Fermi2D::Config& copy_config) override; 72 const Tegra::Engines::Fermi2D::Config& copy_config) override;
74 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 73 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
75 u32 pixel_stride) override; 74 u32 pixel_stride) override;
76 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
77 void LoadDiskResources(const std::atomic_bool& stop_loading, 75 void LoadDiskResources(const std::atomic_bool& stop_loading,
78 const VideoCore::DiskResourceLoadCallback& callback) override; 76 const VideoCore::DiskResourceLoadCallback& callback) override;
79 77
@@ -228,11 +226,6 @@ private:
228 AccelDraw accelerate_draw = AccelDraw::Disabled; 226 AccelDraw accelerate_draw = AccelDraw::Disabled;
229 227
230 OGLFramebuffer clear_framebuffer; 228 OGLFramebuffer clear_framebuffer;
231
232 using CachedPageMap = boost::icl::interval_map<u64, int>;
233 CachedPageMap cached_pages;
234
235 std::mutex pages_mutex;
236}; 229};
237 230
238} // namespace OpenGL 231} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index bf86b5a0b..f25148362 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
5#include <iterator> 6#include <iterator>
6#include <glad/glad.h> 7#include <glad/glad.h>
7#include "common/assert.h" 8#include "common/assert.h"
@@ -69,147 +70,29 @@ void Enable(GLenum cap, GLuint index, bool enable) {
69} 70}
70 71
71void Enable(GLenum cap, bool& current_value, bool new_value) { 72void Enable(GLenum cap, bool& current_value, bool new_value) {
72 if (UpdateValue(current_value, new_value)) 73 if (UpdateValue(current_value, new_value)) {
73 Enable(cap, new_value); 74 Enable(cap, new_value);
75 }
74} 76}
75 77
76void Enable(GLenum cap, GLuint index, bool& current_value, bool new_value) { 78void Enable(GLenum cap, GLuint index, bool& current_value, bool new_value) {
77 if (UpdateValue(current_value, new_value)) 79 if (UpdateValue(current_value, new_value)) {
78 Enable(cap, index, new_value); 80 Enable(cap, index, new_value);
79}
80
81} // namespace
82
83OpenGLState::OpenGLState() {
84 // These all match default OpenGL values
85 framebuffer_srgb.enabled = false;
86
87 multisample_control.alpha_to_coverage = false;
88 multisample_control.alpha_to_one = false;
89
90 cull.enabled = false;
91 cull.mode = GL_BACK;
92 cull.front_face = GL_CCW;
93
94 depth.test_enabled = false;
95 depth.test_func = GL_LESS;
96 depth.write_mask = GL_TRUE;
97
98 primitive_restart.enabled = false;
99 primitive_restart.index = 0;
100
101 for (auto& item : color_mask) {
102 item.red_enabled = GL_TRUE;
103 item.green_enabled = GL_TRUE;
104 item.blue_enabled = GL_TRUE;
105 item.alpha_enabled = GL_TRUE;
106 } 81 }
82}
107 83
108 const auto ResetStencil = [](auto& config) { 84} // Anonymous namespace
109 config.test_func = GL_ALWAYS;
110 config.test_ref = 0;
111 config.test_mask = 0xFFFFFFFF;
112 config.write_mask = 0xFFFFFFFF;
113 config.action_depth_fail = GL_KEEP;
114 config.action_depth_pass = GL_KEEP;
115 config.action_stencil_fail = GL_KEEP;
116 };
117 stencil.test_enabled = false;
118 ResetStencil(stencil.front);
119 ResetStencil(stencil.back);
120
121 for (auto& item : viewports) {
122 item.x = 0;
123 item.y = 0;
124 item.width = 0;
125 item.height = 0;
126 item.depth_range_near = 0.0f;
127 item.depth_range_far = 1.0f;
128 item.scissor.enabled = false;
129 item.scissor.x = 0;
130 item.scissor.y = 0;
131 item.scissor.width = 0;
132 item.scissor.height = 0;
133 }
134
135 for (auto& item : blend) {
136 item.enabled = true;
137 item.rgb_equation = GL_FUNC_ADD;
138 item.a_equation = GL_FUNC_ADD;
139 item.src_rgb_func = GL_ONE;
140 item.dst_rgb_func = GL_ZERO;
141 item.src_a_func = GL_ONE;
142 item.dst_a_func = GL_ZERO;
143 }
144
145 independant_blend.enabled = false;
146
147 blend_color.red = 0.0f;
148 blend_color.green = 0.0f;
149 blend_color.blue = 0.0f;
150 blend_color.alpha = 0.0f;
151
152 logic_op.enabled = false;
153 logic_op.operation = GL_COPY;
154
155 draw.read_framebuffer = 0;
156 draw.draw_framebuffer = 0;
157 draw.vertex_array = 0;
158 draw.shader_program = 0;
159 draw.program_pipeline = 0;
160
161 clip_distance = {};
162
163 point.size = 1;
164
165 fragment_color_clamp.enabled = false;
166
167 depth_clamp.far_plane = false;
168 depth_clamp.near_plane = false;
169
170 polygon_offset.fill_enable = false;
171 polygon_offset.line_enable = false;
172 polygon_offset.point_enable = false;
173 polygon_offset.factor = 0.0f;
174 polygon_offset.units = 0.0f;
175 polygon_offset.clamp = 0.0f;
176 85
177 alpha_test.enabled = false; 86OpenGLState::OpenGLState() = default;
178 alpha_test.func = GL_ALWAYS;
179 alpha_test.ref = 0.0f;
180}
181 87
182void OpenGLState::SetDefaultViewports() { 88void OpenGLState::SetDefaultViewports() {
183 for (auto& item : viewports) { 89 viewports.fill(Viewport{});
184 item.x = 0;
185 item.y = 0;
186 item.width = 0;
187 item.height = 0;
188 item.depth_range_near = 0.0f;
189 item.depth_range_far = 1.0f;
190 item.scissor.enabled = false;
191 item.scissor.x = 0;
192 item.scissor.y = 0;
193 item.scissor.width = 0;
194 item.scissor.height = 0;
195 }
196 90
197 depth_clamp.far_plane = false; 91 depth_clamp.far_plane = false;
198 depth_clamp.near_plane = false; 92 depth_clamp.near_plane = false;
199} 93}
200 94
201void OpenGLState::ApplyDefaultState() { 95void OpenGLState::ApplyFramebufferState() {
202 glEnable(GL_BLEND);
203 glDisable(GL_FRAMEBUFFER_SRGB);
204 glDisable(GL_CULL_FACE);
205 glDisable(GL_DEPTH_TEST);
206 glDisable(GL_PRIMITIVE_RESTART);
207 glDisable(GL_STENCIL_TEST);
208 glDisable(GL_COLOR_LOGIC_OP);
209 glDisable(GL_SCISSOR_TEST);
210}
211
212void OpenGLState::ApplyFramebufferState() const {
213 if (UpdateValue(cur_state.draw.read_framebuffer, draw.read_framebuffer)) { 96 if (UpdateValue(cur_state.draw.read_framebuffer, draw.read_framebuffer)) {
214 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); 97 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
215 } 98 }
@@ -218,52 +101,52 @@ void OpenGLState::ApplyFramebufferState() const {
218 } 101 }
219} 102}
220 103
221void OpenGLState::ApplyVertexArrayState() const { 104void OpenGLState::ApplyVertexArrayState() {
222 if (UpdateValue(cur_state.draw.vertex_array, draw.vertex_array)) { 105 if (UpdateValue(cur_state.draw.vertex_array, draw.vertex_array)) {
223 glBindVertexArray(draw.vertex_array); 106 glBindVertexArray(draw.vertex_array);
224 } 107 }
225} 108}
226 109
227void OpenGLState::ApplyShaderProgram() const { 110void OpenGLState::ApplyShaderProgram() {
228 if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) { 111 if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) {
229 glUseProgram(draw.shader_program); 112 glUseProgram(draw.shader_program);
230 } 113 }
231} 114}
232 115
233void OpenGLState::ApplyProgramPipeline() const { 116void OpenGLState::ApplyProgramPipeline() {
234 if (UpdateValue(cur_state.draw.program_pipeline, draw.program_pipeline)) { 117 if (UpdateValue(cur_state.draw.program_pipeline, draw.program_pipeline)) {
235 glBindProgramPipeline(draw.program_pipeline); 118 glBindProgramPipeline(draw.program_pipeline);
236 } 119 }
237} 120}
238 121
239void OpenGLState::ApplyClipDistances() const { 122void OpenGLState::ApplyClipDistances() {
240 for (std::size_t i = 0; i < clip_distance.size(); ++i) { 123 for (std::size_t i = 0; i < clip_distance.size(); ++i) {
241 Enable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i), cur_state.clip_distance[i], 124 Enable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i), cur_state.clip_distance[i],
242 clip_distance[i]); 125 clip_distance[i]);
243 } 126 }
244} 127}
245 128
246void OpenGLState::ApplyPointSize() const { 129void OpenGLState::ApplyPointSize() {
247 if (UpdateValue(cur_state.point.size, point.size)) { 130 if (UpdateValue(cur_state.point.size, point.size)) {
248 glPointSize(point.size); 131 glPointSize(point.size);
249 } 132 }
250} 133}
251 134
252void OpenGLState::ApplyFragmentColorClamp() const { 135void OpenGLState::ApplyFragmentColorClamp() {
253 if (UpdateValue(cur_state.fragment_color_clamp.enabled, fragment_color_clamp.enabled)) { 136 if (UpdateValue(cur_state.fragment_color_clamp.enabled, fragment_color_clamp.enabled)) {
254 glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, 137 glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
255 fragment_color_clamp.enabled ? GL_TRUE : GL_FALSE); 138 fragment_color_clamp.enabled ? GL_TRUE : GL_FALSE);
256 } 139 }
257} 140}
258 141
259void OpenGLState::ApplyMultisample() const { 142void OpenGLState::ApplyMultisample() {
260 Enable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur_state.multisample_control.alpha_to_coverage, 143 Enable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur_state.multisample_control.alpha_to_coverage,
261 multisample_control.alpha_to_coverage); 144 multisample_control.alpha_to_coverage);
262 Enable(GL_SAMPLE_ALPHA_TO_ONE, cur_state.multisample_control.alpha_to_one, 145 Enable(GL_SAMPLE_ALPHA_TO_ONE, cur_state.multisample_control.alpha_to_one,
263 multisample_control.alpha_to_one); 146 multisample_control.alpha_to_one);
264} 147}
265 148
266void OpenGLState::ApplyDepthClamp() const { 149void OpenGLState::ApplyDepthClamp() {
267 if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane && 150 if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
268 depth_clamp.near_plane == cur_state.depth_clamp.near_plane) { 151 depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
269 return; 152 return;
@@ -276,7 +159,7 @@ void OpenGLState::ApplyDepthClamp() const {
276 Enable(GL_DEPTH_CLAMP, depth_clamp.far_plane || depth_clamp.near_plane); 159 Enable(GL_DEPTH_CLAMP, depth_clamp.far_plane || depth_clamp.near_plane);
277} 160}
278 161
279void OpenGLState::ApplySRgb() const { 162void OpenGLState::ApplySRgb() {
280 if (cur_state.framebuffer_srgb.enabled == framebuffer_srgb.enabled) 163 if (cur_state.framebuffer_srgb.enabled == framebuffer_srgb.enabled)
281 return; 164 return;
282 cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled; 165 cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled;
@@ -287,7 +170,7 @@ void OpenGLState::ApplySRgb() const {
287 } 170 }
288} 171}
289 172
290void OpenGLState::ApplyCulling() const { 173void OpenGLState::ApplyCulling() {
291 Enable(GL_CULL_FACE, cur_state.cull.enabled, cull.enabled); 174 Enable(GL_CULL_FACE, cur_state.cull.enabled, cull.enabled);
292 175
293 if (UpdateValue(cur_state.cull.mode, cull.mode)) { 176 if (UpdateValue(cur_state.cull.mode, cull.mode)) {
@@ -299,7 +182,12 @@ void OpenGLState::ApplyCulling() const {
299 } 182 }
300} 183}
301 184
302void OpenGLState::ApplyColorMask() const { 185void OpenGLState::ApplyColorMask() {
186 if (!dirty.color_mask) {
187 return;
188 }
189 dirty.color_mask = false;
190
303 for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) { 191 for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
304 const auto& updated = color_mask[i]; 192 const auto& updated = color_mask[i];
305 auto& current = cur_state.color_mask[i]; 193 auto& current = cur_state.color_mask[i];
@@ -314,7 +202,7 @@ void OpenGLState::ApplyColorMask() const {
314 } 202 }
315} 203}
316 204
317void OpenGLState::ApplyDepth() const { 205void OpenGLState::ApplyDepth() {
318 Enable(GL_DEPTH_TEST, cur_state.depth.test_enabled, depth.test_enabled); 206 Enable(GL_DEPTH_TEST, cur_state.depth.test_enabled, depth.test_enabled);
319 207
320 if (cur_state.depth.test_func != depth.test_func) { 208 if (cur_state.depth.test_func != depth.test_func) {
@@ -328,7 +216,7 @@ void OpenGLState::ApplyDepth() const {
328 } 216 }
329} 217}
330 218
331void OpenGLState::ApplyPrimitiveRestart() const { 219void OpenGLState::ApplyPrimitiveRestart() {
332 Enable(GL_PRIMITIVE_RESTART, cur_state.primitive_restart.enabled, primitive_restart.enabled); 220 Enable(GL_PRIMITIVE_RESTART, cur_state.primitive_restart.enabled, primitive_restart.enabled);
333 221
334 if (cur_state.primitive_restart.index != primitive_restart.index) { 222 if (cur_state.primitive_restart.index != primitive_restart.index) {
@@ -337,7 +225,12 @@ void OpenGLState::ApplyPrimitiveRestart() const {
337 } 225 }
338} 226}
339 227
340void OpenGLState::ApplyStencilTest() const { 228void OpenGLState::ApplyStencilTest() {
229 if (!dirty.stencil_state) {
230 return;
231 }
232 dirty.stencil_state = false;
233
341 Enable(GL_STENCIL_TEST, cur_state.stencil.test_enabled, stencil.test_enabled); 234 Enable(GL_STENCIL_TEST, cur_state.stencil.test_enabled, stencil.test_enabled);
342 235
343 const auto ConfigStencil = [](GLenum face, const auto& config, auto& current) { 236 const auto ConfigStencil = [](GLenum face, const auto& config, auto& current) {
@@ -366,7 +259,7 @@ void OpenGLState::ApplyStencilTest() const {
366 ConfigStencil(GL_BACK, stencil.back, cur_state.stencil.back); 259 ConfigStencil(GL_BACK, stencil.back, cur_state.stencil.back);
367} 260}
368 261
369void OpenGLState::ApplyViewport() const { 262void OpenGLState::ApplyViewport() {
370 for (GLuint i = 0; i < static_cast<GLuint>(Maxwell::NumViewports); ++i) { 263 for (GLuint i = 0; i < static_cast<GLuint>(Maxwell::NumViewports); ++i) {
371 const auto& updated = viewports[i]; 264 const auto& updated = viewports[i];
372 auto& current = cur_state.viewports[i]; 265 auto& current = cur_state.viewports[i];
@@ -403,7 +296,7 @@ void OpenGLState::ApplyViewport() const {
403 } 296 }
404} 297}
405 298
406void OpenGLState::ApplyGlobalBlending() const { 299void OpenGLState::ApplyGlobalBlending() {
407 const Blend& updated = blend[0]; 300 const Blend& updated = blend[0];
408 Blend& current = cur_state.blend[0]; 301 Blend& current = cur_state.blend[0];
409 302
@@ -427,7 +320,7 @@ void OpenGLState::ApplyGlobalBlending() const {
427 } 320 }
428} 321}
429 322
430void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const { 323void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) {
431 const Blend& updated = blend[target]; 324 const Blend& updated = blend[target];
432 Blend& current = cur_state.blend[target]; 325 Blend& current = cur_state.blend[target];
433 326
@@ -451,7 +344,12 @@ void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
451 } 344 }
452} 345}
453 346
454void OpenGLState::ApplyBlending() const { 347void OpenGLState::ApplyBlending() {
348 if (!dirty.blend_state) {
349 return;
350 }
351 dirty.blend_state = false;
352
455 if (independant_blend.enabled) { 353 if (independant_blend.enabled) {
456 const bool force = independant_blend.enabled != cur_state.independant_blend.enabled; 354 const bool force = independant_blend.enabled != cur_state.independant_blend.enabled;
457 for (std::size_t target = 0; target < Maxwell::NumRenderTargets; ++target) { 355 for (std::size_t target = 0; target < Maxwell::NumRenderTargets; ++target) {
@@ -470,7 +368,7 @@ void OpenGLState::ApplyBlending() const {
470 } 368 }
471} 369}
472 370
473void OpenGLState::ApplyLogicOp() const { 371void OpenGLState::ApplyLogicOp() {
474 Enable(GL_COLOR_LOGIC_OP, cur_state.logic_op.enabled, logic_op.enabled); 372 Enable(GL_COLOR_LOGIC_OP, cur_state.logic_op.enabled, logic_op.enabled);
475 373
476 if (UpdateValue(cur_state.logic_op.operation, logic_op.operation)) { 374 if (UpdateValue(cur_state.logic_op.operation, logic_op.operation)) {
@@ -478,7 +376,12 @@ void OpenGLState::ApplyLogicOp() const {
478 } 376 }
479} 377}
480 378
481void OpenGLState::ApplyPolygonOffset() const { 379void OpenGLState::ApplyPolygonOffset() {
380 if (!dirty.polygon_offset) {
381 return;
382 }
383 dirty.polygon_offset = false;
384
482 Enable(GL_POLYGON_OFFSET_FILL, cur_state.polygon_offset.fill_enable, 385 Enable(GL_POLYGON_OFFSET_FILL, cur_state.polygon_offset.fill_enable,
483 polygon_offset.fill_enable); 386 polygon_offset.fill_enable);
484 Enable(GL_POLYGON_OFFSET_LINE, cur_state.polygon_offset.line_enable, 387 Enable(GL_POLYGON_OFFSET_LINE, cur_state.polygon_offset.line_enable,
@@ -499,7 +402,7 @@ void OpenGLState::ApplyPolygonOffset() const {
499 } 402 }
500} 403}
501 404
502void OpenGLState::ApplyAlphaTest() const { 405void OpenGLState::ApplyAlphaTest() {
503 Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled); 406 Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled);
504 if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref), 407 if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref),
505 std::tie(alpha_test.func, alpha_test.ref))) { 408 std::tie(alpha_test.func, alpha_test.ref))) {
@@ -507,19 +410,19 @@ void OpenGLState::ApplyAlphaTest() const {
507 } 410 }
508} 411}
509 412
510void OpenGLState::ApplyTextures() const { 413void OpenGLState::ApplyTextures() {
511 if (const auto update = UpdateArray(cur_state.textures, textures)) { 414 if (const auto update = UpdateArray(cur_state.textures, textures)) {
512 glBindTextures(update->first, update->second, textures.data() + update->first); 415 glBindTextures(update->first, update->second, textures.data() + update->first);
513 } 416 }
514} 417}
515 418
516void OpenGLState::ApplySamplers() const { 419void OpenGLState::ApplySamplers() {
517 if (const auto update = UpdateArray(cur_state.samplers, samplers)) { 420 if (const auto update = UpdateArray(cur_state.samplers, samplers)) {
518 glBindSamplers(update->first, update->second, samplers.data() + update->first); 421 glBindSamplers(update->first, update->second, samplers.data() + update->first);
519 } 422 }
520} 423}
521 424
522void OpenGLState::ApplyImages() const { 425void OpenGLState::ApplyImages() {
523 if (const auto update = UpdateArray(cur_state.images, images)) { 426 if (const auto update = UpdateArray(cur_state.images, images)) {
524 glBindImageTextures(update->first, update->second, images.data() + update->first); 427 glBindImageTextures(update->first, update->second, images.data() + update->first);
525 } 428 }
@@ -535,32 +438,20 @@ void OpenGLState::Apply() {
535 ApplyPointSize(); 438 ApplyPointSize();
536 ApplyFragmentColorClamp(); 439 ApplyFragmentColorClamp();
537 ApplyMultisample(); 440 ApplyMultisample();
538 if (dirty.color_mask) { 441 ApplyColorMask();
539 ApplyColorMask();
540 dirty.color_mask = false;
541 }
542 ApplyDepthClamp(); 442 ApplyDepthClamp();
543 ApplyViewport(); 443 ApplyViewport();
544 if (dirty.stencil_state) { 444 ApplyStencilTest();
545 ApplyStencilTest();
546 dirty.stencil_state = false;
547 }
548 ApplySRgb(); 445 ApplySRgb();
549 ApplyCulling(); 446 ApplyCulling();
550 ApplyDepth(); 447 ApplyDepth();
551 ApplyPrimitiveRestart(); 448 ApplyPrimitiveRestart();
552 if (dirty.blend_state) { 449 ApplyBlending();
553 ApplyBlending();
554 dirty.blend_state = false;
555 }
556 ApplyLogicOp(); 450 ApplyLogicOp();
557 ApplyTextures(); 451 ApplyTextures();
558 ApplySamplers(); 452 ApplySamplers();
559 ApplyImages(); 453 ApplyImages();
560 if (dirty.polygon_offset) { 454 ApplyPolygonOffset();
561 ApplyPolygonOffset();
562 dirty.polygon_offset = false;
563 }
564 ApplyAlphaTest(); 455 ApplyAlphaTest();
565} 456}
566 457
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index c358d3b38..cca25206b 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -5,168 +5,146 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <type_traits>
8#include <glad/glad.h> 9#include <glad/glad.h>
9#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
10 11
11namespace OpenGL { 12namespace OpenGL {
12 13
13namespace TextureUnits {
14
15struct TextureUnit {
16 GLint id;
17 constexpr GLenum Enum() const {
18 return static_cast<GLenum>(GL_TEXTURE0 + id);
19 }
20};
21
22constexpr TextureUnit MaxwellTexture(int unit) {
23 return TextureUnit{unit};
24}
25
26constexpr TextureUnit LightingLUT{3};
27constexpr TextureUnit FogLUT{4};
28constexpr TextureUnit ProcTexNoiseLUT{5};
29constexpr TextureUnit ProcTexColorMap{6};
30constexpr TextureUnit ProcTexAlphaMap{7};
31constexpr TextureUnit ProcTexLUT{8};
32constexpr TextureUnit ProcTexDiffLUT{9};
33
34} // namespace TextureUnits
35
36class OpenGLState { 14class OpenGLState {
37public: 15public:
38 struct { 16 struct {
39 bool enabled; // GL_FRAMEBUFFER_SRGB 17 bool enabled = false; // GL_FRAMEBUFFER_SRGB
40 } framebuffer_srgb; 18 } framebuffer_srgb;
41 19
42 struct { 20 struct {
43 bool alpha_to_coverage; // GL_ALPHA_TO_COVERAGE 21 bool alpha_to_coverage = false; // GL_ALPHA_TO_COVERAGE
44 bool alpha_to_one; // GL_ALPHA_TO_ONE 22 bool alpha_to_one = false; // GL_ALPHA_TO_ONE
45 } multisample_control; 23 } multisample_control;
46 24
47 struct { 25 struct {
48 bool enabled; // GL_CLAMP_FRAGMENT_COLOR_ARB 26 bool enabled = false; // GL_CLAMP_FRAGMENT_COLOR_ARB
49 } fragment_color_clamp; 27 } fragment_color_clamp;
50 28
51 struct { 29 struct {
52 bool far_plane; 30 bool far_plane = false;
53 bool near_plane; 31 bool near_plane = false;
54 } depth_clamp; // GL_DEPTH_CLAMP 32 } depth_clamp; // GL_DEPTH_CLAMP
55 33
56 struct { 34 struct {
57 bool enabled; // GL_CULL_FACE 35 bool enabled = false; // GL_CULL_FACE
58 GLenum mode; // GL_CULL_FACE_MODE 36 GLenum mode = GL_BACK; // GL_CULL_FACE_MODE
59 GLenum front_face; // GL_FRONT_FACE 37 GLenum front_face = GL_CCW; // GL_FRONT_FACE
60 } cull; 38 } cull;
61 39
62 struct { 40 struct {
63 bool test_enabled; // GL_DEPTH_TEST 41 bool test_enabled = false; // GL_DEPTH_TEST
64 GLenum test_func; // GL_DEPTH_FUNC 42 GLboolean write_mask = GL_TRUE; // GL_DEPTH_WRITEMASK
65 GLboolean write_mask; // GL_DEPTH_WRITEMASK 43 GLenum test_func = GL_LESS; // GL_DEPTH_FUNC
66 } depth; 44 } depth;
67 45
68 struct { 46 struct {
69 bool enabled; 47 bool enabled = false;
70 GLuint index; 48 GLuint index = 0;
71 } primitive_restart; // GL_PRIMITIVE_RESTART 49 } primitive_restart; // GL_PRIMITIVE_RESTART
72 50
73 struct ColorMask { 51 struct ColorMask {
74 GLboolean red_enabled; 52 GLboolean red_enabled = GL_TRUE;
75 GLboolean green_enabled; 53 GLboolean green_enabled = GL_TRUE;
76 GLboolean blue_enabled; 54 GLboolean blue_enabled = GL_TRUE;
77 GLboolean alpha_enabled; 55 GLboolean alpha_enabled = GL_TRUE;
78 }; 56 };
79 std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> 57 std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
80 color_mask; // GL_COLOR_WRITEMASK 58 color_mask; // GL_COLOR_WRITEMASK
81 struct { 59 struct {
82 bool test_enabled; // GL_STENCIL_TEST 60 bool test_enabled = false; // GL_STENCIL_TEST
83 struct { 61 struct {
84 GLenum test_func; // GL_STENCIL_FUNC 62 GLenum test_func = GL_ALWAYS; // GL_STENCIL_FUNC
85 GLint test_ref; // GL_STENCIL_REF 63 GLint test_ref = 0; // GL_STENCIL_REF
86 GLuint test_mask; // GL_STENCIL_VALUE_MASK 64 GLuint test_mask = 0xFFFFFFFF; // GL_STENCIL_VALUE_MASK
87 GLuint write_mask; // GL_STENCIL_WRITEMASK 65 GLuint write_mask = 0xFFFFFFFF; // GL_STENCIL_WRITEMASK
88 GLenum action_stencil_fail; // GL_STENCIL_FAIL 66 GLenum action_stencil_fail = GL_KEEP; // GL_STENCIL_FAIL
89 GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL 67 GLenum action_depth_fail = GL_KEEP; // GL_STENCIL_PASS_DEPTH_FAIL
90 GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS 68 GLenum action_depth_pass = GL_KEEP; // GL_STENCIL_PASS_DEPTH_PASS
91 } front, back; 69 } front, back;
92 } stencil; 70 } stencil;
93 71
94 struct Blend { 72 struct Blend {
95 bool enabled; // GL_BLEND 73 bool enabled = false; // GL_BLEND
96 GLenum rgb_equation; // GL_BLEND_EQUATION_RGB 74 GLenum rgb_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_RGB
97 GLenum a_equation; // GL_BLEND_EQUATION_ALPHA 75 GLenum a_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_ALPHA
98 GLenum src_rgb_func; // GL_BLEND_SRC_RGB 76 GLenum src_rgb_func = GL_ONE; // GL_BLEND_SRC_RGB
99 GLenum dst_rgb_func; // GL_BLEND_DST_RGB 77 GLenum dst_rgb_func = GL_ZERO; // GL_BLEND_DST_RGB
100 GLenum src_a_func; // GL_BLEND_SRC_ALPHA 78 GLenum src_a_func = GL_ONE; // GL_BLEND_SRC_ALPHA
101 GLenum dst_a_func; // GL_BLEND_DST_ALPHA 79 GLenum dst_a_func = GL_ZERO; // GL_BLEND_DST_ALPHA
102 }; 80 };
103 std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend; 81 std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend;
104 82
105 struct { 83 struct {
106 bool enabled; 84 bool enabled = false;
107 } independant_blend; 85 } independant_blend;
108 86
109 struct { 87 struct {
110 GLclampf red; 88 GLclampf red = 0.0f;
111 GLclampf green; 89 GLclampf green = 0.0f;
112 GLclampf blue; 90 GLclampf blue = 0.0f;
113 GLclampf alpha; 91 GLclampf alpha = 0.0f;
114 } blend_color; // GL_BLEND_COLOR 92 } blend_color; // GL_BLEND_COLOR
115 93
116 struct { 94 struct {
117 bool enabled; // GL_LOGIC_OP_MODE 95 bool enabled = false; // GL_LOGIC_OP_MODE
118 GLenum operation; 96 GLenum operation = GL_COPY;
119 } logic_op; 97 } logic_op;
120 98
121 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{}; 99 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures = {};
122 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{}; 100 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers = {};
123 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{}; 101 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images = {};
124 102
125 struct { 103 struct {
126 GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING 104 GLuint read_framebuffer = 0; // GL_READ_FRAMEBUFFER_BINDING
127 GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING 105 GLuint draw_framebuffer = 0; // GL_DRAW_FRAMEBUFFER_BINDING
128 GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING 106 GLuint vertex_array = 0; // GL_VERTEX_ARRAY_BINDING
129 GLuint shader_program; // GL_CURRENT_PROGRAM 107 GLuint shader_program = 0; // GL_CURRENT_PROGRAM
130 GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING 108 GLuint program_pipeline = 0; // GL_PROGRAM_PIPELINE_BINDING
131 } draw; 109 } draw;
132 110
133 struct viewport { 111 struct Viewport {
134 GLint x; 112 GLint x = 0;
135 GLint y; 113 GLint y = 0;
136 GLint width; 114 GLint width = 0;
137 GLint height; 115 GLint height = 0;
138 GLfloat depth_range_near; // GL_DEPTH_RANGE 116 GLfloat depth_range_near = 0.0f; // GL_DEPTH_RANGE
139 GLfloat depth_range_far; // GL_DEPTH_RANGE 117 GLfloat depth_range_far = 1.0f; // GL_DEPTH_RANGE
140 struct { 118 struct {
141 bool enabled; // GL_SCISSOR_TEST 119 bool enabled = false; // GL_SCISSOR_TEST
142 GLint x; 120 GLint x = 0;
143 GLint y; 121 GLint y = 0;
144 GLsizei width; 122 GLsizei width = 0;
145 GLsizei height; 123 GLsizei height = 0;
146 } scissor; 124 } scissor;
147 }; 125 };
148 std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports; 126 std::array<Viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
149 127
150 struct { 128 struct {
151 float size; // GL_POINT_SIZE 129 float size = 1.0f; // GL_POINT_SIZE
152 } point; 130 } point;
153 131
154 struct { 132 struct {
155 bool point_enable; 133 bool point_enable = false;
156 bool line_enable; 134 bool line_enable = false;
157 bool fill_enable; 135 bool fill_enable = false;
158 GLfloat units; 136 GLfloat units = 0.0f;
159 GLfloat factor; 137 GLfloat factor = 0.0f;
160 GLfloat clamp; 138 GLfloat clamp = 0.0f;
161 } polygon_offset; 139 } polygon_offset;
162 140
163 struct { 141 struct {
164 bool enabled; // GL_ALPHA_TEST 142 bool enabled = false; // GL_ALPHA_TEST
165 GLenum func; // GL_ALPHA_TEST_FUNC 143 GLenum func = GL_ALWAYS; // GL_ALPHA_TEST_FUNC
166 GLfloat ref; // GL_ALPHA_TEST_REF 144 GLfloat ref = 0.0f; // GL_ALPHA_TEST_REF
167 } alpha_test; 145 } alpha_test;
168 146
169 std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE 147 std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE
170 148
171 OpenGLState(); 149 OpenGLState();
172 150
@@ -179,34 +157,31 @@ public:
179 /// Apply this state as the current OpenGL state 157 /// Apply this state as the current OpenGL state
180 void Apply(); 158 void Apply();
181 159
182 void ApplyFramebufferState() const; 160 void ApplyFramebufferState();
183 void ApplyVertexArrayState() const; 161 void ApplyVertexArrayState();
184 void ApplyShaderProgram() const; 162 void ApplyShaderProgram();
185 void ApplyProgramPipeline() const; 163 void ApplyProgramPipeline();
186 void ApplyClipDistances() const; 164 void ApplyClipDistances();
187 void ApplyPointSize() const; 165 void ApplyPointSize();
188 void ApplyFragmentColorClamp() const; 166 void ApplyFragmentColorClamp();
189 void ApplyMultisample() const; 167 void ApplyMultisample();
190 void ApplySRgb() const; 168 void ApplySRgb();
191 void ApplyCulling() const; 169 void ApplyCulling();
192 void ApplyColorMask() const; 170 void ApplyColorMask();
193 void ApplyDepth() const; 171 void ApplyDepth();
194 void ApplyPrimitiveRestart() const; 172 void ApplyPrimitiveRestart();
195 void ApplyStencilTest() const; 173 void ApplyStencilTest();
196 void ApplyViewport() const; 174 void ApplyViewport();
197 void ApplyTargetBlending(std::size_t target, bool force) const; 175 void ApplyTargetBlending(std::size_t target, bool force);
198 void ApplyGlobalBlending() const; 176 void ApplyGlobalBlending();
199 void ApplyBlending() const; 177 void ApplyBlending();
200 void ApplyLogicOp() const; 178 void ApplyLogicOp();
201 void ApplyTextures() const; 179 void ApplyTextures();
202 void ApplySamplers() const; 180 void ApplySamplers();
203 void ApplyImages() const; 181 void ApplyImages();
204 void ApplyDepthClamp() const; 182 void ApplyDepthClamp();
205 void ApplyPolygonOffset() const; 183 void ApplyPolygonOffset();
206 void ApplyAlphaTest() const; 184 void ApplyAlphaTest();
207
208 /// Set the initial OpenGL state
209 static void ApplyDefaultState();
210 185
211 /// Resets any references to the given resource 186 /// Resets any references to the given resource
212 OpenGLState& UnbindTexture(GLuint handle); 187 OpenGLState& UnbindTexture(GLuint handle);
@@ -253,5 +228,6 @@ private:
253 bool color_mask; 228 bool color_mask;
254 } dirty{}; 229 } dirty{};
255}; 230};
231static_assert(std::is_trivially_copyable_v<OpenGLState>);
256 232
257} // namespace OpenGL 233} // namespace OpenGL
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 8d3d962c7..ca690b58b 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -96,6 +96,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
96 } 96 }
97 break; 97 break;
98 } 98 }
99 case OpCode::Id::TLD4_B: {
100 is_bindless = true;
101 [[fallthrough]];
102 }
99 case OpCode::Id::TLD4: { 103 case OpCode::Id::TLD4: {
100 ASSERT(instr.tld4.array == 0); 104 ASSERT(instr.tld4.array == 0);
101 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV), 105 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV),
@@ -108,11 +112,14 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
108 } 112 }
109 113
110 const auto texture_type = instr.tld4.texture_type.Value(); 114 const auto texture_type = instr.tld4.texture_type.Value();
111 const bool depth_compare = instr.tld4.UsesMiscMode(TextureMiscMode::DC); 115 const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC)
116 : instr.tld4.UsesMiscMode(TextureMiscMode::DC);
112 const bool is_array = instr.tld4.array != 0; 117 const bool is_array = instr.tld4.array != 0;
113 const bool is_aoffi = instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI); 118 const bool is_aoffi = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::AOFFI)
119 : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
114 WriteTexInstructionFloat( 120 WriteTexInstructionFloat(
115 bb, instr, GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi)); 121 bb, instr,
122 GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless));
116 break; 123 break;
117 } 124 }
118 case OpCode::Id::TLD4S: { 125 case OpCode::Id::TLD4S: {
@@ -586,7 +593,7 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type,
586} 593}
587 594
588Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, 595Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare,
589 bool is_array, bool is_aoffi) { 596 bool is_array, bool is_aoffi, bool is_bindless) {
590 const std::size_t coord_count = GetCoordCount(texture_type); 597 const std::size_t coord_count = GetCoordCount(texture_type);
591 598
592 // If enabled arrays index is always stored in the gpr8 field 599 // If enabled arrays index is always stored in the gpr8 field
@@ -600,6 +607,12 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
600 } 607 }
601 608
602 u64 parameter_register = instr.gpr20.Value(); 609 u64 parameter_register = instr.gpr20.Value();
610
611 const auto& sampler =
612 is_bindless
613 ? GetBindlessSampler(parameter_register++, {{texture_type, is_array, depth_compare}})
614 : GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
615
603 std::vector<Node> aoffi; 616 std::vector<Node> aoffi;
604 if (is_aoffi) { 617 if (is_aoffi) {
605 aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true); 618 aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true);
@@ -610,12 +623,14 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
610 dc = GetRegister(parameter_register++); 623 dc = GetRegister(parameter_register++);
611 } 624 }
612 625
613 const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}}); 626 const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component))
627 : Immediate(static_cast<u32>(instr.tld4.component));
614 628
615 Node4 values; 629 Node4 values;
616 for (u32 element = 0; element < values.size(); ++element) { 630 for (u32 element = 0; element < values.size(); ++element) {
617 auto coords_copy = coords; 631 auto coords_copy = coords;
618 MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, element}; 632 MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component,
633 element};
619 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 634 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
620 } 635 }
621 636
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 5243644e8..26c8fde22 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -341,7 +341,7 @@ private:
341 bool is_array); 341 bool is_array);
342 342
343 Node4 GetTld4Code(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, 343 Node4 GetTld4Code(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type,
344 bool depth_compare, bool is_array, bool is_aoffi); 344 bool depth_compare, bool is_array, bool is_aoffi, bool is_bindless);
345 345
346 Node4 GetTldCode(Tegra::Shader::Instruction instr); 346 Node4 GetTldCode(Tegra::Shader::Instruction instr);
347 347
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() {
1839 return; 1839 return;
1840 } 1840 }
1841 1841
1842 LoadAmiibo(filename);
1843}
1844
1845void GMainWindow::LoadAmiibo(const QString& filename) {
1842 Core::System& system{Core::System::GetInstance()}; 1846 Core::System& system{Core::System::GetInstance()};
1843 Service::SM::ServiceManager& sm = system.ServiceManager(); 1847 Service::SM::ServiceManager& sm = system.ServiceManager();
1844 auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user"); 1848 auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user");
@@ -2189,10 +2193,19 @@ static bool IsSingleFileDropEvent(QDropEvent* event) {
2189} 2193}
2190 2194
2191void GMainWindow::dropEvent(QDropEvent* event) { 2195void GMainWindow::dropEvent(QDropEvent* event) {
2192 if (IsSingleFileDropEvent(event) && ConfirmChangeGame()) { 2196 if (!IsSingleFileDropEvent(event)) {
2193 const QMimeData* mimeData = event->mimeData(); 2197 return;
2194 QString filename = mimeData->urls().at(0).toLocalFile(); 2198 }
2195 BootGame(filename); 2199
2200 const QMimeData* mime_data = event->mimeData();
2201 const QString filename = mime_data->urls().at(0).toLocalFile();
2202
2203 if (emulation_running && QFileInfo(filename).suffix() == QStringLiteral("bin")) {
2204 LoadAmiibo(filename);
2205 } else {
2206 if (ConfirmChangeGame()) {
2207 BootGame(filename);
2208 }
2196 } 2209 }
2197} 2210}
2198 2211
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:
142 142
143 void ShowTelemetryCallout(); 143 void ShowTelemetryCallout();
144 void SetDiscordEnabled(bool state); 144 void SetDiscordEnabled(bool state);
145 void LoadAmiibo(const QString& filename);
145 146
146 void SelectAndSetCurrentUser(); 147 void SelectAndSetCurrentUser();
147 148