mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-04 00:46:25 +00:00
Compare commits
251 Commits
release-3.
...
release-3.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8589a8422 | ||
![]() |
0bdaaf6c76 | ||
![]() |
390197d3aa | ||
![]() |
9fafba49dc | ||
![]() |
5d47efe7fb | ||
![]() |
824234accc | ||
![]() |
6519158ae5 | ||
![]() |
00718d60d2 | ||
![]() |
18c2e179ee | ||
![]() |
21ae008fc2 | ||
![]() |
97a8bb44e6 | ||
![]() |
5d33fce898 | ||
![]() |
bb5df96f69 | ||
![]() |
12b97944f3 | ||
![]() |
0f17fbe1ca | ||
![]() |
c3480ca99c | ||
![]() |
936d94c2ee | ||
![]() |
6cb55ebd46 | ||
![]() |
482c5130eb | ||
![]() |
066bcc5204 | ||
![]() |
21baa27bea | ||
![]() |
93fd4a1c80 | ||
![]() |
7135779599 | ||
![]() |
62c151d044 | ||
![]() |
11d38fc23b | ||
![]() |
d027f0ae6e | ||
![]() |
44290c204e | ||
![]() |
0b69860af6 | ||
![]() |
e7a1ae0ea5 | ||
![]() |
7af36d6c40 | ||
![]() |
d1ae1163dd | ||
![]() |
b2cf5729b4 | ||
![]() |
11b8dd76db | ||
![]() |
56507a6122 | ||
![]() |
8d4324cba2 | ||
![]() |
35408a2126 | ||
![]() |
e5b9dfd181 | ||
![]() |
e8a5d07e5e | ||
![]() |
8c1daf0caf | ||
![]() |
ad2b211f75 | ||
![]() |
414ae344af | ||
![]() |
71af2c020c | ||
![]() |
e755f50072 | ||
![]() |
a0b8275e9c | ||
![]() |
ea362839b1 | ||
![]() |
e7dd5d841b | ||
![]() |
5594d03da0 | ||
![]() |
f2ae66b64f | ||
![]() |
393d99338f | ||
![]() |
4d88280931 | ||
![]() |
e8cc359b5e | ||
![]() |
3b4a198655 | ||
![]() |
03dd1520a3 | ||
![]() |
a6fd74fa3b | ||
![]() |
03b36bac94 | ||
![]() |
a96677bdf6 | ||
![]() |
67f89d0a2b | ||
![]() |
f6de8877ec | ||
![]() |
7c189b1f17 | ||
![]() |
a7947080c0 | ||
![]() |
08c82a3781 | ||
![]() |
589aea50c2 | ||
![]() |
72acd7c9df | ||
![]() |
1a70d1158e | ||
![]() |
ae915c6516 | ||
![]() |
54d573332e | ||
![]() |
0204a69f6b | ||
![]() |
b2689ff76a | ||
![]() |
611940fb80 | ||
![]() |
16c0329a2a | ||
![]() |
2743716132 | ||
![]() |
a744eee993 | ||
![]() |
0e24267eb5 | ||
![]() |
f4d6043aa4 | ||
![]() |
9fb9bd31a3 | ||
![]() |
c3828bb0a3 | ||
![]() |
40371f0907 | ||
![]() |
94f9434564 | ||
![]() |
bfaf247d30 | ||
![]() |
2287c43b59 | ||
![]() |
15cc0f5f91 | ||
![]() |
68e0108b1c | ||
![]() |
7b3796bc39 | ||
![]() |
b5bc6d2cc4 | ||
![]() |
0d1d4ea1f9 | ||
![]() |
1a48f897f2 | ||
![]() |
2b42789de6 | ||
![]() |
b9c1da10ba | ||
![]() |
56f5a76696 | ||
![]() |
c7e8977e60 | ||
![]() |
e6ba3612db | ||
![]() |
5e77fb314c | ||
![]() |
1a2841deb1 | ||
![]() |
688637eca8 | ||
![]() |
85d1d70ca1 | ||
![]() |
09356c709a | ||
![]() |
07b9e86d02 | ||
![]() |
8e46e5d8b4 | ||
![]() |
96292a5b46 | ||
![]() |
ffa618c00b | ||
![]() |
291b9b3c82 | ||
![]() |
ec45117f0f | ||
![]() |
0d7aff9c56 | ||
![]() |
d31b239288 | ||
![]() |
b1cadf0e99 | ||
![]() |
c1f67585e6 | ||
![]() |
93988e28c0 | ||
![]() |
edef6e66e9 | ||
![]() |
e3f47809c4 | ||
![]() |
f759e7ac59 | ||
![]() |
544eb2c5a9 | ||
![]() |
30e3eba20a | ||
![]() |
f0e85a2a9c | ||
![]() |
106af5b46a | ||
![]() |
522716ed90 | ||
![]() |
a65fbb0211 | ||
![]() |
46ec859bd1 | ||
![]() |
2a7aa4eae4 | ||
![]() |
c31ddf021e | ||
![]() |
eaa2a8239f | ||
![]() |
d313ecb737 | ||
![]() |
64b2af0340 | ||
![]() |
58d0702948 | ||
![]() |
707717e94b | ||
![]() |
a140bba55a | ||
![]() |
f4ddacacd0 | ||
![]() |
ebba656bdb | ||
![]() |
b78c61d67a | ||
![]() |
4210aa61e1 | ||
![]() |
d8a345d924 | ||
![]() |
b8dc9767da | ||
![]() |
1ab01b9367 | ||
![]() |
ee371ff740 | ||
![]() |
ef58dd77ca | ||
![]() |
e6a7121904 | ||
![]() |
a6ed8ab59d | ||
![]() |
bd40d0ded1 | ||
![]() |
68bfcb6c54 | ||
![]() |
0d01efca52 | ||
![]() |
0e65e04ce1 | ||
![]() |
58d351fe98 | ||
![]() |
9b71f18141 | ||
![]() |
554f08bac3 | ||
![]() |
913813a933 | ||
![]() |
4e34c771e4 | ||
![]() |
9995174e68 | ||
![]() |
5a0197d430 | ||
![]() |
4a55143e15 | ||
![]() |
87c9bc1b1f | ||
![]() |
16a57b70f7 | ||
![]() |
69564cd0b1 | ||
![]() |
da648b00e7 | ||
![]() |
5886d90308 | ||
![]() |
e84df0cad1 | ||
![]() |
e482904111 | ||
![]() |
b8ee44ca6a | ||
![]() |
4a4abe4240 | ||
![]() |
fe47f5cc30 | ||
![]() |
5b64be0810 | ||
![]() |
17656d051b | ||
![]() |
233fce456a | ||
![]() |
5290bb036c | ||
![]() |
2bff72b4f6 | ||
![]() |
08ebeaee5c | ||
![]() |
12b56f5447 | ||
![]() |
165b86e7b7 | ||
![]() |
608101a185 | ||
![]() |
554bee6aae | ||
![]() |
3e0ce51067 | ||
![]() |
7261c43342 | ||
![]() |
ad57c6ea37 | ||
![]() |
caecff650d | ||
![]() |
f6300be4b2 | ||
![]() |
bde5687a3c | ||
![]() |
0f3504f78d | ||
![]() |
0aaa0321cc | ||
![]() |
caaaf52583 | ||
![]() |
56449f167d | ||
![]() |
c7325228dc | ||
![]() |
079967afa5 | ||
![]() |
2ed55b614c | ||
![]() |
28721e3cd2 | ||
![]() |
9d9845d063 | ||
![]() |
a96dc76831 | ||
![]() |
ad8e517227 | ||
![]() |
8d578d590f | ||
![]() |
6b4a211374 | ||
![]() |
55b023c961 | ||
![]() |
e2d0fe3e2f | ||
![]() |
6b56ff7a97 | ||
![]() |
67f796ebde | ||
![]() |
06da7490fc | ||
![]() |
af83c442d3 | ||
![]() |
d726e98596 | ||
![]() |
c9a6709bd2 | ||
![]() |
25816bea41 | ||
![]() |
e0f6e96da0 | ||
![]() |
57de46ae7e | ||
![]() |
59693c8996 | ||
![]() |
f0efffc093 | ||
![]() |
1b41cd759c | ||
![]() |
d42a1402e8 | ||
![]() |
5c44678d55 | ||
![]() |
0638fd58ce | ||
![]() |
cb662b6730 | ||
![]() |
e874c7515e | ||
![]() |
2ba797576b | ||
![]() |
180b454d61 | ||
![]() |
6ce7ae77b1 | ||
![]() |
abbaf95cf0 | ||
![]() |
1081b70951 | ||
![]() |
4f51f956ad | ||
![]() |
b076f4b590 | ||
![]() |
91180f8cb4 | ||
![]() |
99aa859362 | ||
![]() |
31267feb03 | ||
![]() |
6a5bac72cb | ||
![]() |
2ed5062950 | ||
![]() |
0b0b02c5a1 | ||
![]() |
28c71368a1 | ||
![]() |
25bd4285ab | ||
![]() |
180171cad6 | ||
![]() |
bc3eeecf7f | ||
![]() |
9178d14519 | ||
![]() |
6cd35f5b72 | ||
![]() |
72d5eb0ecb | ||
![]() |
5cf924420d | ||
![]() |
290574e6f6 | ||
![]() |
d9db975b4b | ||
![]() |
e5c0e5efa7 | ||
![]() |
26a1aae098 | ||
![]() |
ab114490fc | ||
![]() |
9546c54286 | ||
![]() |
4d3cdb70b5 | ||
![]() |
a66816a72f | ||
![]() |
c925f72562 | ||
![]() |
ef97329f41 | ||
![]() |
195f709eda | ||
![]() |
eb57d94ec5 | ||
![]() |
d6212ae839 | ||
![]() |
b494897b3d | ||
![]() |
559d4415eb | ||
![]() |
49e9134774 | ||
![]() |
9571b0ece8 | ||
![]() |
b55cfaf90b | ||
![]() |
509168856f | ||
![]() |
24fa2722c3 | ||
![]() |
142700f909 | ||
![]() |
f3611681df | ||
![]() |
7f0a5d6a10 | ||
![]() |
2001cc15d5 |
36
.github/workflows/create-test-plan.py
vendored
36
.github/workflows/create-test-plan.py
vendored
@@ -20,7 +20,6 @@ class AppleArch(Enum):
|
||||
class MsvcArch(Enum):
|
||||
X86 = "x86"
|
||||
X64 = "x64"
|
||||
Arm32 = "arm"
|
||||
Arm64 = "arm64"
|
||||
|
||||
|
||||
@@ -54,6 +53,7 @@ class SdlPlatform(Enum):
|
||||
Riscos = "riscos"
|
||||
FreeBSD = "freebsd"
|
||||
NetBSD = "netbsd"
|
||||
OpenBSD = "openbsd"
|
||||
|
||||
|
||||
class Msys2Platform(Enum):
|
||||
@@ -108,7 +108,6 @@ JOB_SPECS = {
|
||||
"msvc-x86": JobSpec(name="Windows (MSVC, x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x86", msvc_arch=MsvcArch.X86, msvc_project="VisualC/SDL.sln", ),
|
||||
"msvc-clang-x64": JobSpec(name="Windows (MSVC, clang-cl x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x64", msvc_arch=MsvcArch.X64, clang_cl=True, ),
|
||||
"msvc-clang-x86": JobSpec(name="Windows (MSVC, clang-cl x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x86", msvc_arch=MsvcArch.X86, clang_cl=True, ),
|
||||
"msvc-arm32": JobSpec(name="Windows (MSVC, ARM)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm32", msvc_arch=MsvcArch.Arm32, ),
|
||||
"msvc-arm64": JobSpec(name="Windows (MSVC, ARM64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm64", msvc_arch=MsvcArch.Arm64, ),
|
||||
"msvc-gdk-x64": JobSpec(name="GDK (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-GDK", msvc_arch=MsvcArch.X64, msvc_project="VisualC-GDK/SDL.sln", gdk=True, no_cmake=True, ),
|
||||
"ubuntu-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", ),
|
||||
@@ -137,6 +136,7 @@ JOB_SPECS = {
|
||||
"vita-pvr": JobSpec(name="Sony PlayStation Vita (GLES w/ PVR_PSP2)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pvr", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pvr, ),
|
||||
"riscos": JobSpec(name="RISC OS", os=JobOs.UbuntuLatest, platform=SdlPlatform.Riscos, artifact="SDL-riscos", container="riscosdotinfo/riscos-gccsdk-4.7:latest", ),
|
||||
"netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", ),
|
||||
"openbsd": JobSpec(name="OpenBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.OpenBSD, artifact="SDL-openbsd-x64", ),
|
||||
"freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ),
|
||||
}
|
||||
|
||||
@@ -174,6 +174,7 @@ class JobDetails:
|
||||
brew_packages: list[str] = dataclasses.field(default_factory=list)
|
||||
cmake_toolchain_file: str = ""
|
||||
cmake_arguments: list[str] = dataclasses.field(default_factory=list)
|
||||
cmake_generator: str = "Ninja"
|
||||
cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
|
||||
clang_tidy: bool = True
|
||||
cppflags: list[str] = dataclasses.field(default_factory=list)
|
||||
@@ -222,6 +223,7 @@ class JobDetails:
|
||||
check_sources: bool = False
|
||||
setup_python: bool = False
|
||||
pypi_packages: list[str] = dataclasses.field(default_factory=list)
|
||||
binutils_strings: str = "strings"
|
||||
|
||||
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
|
||||
data = {
|
||||
@@ -255,6 +257,7 @@ class JobDetails:
|
||||
"cflags": my_shlex_join(self.cppflags + self.cflags),
|
||||
"cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
|
||||
"ldflags": my_shlex_join(self.ldflags),
|
||||
"cmake-generator": self.cmake_generator,
|
||||
"cmake-toolchain-file": self.cmake_toolchain_file,
|
||||
"clang-tidy": self.clang_tidy,
|
||||
"cmake-arguments": my_shlex_join(self.cmake_arguments),
|
||||
@@ -289,6 +292,7 @@ class JobDetails:
|
||||
"check-sources": self.check_sources,
|
||||
"setup-python": self.setup_python,
|
||||
"pypi-packages": my_shlex_join(self.pypi_packages),
|
||||
"binutils-strings": self.binutils_strings,
|
||||
}
|
||||
return {k: v for k, v in data.items() if v != ""}
|
||||
|
||||
@@ -403,10 +407,6 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
job.msvc_vcvars_arch = "x64_x86"
|
||||
case MsvcArch.X64:
|
||||
job.msvc_vcvars_arch = "x64"
|
||||
case MsvcArch.Arm32:
|
||||
job.msvc_vcvars_arch = "x64_arm"
|
||||
job.msvc_vcvars_sdk = "10.0.22621.0" # 10.0.26100.0 dropped ARM32 um and ucrt libraries
|
||||
job.run_tests = False
|
||||
case MsvcArch.Arm64:
|
||||
job.msvc_vcvars_arch = "x64_arm64"
|
||||
job.run_tests = False
|
||||
@@ -512,11 +512,14 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
job.shared_lib = SharedLibType.DYLIB
|
||||
job.static_lib = StaticLibType.A
|
||||
job.ccache = True
|
||||
if spec.os == JobOs.Macos13:
|
||||
job.ccache = False
|
||||
job.apt_packages = []
|
||||
job.brew_packages.extend((
|
||||
"ccache",
|
||||
"ninja",
|
||||
))
|
||||
if job.ccache:
|
||||
job.brew_packages.append("ccache")
|
||||
if job.clang_tidy:
|
||||
job.brew_packages.append("llvm")
|
||||
if spec.xcode:
|
||||
@@ -550,6 +553,10 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
"testmultiaudio-apk",
|
||||
"testsprite-apk",
|
||||
]
|
||||
|
||||
# -fPIC is required after updating NDK from 21 to 28
|
||||
job.cflags.append("-fPIC")
|
||||
job.cxxflags.append("-fPIC")
|
||||
case SdlPlatform.Emscripten:
|
||||
job.clang_tidy = False # clang-tidy does not understand -gsource-map
|
||||
job.shared = False
|
||||
@@ -675,13 +682,16 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
job.shared_lib = SharedLibType.SO_0
|
||||
job.static_lib = StaticLibType.A
|
||||
case SdlPlatform.N3ds:
|
||||
job.ccache = True
|
||||
job.cmake_generator = "Unix Makefiles"
|
||||
job.cmake_build_arguments.append("-j$(nproc)")
|
||||
job.ccache = False
|
||||
job.shared = False
|
||||
job.apt_packages = ["ccache", "ninja-build", "binutils"]
|
||||
job.apt_packages = []
|
||||
job.clang_tidy = False
|
||||
job.run_tests = False
|
||||
job.cc_from_cmake = True
|
||||
job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
|
||||
job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
|
||||
job.static_lib = StaticLibType.A
|
||||
case SdlPlatform.Msys2:
|
||||
job.ccache = True
|
||||
@@ -713,7 +723,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
))
|
||||
job.cmake_toolchain_file = "/home/riscos/env/toolchain-riscos.cmake"
|
||||
job.static_lib = StaticLibType.A
|
||||
case SdlPlatform.FreeBSD | SdlPlatform.NetBSD:
|
||||
case SdlPlatform.FreeBSD | SdlPlatform.NetBSD | SdlPlatform.OpenBSD:
|
||||
job.cpactions = True
|
||||
job.no_cmake = True
|
||||
job.run_tests = False
|
||||
@@ -737,6 +747,12 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
job.cpactions_arch = "x86-64"
|
||||
job.cpactions_setup_cmd = "export PATH=\"/usr/pkg/sbin:/usr/pkg/bin:/sbin:$PATH\"; export PKG_CONFIG_PATH=\"/usr/pkg/lib/pkgconfig\";export PKG_PATH=\"https://cdn.netBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f \"1 2\" -d.)/All/\";echo \"PKG_PATH=$PKG_PATH\";echo \"uname -a -> \"$(uname -a)\"\";sudo -E sysctl -w security.pax.aslr.enabled=0;sudo -E sysctl -w security.pax.aslr.global=0;sudo -E pkgin clean;sudo -E pkgin update"
|
||||
job.cpactions_install_cmd = "sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1"
|
||||
case SdlPlatform.OpenBSD:
|
||||
job.cpactions_os = "openbsd"
|
||||
job.cpactions_version = "7.4"
|
||||
job.cpactions_arch = "x86-64"
|
||||
job.cpactions_setup_cmd = "sudo pkg_add -u"
|
||||
job.cpactions_install_cmd = "sudo pkg_add cmake ninja pkgconf wayland wayland-protocols xwayland libxkbcommon libinotify pulseaudio dbus ibus"
|
||||
case _:
|
||||
raise ValueError(f"Unsupported platform={spec.platform}")
|
||||
|
||||
|
16
.github/workflows/generic.yml
vendored
16
.github/workflows/generic.yml
vendored
@@ -76,7 +76,7 @@ jobs:
|
||||
id: setup-ndk
|
||||
with:
|
||||
local-cache: true
|
||||
ndk-version: r21e
|
||||
ndk-version: r28c
|
||||
- name: 'Configure Android NDK variables'
|
||||
if: ${{ matrix.platform.android-ndk }}
|
||||
shell: sh
|
||||
@@ -201,7 +201,7 @@ jobs:
|
||||
#shell: ${{ matrix.platform.shell }}
|
||||
run: |
|
||||
${{ matrix.platform.source-cmd }}
|
||||
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
|
||||
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -G "${{ matrix.platform.cmake-generator }}" \
|
||||
-Wdeprecated -Wdev -Werror \
|
||||
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
|
||||
-DSDL_WERROR=${{ matrix.platform.werror }} \
|
||||
@@ -232,9 +232,9 @@ jobs:
|
||||
run: |
|
||||
echo "This should show us the SDL_REVISION"
|
||||
echo "Shared library:"
|
||||
${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
|
||||
${{ (matrix.platform.shared-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
|
||||
echo "Static library:"
|
||||
${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
|
||||
${{ (matrix.platform.static-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
|
||||
- name: 'Run build-time tests (CMake)'
|
||||
id: tests
|
||||
if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}
|
||||
@@ -406,6 +406,14 @@ jobs:
|
||||
build-scripts/test-versioning.sh
|
||||
python build-scripts/check_android_jni.py
|
||||
python build-scripts/check_stdlib_usage.py
|
||||
- name: 'Verify alignment of Android test apks'
|
||||
if: ${{ matrix.platform.android-ndk && !matrix.platform.no-cmake }}
|
||||
run: |
|
||||
find ./ -iname '*.apk' | xargs -L1 ./build-scripts/check_elf_alignment.sh
|
||||
- name: 'Verify alignment of Android .so files'
|
||||
if: ${{ matrix.platform.android-ndk && !matrix.platform.no-cmake }}
|
||||
run: |
|
||||
find ./ -iname '*.so' | xargs -L1 ./build-scripts/check_elf_alignment.sh
|
||||
- name: 'Upload binary package'
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }}
|
||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -256,7 +256,7 @@ jobs:
|
||||
|
||||
msvc:
|
||||
needs: [src]
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2025
|
||||
outputs:
|
||||
VC-x86: ${{ steps.releaser.outputs.VC-x86 }}
|
||||
VC-x64: ${{ steps.releaser.outputs.VC-x64 }}
|
||||
@@ -535,7 +535,7 @@ jobs:
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
local-cache: true
|
||||
ndk-version: r21e
|
||||
ndk-version: r28c
|
||||
- name: 'Setup Java JDK'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
|
126
CMakeLists.txt
126
CMakeLists.txt
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
# See docs/release_checklist.md
|
||||
project(SDL3 LANGUAGES C VERSION "3.2.14")
|
||||
project(SDL3 LANGUAGES C VERSION "3.2.24")
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(SDL3_MAINPROJECT ON)
|
||||
@@ -79,6 +79,12 @@ include("${SDL3_SOURCE_DIR}/cmake/PreseedEmscriptenCache.cmake")
|
||||
|
||||
SDL_DetectCompiler()
|
||||
SDL_DetectTargetCPUArchitectures(SDL_CPUS)
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
list(LENGTH CMAKE_OSX_ARCHITECTURES _num_arches)
|
||||
if(_num_arches GREATER 1)
|
||||
set(APPLE_MULTIARCH TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Increment this if there is an incompatible change - but if that happens,
|
||||
# we should rename the library from SDL3 to SDL4, at which point this would
|
||||
@@ -183,26 +189,6 @@ if(MSVC)
|
||||
set(SDL_RELOCATABLE_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(NOT SDL_LIBC)
|
||||
# Make sure /RTC1 is disabled, otherwise it will use functions from the CRT
|
||||
foreach(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "/RTC(su|[1su])" "" ${flag_var} "${${flag_var}}")
|
||||
endforeach(flag_var)
|
||||
endif()
|
||||
|
||||
if(MSVC_CLANG)
|
||||
# clang-cl treats /W4 as '-Wall -Wextra' -- we don't need -Wextra
|
||||
foreach(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "/W4" "/W3" ${flag_var} "${${flag_var}}")
|
||||
endforeach(flag_var)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SDL_SHARED_DEFAULT ON)
|
||||
set(SDL_STATIC_DEFAULT ON)
|
||||
|
||||
@@ -370,7 +356,7 @@ dep_option(SDL_WASAPI "Use the Windows WASAPI audio driver" ON "WIN
|
||||
dep_option(SDL_RENDER_D3D "Enable the Direct3D 9 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF)
|
||||
dep_option(SDL_RENDER_D3D11 "Enable the Direct3D 11 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF)
|
||||
dep_option(SDL_RENDER_D3D12 "Enable the Direct3D 12 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF)
|
||||
dep_option(SDL_RENDER_METAL "Enable the Metal render driver" ON "SDL_RENDER;${APPLE}" OFF)
|
||||
dep_option(SDL_RENDER_METAL "Enable the Metal render driver" ON "SDL_RENDER;APPLE" OFF)
|
||||
dep_option(SDL_RENDER_GPU "Enable the SDL_GPU render driver" ON "SDL_RENDER;SDL_GPU" OFF)
|
||||
dep_option(SDL_VIVANTE "Use Vivante EGL video driver" ON "${UNIX_SYS};SDL_CPU_ARM32" OFF)
|
||||
dep_option(SDL_VULKAN "Enable Vulkan support" ON "SDL_VIDEO;ANDROID OR APPLE OR LINUX OR FREEBSD OR WINDOWS" OFF)
|
||||
@@ -421,6 +407,29 @@ if(SDL_PRESEED)
|
||||
SDL_Preseed_CMakeCache()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(NOT SDL_LIBC)
|
||||
# Make sure /RTC1 is disabled, otherwise it will use functions from the CRT
|
||||
foreach(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "/RTC(su|[1su])" "" ${flag_var} "${${flag_var}}")
|
||||
endforeach(flag_var)
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS "")
|
||||
endif()
|
||||
|
||||
if(MSVC_CLANG)
|
||||
# clang-cl treats /W4 as '-Wall -Wextra' -- we don't need -Wextra
|
||||
foreach(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "/W4" "/W3" ${flag_var} "${${flag_var}}")
|
||||
endforeach(flag_var)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL_SHARED)
|
||||
add_library(SDL3-shared SHARED)
|
||||
add_library(SDL3::SDL3-shared ALIAS SDL3-shared)
|
||||
@@ -634,6 +643,11 @@ if(MSVC)
|
||||
# Mark SDL3.dll as compatible with Control-flow Enforcement Technology (CET)
|
||||
sdl_shared_link_options("-CETCOMPAT")
|
||||
endif()
|
||||
|
||||
# for VS >= 17.14 targeting ARM64: inline the Interlocked funcs
|
||||
if(MSVC_VERSION GREATER 1943 AND SDL_CPU_ARM64 AND NOT SDL_LIBC)
|
||||
sdl_compile_options(PRIVATE "/forceInterlockedFunctions-")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||
@@ -650,7 +664,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -mmmx")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <mmintrin.h>
|
||||
void ints_add(int *dest, int *a, int *b, unsigned size) {
|
||||
for (; size >= 2; size -= 2, dest += 2, a += 2, b += 2) {
|
||||
@@ -660,7 +674,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char *argv[]) {
|
||||
ints_add((int*)0, (int*)0, (int*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_MMX)
|
||||
}]==] COMPILER_SUPPORTS_MMX)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_MMX)
|
||||
set(HAVE_MMX TRUE)
|
||||
@@ -671,7 +685,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <xmmintrin.h>
|
||||
void floats_add(float *dest, float *a, float *b, unsigned size) {
|
||||
for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) {
|
||||
@@ -681,7 +695,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
floats_add((float*)0, (float*)0, (float*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_SSE)
|
||||
}]==] COMPILER_SUPPORTS_SSE)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_SSE)
|
||||
set(HAVE_SSE TRUE)
|
||||
@@ -692,7 +706,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse2")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <emmintrin.h>
|
||||
void doubles_add(double *dest, double *a, double *b, unsigned size) {
|
||||
for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) {
|
||||
@@ -702,7 +716,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
doubles_add((double*)0, (double*)0, (double*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_SSE2)
|
||||
}]==] COMPILER_SUPPORTS_SSE2)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_SSE2)
|
||||
set(HAVE_SSE2 TRUE)
|
||||
@@ -713,7 +727,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse3")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <pmmintrin.h>
|
||||
void ints_add(int *dest, int *a, int *b, unsigned size) {
|
||||
for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) {
|
||||
@@ -723,7 +737,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
ints_add((int*)0, (int*)0, (int*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_SSE3)
|
||||
}]==] COMPILER_SUPPORTS_SSE3)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_SSE3)
|
||||
set(HAVE_SSE3 TRUE)
|
||||
@@ -734,7 +748,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse4.1")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <smmintrin.h>
|
||||
void ints_mul(int *dest, int *a, int *b, unsigned size) {
|
||||
for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) {
|
||||
@@ -744,7 +758,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
ints_mul((int*)0, (int*)0, (int*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_SSE4_1)
|
||||
}]==] COMPILER_SUPPORTS_SSE4_1)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_SSE4_1)
|
||||
set(HAVE_SSE4_1 TRUE)
|
||||
@@ -753,21 +767,16 @@ if(SDL_ASSEMBLY)
|
||||
if(SDL_SSE4_2)
|
||||
cmake_push_check_state()
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse4.2 -mcrc32")
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -msse4.2")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <nmmintrin.h>
|
||||
unsigned calc_crc32c(const char *text, unsigned len) {
|
||||
unsigned crc32c = ~0;
|
||||
for (; len >= 4; len -= 4, text += 4) {
|
||||
crc32c = (unsigned)_mm_crc32_u32(crc32c, *(unsigned*)text);
|
||||
}
|
||||
return crc32c;
|
||||
}
|
||||
__m128i bitmask;
|
||||
char data[16];
|
||||
int main(int argc, char **argv) {
|
||||
calc_crc32c(\"SDL_SSE4\",8);
|
||||
bitmask = _mm_cmpgt_epi64(_mm_set1_epi64x(0), _mm_loadu_si128((void*)data));
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_SSE4_2)
|
||||
}]==] COMPILER_SUPPORTS_SSE4_2)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_SSE4_2)
|
||||
set(HAVE_SSE4_2 TRUE)
|
||||
@@ -778,7 +787,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -mavx")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <immintrin.h>
|
||||
void floats_add(float *dest, float *a, float *b, unsigned size) {
|
||||
for (; size >= 8; size -= 8, dest += 8, a += 8, b += 8) {
|
||||
@@ -788,7 +797,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
floats_add((float*)0, (float*)0, (float*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_AVX)
|
||||
}]==] COMPILER_SUPPORTS_AVX)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_AVX)
|
||||
set(HAVE_AVX TRUE)
|
||||
@@ -799,7 +808,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -mavx2")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <immintrin.h>
|
||||
void ints_add(int *dest, int *a, int *b, unsigned size) {
|
||||
for (; size >= 8; size -= 8, dest += 8, a += 8, b += 8) {
|
||||
@@ -809,7 +818,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
ints_add((int*)0, (int*)0, (int*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_AVX2)
|
||||
}]==] COMPILER_SUPPORTS_AVX2)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_AVX2)
|
||||
set(HAVE_AVX2 TRUE)
|
||||
@@ -820,7 +829,7 @@ if(SDL_ASSEMBLY)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -mavx512f")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
check_x86_source_compiles([==[
|
||||
#include <immintrin.h>
|
||||
void floats_add(float *dest, float *a, float *b, unsigned size) {
|
||||
for (; size >= 16; size -= 16, dest += 16, a += 16, b += 16) {
|
||||
@@ -830,7 +839,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char **argv) {
|
||||
floats_add((float*)0, (float*)0, (float*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_AVX512F)
|
||||
}]==] COMPILER_SUPPORTS_AVX512F)
|
||||
cmake_pop_check_state()
|
||||
if(COMPILER_SUPPORTS_AVX512F)
|
||||
set(HAVE_AVX512F TRUE)
|
||||
@@ -838,7 +847,7 @@ if(SDL_ASSEMBLY)
|
||||
endif()
|
||||
|
||||
if(SDL_ARMNEON)
|
||||
check_c_source_compiles("
|
||||
check_arm_source_compiles([==[
|
||||
#include <arm_neon.h>
|
||||
void floats_add(float *dest, float *a, float *b, unsigned size) {
|
||||
for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) {
|
||||
@@ -848,8 +857,7 @@ if(SDL_ASSEMBLY)
|
||||
int main(int argc, char *argv[]) {
|
||||
floats_add((float*)0, (float*)0, (float*)0, 0);
|
||||
return 0;
|
||||
}" COMPILER_SUPPORTS_ARMNEON)
|
||||
|
||||
}]==] COMPILER_SUPPORTS_ARMNEON)
|
||||
if(COMPILER_SUPPORTS_ARMNEON)
|
||||
set(HAVE_ARMNEON TRUE)
|
||||
endif()
|
||||
@@ -1052,8 +1060,10 @@ if(SDL_LIBC)
|
||||
cmake_push_check_state()
|
||||
if(MSVC)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -we4244 -WX") # 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
else()
|
||||
elseif(HAVE_GCC_WFLOAT_CONVERSION)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -Wfloat-conversion -Werror")
|
||||
else()
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS " -Wconversion -Werror")
|
||||
endif()
|
||||
foreach(math_fn isinf isnan)
|
||||
string(TOUPPER "${math_fn}" MATH_FN)
|
||||
@@ -1091,6 +1101,7 @@ if(SDL_LIBC)
|
||||
check_symbol_exists(gethostname "unistd.h" HAVE_GETHOSTNAME)
|
||||
check_symbol_exists(getpagesize "unistd.h" HAVE_GETPAGESIZE)
|
||||
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
|
||||
check_symbol_exists(sigtimedwait "signal.h" HAVE_SIGTIMEDWAIT)
|
||||
check_symbol_exists(setjmp "setjmp.h" HAVE_SETJMP)
|
||||
check_symbol_exists(nanosleep "time.h" HAVE_NANOSLEEP)
|
||||
check_symbol_exists(gmtime_r "time.h" HAVE_GMTIME_R)
|
||||
@@ -1336,9 +1347,7 @@ if(ANDROID)
|
||||
set(HAVE_SDL_HAPTIC TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_HIDAPI)
|
||||
CheckHIDAPI()
|
||||
endif()
|
||||
|
||||
if(SDL_JOYSTICK)
|
||||
set(SDL_JOYSTICK_ANDROID 1)
|
||||
@@ -2954,7 +2963,7 @@ if(WINDOWS)
|
||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/process/windows/*.c")
|
||||
set(SDL_PROCESS_WINDOWS 1)
|
||||
set(HAVE_SDL_PROCESS TRUE)
|
||||
else()
|
||||
elseif(NOT ANDROID)
|
||||
check_c_source_compiles("
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
@@ -3144,14 +3153,15 @@ endforeach()
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/REVISION.txt")
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/REVISION.txt" revisions)
|
||||
list(GET revisions 0 revisions_0)
|
||||
string(STRIP "${revisions_0}" SDL_REVISION)
|
||||
string(STRIP "${revisions_0}" revisions_0_stripped)
|
||||
set(SDL_REVISION "SDL-${revisions_0_stripped}")
|
||||
else()
|
||||
set(SDL_REVISION "" CACHE STRING "Custom SDL revision (only used when REVISION.txt does not exist)")
|
||||
endif()
|
||||
if(NOT SDL_REVISION)
|
||||
# If SDL_REVISION is not overrided, use git to describe
|
||||
git_describe(SDL_REVISION_GIT)
|
||||
set(SDL_REVISION "SDL3-${SDL3_VERSION}-${SDL_REVISION_GIT}")
|
||||
set(SDL_REVISION "SDL-${SDL3_VERSION}-${SDL_REVISION_GIT}")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${SDL3_BINARY_DIR}/include-revision/SDL3")
|
||||
|
@@ -19,10 +19,10 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.2.14</string>
|
||||
<string>3.2.24</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>SDLX</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.2.14</string>
|
||||
<string>3.2.24</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@@ -3086,7 +3086,7 @@
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEPLOYMENT_POSTPROCESSING = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
||||
DYLIB_CURRENT_VERSION = 201.14.0;
|
||||
DYLIB_CURRENT_VERSION = 201.24.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
@@ -3121,7 +3121,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.2.14;
|
||||
MARKETING_VERSION = 3.2.24;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
PRODUCT_NAME = SDL3;
|
||||
@@ -3150,7 +3150,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
||||
DYLIB_CURRENT_VERSION = 201.14.0;
|
||||
DYLIB_CURRENT_VERSION = 201.24.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -3182,7 +3182,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.2.14;
|
||||
MARKETING_VERSION = 3.2.24;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Title SDL 3.2.14
|
||||
Title SDL 3.2.24
|
||||
Version 1
|
||||
Description SDL Library for macOS (http://www.libsdl.org)
|
||||
DefaultLocation /Library/Frameworks
|
||||
|
@@ -92,7 +92,7 @@ if(NOT TARGET SDL3::Headers)
|
||||
add_library(SDL3::Headers INTERFACE IMPORTED)
|
||||
set_target_properties(SDL3::Headers
|
||||
PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${_sdl3_framework_parent_path}\""
|
||||
INTERFACE_COMPILE_OPTIONS "-F${_sdl3_framework_parent_path}"
|
||||
)
|
||||
endif()
|
||||
set(SDL3_Headers_FOUND TRUE)
|
||||
|
@@ -7,4 +7,4 @@
|
||||
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
|
||||
|
||||
# Min runtime API level
|
||||
APP_PLATFORM=android-16
|
||||
APP_PLATFORM=android-21
|
||||
|
2
android-project/app/proguard-rules.pro
vendored
2
android-project/app/proguard-rules.pro
vendored
@@ -51,6 +51,8 @@
|
||||
boolean supportsRelativeMouse();
|
||||
int openFileDescriptor(java.lang.String, java.lang.String);
|
||||
boolean showFileDialog(java.lang.String[], boolean, boolean, int);
|
||||
java.lang.String getPreferredLocales();
|
||||
java.lang.String formatLocale(java.util.Locale);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
|
||||
|
@@ -23,6 +23,7 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.DisplayMetrics;
|
||||
@@ -60,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 3;
|
||||
private static final int SDL_MINOR_VERSION = 2;
|
||||
private static final int SDL_MICRO_VERSION = 14;
|
||||
private static final int SDL_MICRO_VERSION = 24;
|
||||
/*
|
||||
// Display InputType.SOURCE/CLASS of events and devices
|
||||
//
|
||||
@@ -2116,6 +2117,44 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
int requestCode;
|
||||
boolean multipleChoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static String getPreferredLocales() {
|
||||
String result = "";
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7 (N) */) {
|
||||
LocaleList locales = LocaleList.getAdjustedDefault();
|
||||
for (int i = 0; i < locales.size(); i++) {
|
||||
if (i != 0) result += ",";
|
||||
result += formatLocale(locales.get(i));
|
||||
}
|
||||
} else if (mCurrentLocale != null) {
|
||||
result = formatLocale(mCurrentLocale);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String formatLocale(Locale locale) {
|
||||
String result = "";
|
||||
String lang = "";
|
||||
if (locale.getLanguage() == "in") {
|
||||
// Indonesian is "id" according to ISO 639.2, but on Android is "in" because of Java backwards compatibility
|
||||
lang = "id";
|
||||
} else if (locale.getLanguage() == "") {
|
||||
// Make sure language is never empty
|
||||
lang = "und";
|
||||
} else {
|
||||
lang = locale.getLanguage();
|
||||
}
|
||||
|
||||
if (locale.getCountry() == "") {
|
||||
result = lang;
|
||||
} else {
|
||||
result = lang + "_" + locale.getCountry();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2157,7 +2196,11 @@ class SDLClipboardHandler implements
|
||||
}
|
||||
|
||||
public boolean clipboardHasText() {
|
||||
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (P) */) {
|
||||
return mClipMgr.hasPrimaryClip();
|
||||
} else {
|
||||
return mClipMgr.hasText();
|
||||
}
|
||||
}
|
||||
|
||||
public String clipboardGetText() {
|
||||
@@ -2176,8 +2219,17 @@ class SDLClipboardHandler implements
|
||||
|
||||
public void clipboardSetText(String string) {
|
||||
mClipMgr.removePrimaryClipChangedListener(this);
|
||||
if (string.isEmpty()) {
|
||||
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (P) */) {
|
||||
mClipMgr.clearPrimaryClip();
|
||||
} else {
|
||||
ClipData clip = ClipData.newPlainText(null, "");
|
||||
mClipMgr.setPrimaryClip(clip);
|
||||
}
|
||||
} else {
|
||||
ClipData clip = ClipData.newPlainText(null, string);
|
||||
mClipMgr.setPrimaryClip(clip);
|
||||
}
|
||||
mClipMgr.addPrimaryClipChangedListener(this);
|
||||
}
|
||||
|
||||
|
@@ -542,6 +542,7 @@ class AndroidApiVersion:
|
||||
def __repr__(self) -> str:
|
||||
return f"<{self.name} ({'.'.join(str(v) for v in self.ints)})>"
|
||||
|
||||
ANDROID_ABI_EXTRA_LINK_OPTIONS = {}
|
||||
|
||||
class Releaser:
|
||||
def __init__(self, release_info: dict, commit: str, revision: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str, deps_path: Path, overwrite: bool, github: bool, fast: bool):
|
||||
@@ -1013,6 +1014,7 @@ class Releaser:
|
||||
android_devel_file_tree = ArchiveFileTree()
|
||||
|
||||
for android_abi in android_abis:
|
||||
extra_link_options = ANDROID_ABI_EXTRA_LINK_OPTIONS.get(android_abi, "")
|
||||
with self.section_printer.group(f"Building for Android {android_api} {android_abi}"):
|
||||
build_dir = self.root / "build-android" / f"{android_abi}-build"
|
||||
install_dir = self.root / "install-android" / f"{android_abi}-install"
|
||||
@@ -1023,8 +1025,11 @@ class Releaser:
|
||||
"cmake",
|
||||
"-S", str(self.root),
|
||||
"-B", str(build_dir),
|
||||
f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
# NDK 21e does not support -ffile-prefix-map
|
||||
# f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
# f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
f"-DCMAKE_EXE_LINKER_FLAGS={extra_link_options}",
|
||||
f"-DCMAKE_SHARED_LINKER_FLAGS={extra_link_options}",
|
||||
f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}",
|
||||
f"-DCMAKE_PREFIX_PATH={str(android_deps_path)}",
|
||||
f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH",
|
||||
@@ -1530,7 +1535,7 @@ def main(argv=None) -> int:
|
||||
parser.error("Invalid --android-api, and/or could not be detected")
|
||||
android_api_path = Path(args.android_home) / f"platforms/{args.android_api.name}"
|
||||
if not android_api_path.is_dir():
|
||||
parser.error(f"Android API directory does not exist ({android_api_path})")
|
||||
logger.warning(f"Android API directory does not exist ({android_api_path})")
|
||||
with section_printer.group("Android arguments"):
|
||||
print(f"android_home = {args.android_home}")
|
||||
print(f"android_ndk_home = {args.android_ndk_home}")
|
||||
|
127
build-scripts/check_elf_alignment.sh
Executable file
127
build-scripts/check_elf_alignment.sh
Executable file
@@ -0,0 +1,127 @@
|
||||
#!/bin/bash
|
||||
progname="${0##*/}"
|
||||
progname="${progname%.sh}"
|
||||
|
||||
# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
|
||||
|
||||
cleanup_trap() {
|
||||
if [ -n "${tmp}" -a -d "${tmp}" ]; then
|
||||
rm -rf ${tmp}
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Host side script to check the ELF alignment of shared libraries."
|
||||
echo "Shared libraries are reported ALIGNED when their ELF regions are"
|
||||
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
|
||||
echo
|
||||
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
|
||||
}
|
||||
|
||||
if [ ${#} -ne 1 ]; then
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
|
||||
case ${1} in
|
||||
--help | -h | -\?)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
|
||||
*)
|
||||
dir="${1}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! [ -f "${dir}" -o -d "${dir}" ]; then
|
||||
echo "Invalid file: ${dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apk ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
|
||||
echo "=== APK zip-alignment ==="
|
||||
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
|
||||
echo "========================="
|
||||
else
|
||||
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
|
||||
echo " You can install the latest build-tools by running the below command"
|
||||
echo " and updating your \$PATH:"
|
||||
echo
|
||||
echo " sdkmanager \"build-tools;35.0.0-rc3\""
|
||||
fi
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
|
||||
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apex ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
|
||||
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
RED="\e[31m"
|
||||
GREEN="\e[32m"
|
||||
ENDCOLOR="\e[0m"
|
||||
|
||||
unaligned_libs=()
|
||||
unaligned_critical_libs=()
|
||||
|
||||
echo
|
||||
echo "=== ELF alignment ==="
|
||||
|
||||
matches="$(find "${dir}" -type f)"
|
||||
IFS=$'\n'
|
||||
for match in $matches; do
|
||||
# We could recursively call this script or rewrite it to though.
|
||||
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
|
||||
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"
|
||||
|
||||
[[ $(file "${match}") == *"ELF"* ]] || continue
|
||||
|
||||
res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
|
||||
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
|
||||
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
|
||||
else
|
||||
unaligned_libs+=("${match}")
|
||||
# Check if this is a critical architecture (arm64-v8a or x86_64)
|
||||
if [[ "${match}" == *"arm64-v8a"* ]] || [[ "${match}" == *"x86_64"* ]]; then
|
||||
unaligned_critical_libs+=("${match}")
|
||||
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
|
||||
else
|
||||
echo -e "${match}: UNALIGNED ($res)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#unaligned_libs[@]} -gt 0 ]; then
|
||||
echo -e "Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
|
||||
fi
|
||||
echo "====================="
|
||||
|
||||
# Exit with appropriate code: 1 if critical unaligned libs found, 0 otherwise
|
||||
if [ ${#unaligned_critical_libs[@]} -gt 0 ]; then
|
||||
echo -e "${RED}Found ${#unaligned_critical_libs[@]} critical unaligned libs.${ENDCOLOR}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "${GREEN}ELF Verification Successful${ENDCOLOR}"
|
||||
exit 0
|
||||
fi
|
@@ -183,7 +183,7 @@
|
||||
],
|
||||
"api-minimum": 21,
|
||||
"api-target": 35,
|
||||
"ndk-minimum": 21,
|
||||
"ndk-minimum": 28,
|
||||
"aar-files": {
|
||||
"": [
|
||||
"android-project/app/proguard-rules.pro:proguard.txt",
|
||||
|
@@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# libtool assumes that the compiler can handle the -fPIC flag
|
||||
# This isn't always true (for example, nasm can't handle it)
|
||||
command=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-?PIC)
|
||||
# Ignore -fPIC and -DPIC options
|
||||
;;
|
||||
-fno-common)
|
||||
# Ignore -fPIC and -DPIC options
|
||||
;;
|
||||
*)
|
||||
command="$command $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo $command
|
||||
exec $command
|
@@ -1077,6 +1077,14 @@ endmacro()
|
||||
|
||||
# Check for HIDAPI support
|
||||
macro(CheckHIDAPI)
|
||||
if(ANDROID)
|
||||
enable_language(CXX)
|
||||
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp")
|
||||
endif()
|
||||
if(IOS OR TVOS)
|
||||
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m")
|
||||
set(SDL_FRAMEWORK_COREBLUETOOTH 1)
|
||||
endif()
|
||||
if(SDL_HIDAPI)
|
||||
set(HAVE_HIDAPI ON)
|
||||
if(SDL_HIDAPI_LIBUSB)
|
||||
@@ -1109,14 +1117,6 @@ macro(CheckHIDAPI)
|
||||
endif()
|
||||
|
||||
if(HAVE_HIDAPI)
|
||||
if(ANDROID)
|
||||
enable_language(CXX)
|
||||
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp")
|
||||
endif()
|
||||
if(IOS OR TVOS)
|
||||
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m")
|
||||
set(SDL_FRAMEWORK_COREBLUETOOTH 1)
|
||||
endif()
|
||||
set(HAVE_SDL_HIDAPI TRUE)
|
||||
|
||||
if(SDL_JOYSTICK AND SDL_HIDAPI_JOYSTICK)
|
||||
|
@@ -160,3 +160,63 @@ function(SDL_AddCommonCompilerFlags TARGET)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(check_x86_source_compiles BODY VAR)
|
||||
if(ARGN)
|
||||
message(FATAL_ERROR "Unknown arguments: ${ARGN}")
|
||||
endif()
|
||||
if(APPLE_MULTIARCH AND (SDL_CPU_X86 OR SDL_CPU_X64))
|
||||
set(test_conditional 1)
|
||||
else()
|
||||
set(test_conditional 0)
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
#if ${test_conditional}
|
||||
# if defined(__i386__) || defined(__x86_64__)
|
||||
# define test_enabled 1
|
||||
# else
|
||||
# define test_enabled 0 /* feign success in Apple multi-arch configs */
|
||||
# endif
|
||||
#else /* test normally */
|
||||
# define test_enabled 1
|
||||
#endif
|
||||
#if test_enabled
|
||||
${BODY}
|
||||
#else
|
||||
int main(int argc, char *argv[]) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
||||
#endif" ${VAR})
|
||||
endfunction()
|
||||
|
||||
function(check_arm_source_compiles BODY VAR)
|
||||
if(ARGN)
|
||||
message(FATAL_ERROR "Unknown arguments: ${ARGN}")
|
||||
endif()
|
||||
if(APPLE_MULTIARCH AND (SDL_CPU_ARM32 OR SDL_CPU_ARM64))
|
||||
set(test_conditional 1)
|
||||
else()
|
||||
set(test_conditional 0)
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
#if ${test_conditional}
|
||||
# if defined(__arm__) || defined(__aarch64__)
|
||||
# define test_enabled 1
|
||||
# else
|
||||
# define test_enabled 0 /* feign success in Apple multi-arch configs */
|
||||
# endif
|
||||
#else /* test normally */
|
||||
# define test_enabled 1
|
||||
#endif
|
||||
#if test_enabled
|
||||
${BODY}
|
||||
#else
|
||||
int main(int argc, char *argv[]) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
||||
#endif" ${VAR})
|
||||
endfunction()
|
||||
|
@@ -4,15 +4,15 @@ function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS)
|
||||
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
foreach(known_arch IN LISTS known_archs)
|
||||
set(SDL_CPU_${known_arch} "0")
|
||||
set(SDL_CPU_${known_arch} "0" PARENT_SCOPE)
|
||||
endforeach()
|
||||
set(detected_archs)
|
||||
foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES)
|
||||
if(osx_arch STREQUAL "x86_64")
|
||||
set(SDL_CPU_X64 "1")
|
||||
set(SDL_CPU_X64 "1" PARENT_SCOPE)
|
||||
list(APPEND detected_archs "X64")
|
||||
elseif(osx_arch STREQUAL "arm64")
|
||||
set(SDL_CPU_ARM64 "1")
|
||||
set(SDL_CPU_ARM64 "1" PARENT_SCOPE)
|
||||
list(APPEND detected_archs "ARM64")
|
||||
endif()
|
||||
endforeach()
|
||||
|
@@ -49,7 +49,7 @@ NSApplicationDelegate implementation:
|
||||
```objc
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if (SDL_GetEventState(SDL_EVENT_QUIT) == SDL_ENABLE) {
|
||||
if (SDL_EventEnabled(SDL_EVENT_QUIT)) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = SDL_EVENT_QUIT;
|
||||
@@ -61,7 +61,7 @@ NSApplicationDelegate implementation:
|
||||
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
if (SDL_GetEventState(SDL_EVENT_DROP_FILE) == SDL_ENABLE) {
|
||||
if (SDL_EventEnabled(SDL_EVENT_DROP_FILE)) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = SDL_EVENT_DROP_FILE;
|
||||
|
@@ -11,7 +11,7 @@
|
||||
- [macOS](README-macos.md)
|
||||
- [NetBSD](README-bsd.md)
|
||||
- [Nintendo Switch](README-switch.md)
|
||||
- [Nintendo 3DS](README-3ds.md)
|
||||
- [Nintendo 3DS](README-n3ds.md)
|
||||
- [OpenBSD](README-bsd.md)
|
||||
- [PlayStation 2](README-ps2.md)
|
||||
- [PlayStation 4](README-ps4.md)
|
||||
|
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main include header for the SDL library, version 3.2.14
|
||||
* Main include header for the SDL library, version 3.2.24
|
||||
*
|
||||
* It is almost always best to include just this one header instead of
|
||||
* picking out individual headers included here. There are exceptions to
|
||||
|
@@ -126,7 +126,7 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1310
|
||||
#elif defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1310)
|
||||
/* Don't include intrin.h here because it contains C++ code */
|
||||
extern void __cdecl __debugbreak(void);
|
||||
#define SDL_TriggerBreakpoint() __debugbreak()
|
||||
@@ -362,7 +362,7 @@ extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *
|
||||
#define SDL_enabled_assert(condition) \
|
||||
do { \
|
||||
while ( !(condition) ) { \
|
||||
static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \
|
||||
static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \
|
||||
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
|
||||
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
|
||||
continue; /* go again. */ \
|
||||
|
@@ -942,7 +942,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid);
|
||||
* Binding a stream to a device will set its output format for playback
|
||||
* devices, and its input format for recording devices, so they match the
|
||||
* device's settings. The caller is welcome to change the other end of the
|
||||
* stream's format at any time with SDL_SetAudioStreamFormat().
|
||||
* stream's format at any time with SDL_SetAudioStreamFormat(). If the other
|
||||
* end of the stream's format has never been set (the audio stream was created
|
||||
* with a NULL audio spec), this function will set it to match the device
|
||||
* end's format.
|
||||
*
|
||||
* \param devid an audio device to bind a stream to.
|
||||
* \param streams an array of audio streams to bind.
|
||||
@@ -1021,7 +1024,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream);
|
||||
/**
|
||||
* Query an audio stream for its currently-bound device.
|
||||
*
|
||||
* This reports the audio device that an audio stream is currently bound to.
|
||||
* This reports the logical audio device that an audio stream is currently bound to.
|
||||
*
|
||||
* If not bound, or invalid, this returns zero, which is not a valid device
|
||||
* ID.
|
||||
|
@@ -119,7 +119,7 @@ typedef struct SDL_CameraSpec
|
||||
int width; /**< Frame width */
|
||||
int height; /**< Frame height */
|
||||
int framerate_numerator; /**< Frame rate numerator ((num / denom) == FPS, (denom / num) == duration in seconds) */
|
||||
int framerate_denominator; /**< Frame rate demoninator ((num / denom) == FPS, (denom / num) == duration in seconds) */
|
||||
int framerate_denominator; /**< Frame rate denominator ((num / denom) == FPS, (denom / num) == duration in seconds) */
|
||||
} SDL_CameraSpec;
|
||||
|
||||
/**
|
||||
|
@@ -106,7 +106,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text);
|
||||
/**
|
||||
* Get UTF-8 text from the clipboard.
|
||||
*
|
||||
* This functions returns an empty string if there was not enough memory left
|
||||
* This function returns an empty string if there is not enough memory left
|
||||
* for a copy of the clipboard's content.
|
||||
*
|
||||
* \returns the clipboard text on success or an empty string on failure; call
|
||||
@@ -155,7 +155,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text);
|
||||
/**
|
||||
* Get UTF-8 text from the primary selection.
|
||||
*
|
||||
* This functions returns an empty string if there was not enough memory left
|
||||
* This function returns an empty string if there is not enough memory left
|
||||
* for a copy of the primary selection's content.
|
||||
*
|
||||
* \returns the primary selection text on success or an empty string on
|
||||
@@ -194,15 +194,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
|
||||
* clipboard is cleared or new data is set. The clipboard is automatically
|
||||
* cleared in SDL_Quit().
|
||||
*
|
||||
* \param userdata a pointer to provided user data.
|
||||
* \param userdata a pointer to the provided user data.
|
||||
* \param mime_type the requested mime-type.
|
||||
* \param size a pointer filled in with the length of the returned data.
|
||||
* \returns a pointer to the data for the provided mime-type. Returning NULL
|
||||
* or setting length to 0 will cause no data to be sent to the
|
||||
* or setting the length to 0 will cause no data to be sent to the
|
||||
* "receiver". It is up to the receiver to handle this. Essentially
|
||||
* returning no data is more or less undefined behavior and may cause
|
||||
* breakage in receiving applications. The returned data will not be
|
||||
* freed so it needs to be retained and dealt with internally.
|
||||
* freed, so it needs to be retained and dealt with internally.
|
||||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*
|
||||
@@ -211,10 +211,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
|
||||
typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size);
|
||||
|
||||
/**
|
||||
* Callback function that will be called when the clipboard is cleared, or new
|
||||
* Callback function that will be called when the clipboard is cleared, or when new
|
||||
* data is set.
|
||||
*
|
||||
* \param userdata a pointer to provided user data.
|
||||
* \param userdata a pointer to the provided user data.
|
||||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*
|
||||
@@ -231,7 +231,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
|
||||
* respond with the data for the requested mime-type.
|
||||
*
|
||||
* The size of text data does not include any terminator, and the text does
|
||||
* not need to be null terminated (e.g. you can directly copy a portion of a
|
||||
* not need to be null-terminated (e.g., you can directly copy a portion of a
|
||||
* document).
|
||||
*
|
||||
* \param callback a function pointer to the function that provides the
|
||||
@@ -239,7 +239,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
|
||||
* \param cleanup a function pointer to the function that cleans up the
|
||||
* clipboard data.
|
||||
* \param userdata an opaque pointer that will be forwarded to the callbacks.
|
||||
* \param mime_types a list of mime-types that are being offered.
|
||||
* \param mime_types a list of mime-types that are being offered. SDL copies the given list.
|
||||
* \param num_mime_types the number of mime-types in the mime_types list.
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
@@ -269,10 +269,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void);
|
||||
|
||||
/**
|
||||
* Get the data from clipboard for a given mime type.
|
||||
* Get the data from the clipboard for a given mime type.
|
||||
*
|
||||
* The size of text data does not include the terminator, but the text is
|
||||
* guaranteed to be null terminated.
|
||||
* guaranteed to be null-terminated.
|
||||
*
|
||||
* \param mime_type the mime type to read from the clipboard.
|
||||
* \param size a pointer filled in with the length of the returned data.
|
||||
@@ -292,8 +292,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, s
|
||||
/**
|
||||
* Query whether there is data in the clipboard for the provided mime type.
|
||||
*
|
||||
* \param mime_type the mime type to check for data for.
|
||||
* \returns true if there exists data in clipboard for the provided mime type,
|
||||
* \param mime_type the mime type to check for data.
|
||||
* \returns true if data exists in the clipboard for the provided mime type,
|
||||
* false if it does not.
|
||||
*
|
||||
* \threadsafety This function should only be called on the main thread.
|
||||
@@ -310,7 +310,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type);
|
||||
*
|
||||
* \param num_mime_types a pointer filled with the number of mime types, may
|
||||
* be NULL.
|
||||
* \returns a null terminated array of strings with mime types, or NULL on
|
||||
* \returns a null-terminated array of strings with mime types, or NULL on
|
||||
* failure; call SDL_GetError() for more information. This should be
|
||||
* freed with SDL_free() when it is no longer needed.
|
||||
*
|
||||
|
@@ -46,7 +46,7 @@
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
|
||||
so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__) && !SDL_HAS_BUILTIN(_m_prefetch)
|
||||
#ifndef __PRFCHWINTRIN_H
|
||||
#define __PRFCHWINTRIN_H
|
||||
static __inline__ void __attribute__((__always_inline__, __nodebug__))
|
||||
@@ -128,7 +128,7 @@ _m_prefetch(void *__P)
|
||||
* \sa SDL_BIG_ENDIAN
|
||||
*/
|
||||
#define SDL_BYTEORDER SDL_LIL_ENDIAN___or_maybe___SDL_BIG_ENDIAN
|
||||
#elif defined(SDL_PLATFORM_LINUX)
|
||||
#elif defined(SDL_PLATFORM_LINUX) || defined(__GLIBC__)
|
||||
#include <endian.h>
|
||||
#define SDL_BYTEORDER __BYTE_ORDER
|
||||
#elif defined(SDL_PLATFORM_SOLARIS)
|
||||
@@ -486,7 +486,7 @@ SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return x_but_byteswapped; }
|
||||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*/
|
||||
SDL_FORCE_INLINE Uint32 SDL_Swap64(Uint64 x) { return x_but_byteswapped; }
|
||||
SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) { return x_but_byteswapped; }
|
||||
|
||||
/**
|
||||
* Swap a 16-bit value from littleendian to native byte order.
|
||||
|
@@ -224,8 +224,8 @@
|
||||
* - `drawIndirectFirstInstance`
|
||||
*
|
||||
* **D3D12:** Supported on Windows 10 or newer, Xbox One (GDK), and Xbox
|
||||
* Series X|S (GDK). Requires a GPU that supports DirectX 12 Feature Level
|
||||
* 11_1.
|
||||
* Series X|S (GDK). Requires a GPU that supports DirectX 12 Feature Level 11_0 and
|
||||
* Resource Binding Tier 2 or above.
|
||||
*
|
||||
* **Metal:** Supported on macOS 10.14+ and iOS/tvOS 13.0+. Hardware
|
||||
* requirements vary by operating system:
|
||||
@@ -1091,7 +1091,7 @@ typedef enum SDL_GPUCompareOp
|
||||
SDL_GPU_COMPAREOP_LESS_OR_EQUAL, /**< The comparison evaluates reference <= test. */
|
||||
SDL_GPU_COMPAREOP_GREATER, /**< The comparison evaluates reference > test. */
|
||||
SDL_GPU_COMPAREOP_NOT_EQUAL, /**< The comparison evaluates reference != test. */
|
||||
SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, /**< The comparison evalutes reference >= test. */
|
||||
SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, /**< The comparison evaluates reference >= test. */
|
||||
SDL_GPU_COMPAREOP_ALWAYS /**< The comparison always evaluates true. */
|
||||
} SDL_GPUCompareOp;
|
||||
|
||||
@@ -1549,7 +1549,7 @@ typedef struct SDL_GPUSamplerCreateInfo
|
||||
typedef struct SDL_GPUVertexBufferDescription
|
||||
{
|
||||
Uint32 slot; /**< The binding slot of the vertex buffer. */
|
||||
Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */
|
||||
Uint32 pitch; /**< The size of a single element + the offset between elements. */
|
||||
SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */
|
||||
Uint32 instance_step_rate; /**< Reserved for future use. Must be set to 0. */
|
||||
} SDL_GPUVertexBufferDescription;
|
||||
@@ -2648,7 +2648,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_InsertGPUDebugLabel(
|
||||
const char *text);
|
||||
|
||||
/**
|
||||
* Begins a debug group with an arbitary name.
|
||||
* Begins a debug group with an arbitrary name.
|
||||
*
|
||||
* Used for denoting groups of calls when viewing the command buffer
|
||||
* callstream in a graphics debugging tool.
|
||||
|
@@ -595,7 +595,7 @@ extern "C" {
|
||||
* A variable that limits what CPU features are available.
|
||||
*
|
||||
* By default, SDL marks all features the current CPU supports as available.
|
||||
* This hint allows to limit these to a subset.
|
||||
* This hint allows the enabled features to be limited to a subset.
|
||||
*
|
||||
* When the hint is unset, or empty, SDL will enable all detected CPU
|
||||
* features.
|
||||
@@ -2026,8 +2026,8 @@ extern "C" {
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": RAWINPUT drivers are not used.
|
||||
* - "1": RAWINPUT drivers are used. (default)
|
||||
* - "0": RAWINPUT drivers are not used. (default)
|
||||
* - "1": RAWINPUT drivers are used.
|
||||
*
|
||||
* This hint should be set before SDL is initialized.
|
||||
*
|
||||
@@ -2126,8 +2126,8 @@ extern "C" {
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": WGI is not used.
|
||||
* - "1": WGI is used. (default)
|
||||
* - "0": WGI is not used. (default)
|
||||
* - "1": WGI is used.
|
||||
*
|
||||
* This hint should be set before SDL is initialized.
|
||||
*
|
||||
|
@@ -79,7 +79,7 @@ typedef Uint32 SDL_InitFlags;
|
||||
|
||||
#define SDL_INIT_AUDIO 0x00000010u /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */
|
||||
#define SDL_INIT_VIDEO 0x00000020u /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread */
|
||||
#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD */
|
||||
#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS` */
|
||||
#define SDL_INIT_HAPTIC 0x00001000u
|
||||
#define SDL_INIT_GAMEPAD 0x00002000u /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */
|
||||
#define SDL_INIT_EVENTS 0x00004000u
|
||||
|
@@ -517,7 +517,7 @@ typedef enum SDL_PackedLayout
|
||||
* ABGR32, define a platform-independent encoding into bytes in the order
|
||||
* specified. For example, in RGB24 data, each pixel is encoded in 3 bytes
|
||||
* (red, green, blue) in that order, and in ABGR32 data, each pixel is
|
||||
* encoded in 4 bytes alpha, blue, green, red) in that order. Use these
|
||||
* encoded in 4 bytes (alpha, blue, green, red) in that order. Use these
|
||||
* names if the property of a format that is important to you is the order
|
||||
* of the bytes in memory or on disk.
|
||||
* - Names with a bit count per component, such as ARGB8888 and XRGB1555, are
|
||||
|
@@ -2612,7 +2612,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderDebugText(SDL_Renderer *renderer, flo
|
||||
* Draw debug text to an SDL_Renderer.
|
||||
*
|
||||
* This function will render a printf()-style format string to a renderer.
|
||||
* Note that this is a convinence function for debugging, with severe
|
||||
* Note that this is a convenience function for debugging, with severe
|
||||
* limitations, and is not intended to be used for production apps and games.
|
||||
*
|
||||
* For the full list of limitations and other useful information, see
|
||||
|
@@ -208,7 +208,7 @@ typedef enum SDL_Scancode
|
||||
|
||||
SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
|
||||
* keyboards have over ANSI ones,
|
||||
* located between left shift and Y.
|
||||
* located between left shift and Z.
|
||||
* Produces GRAVE ACCENT and TILDE in a
|
||||
* US or UK Mac layout, REVERSE SOLIDUS
|
||||
* (backslash) and VERTICAL LINE in a
|
||||
|
@@ -138,7 +138,8 @@ typedef enum SDL_SensorType
|
||||
SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */
|
||||
SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */
|
||||
SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */
|
||||
SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */
|
||||
SDL_SENSOR_GYRO_R, /**< Gyroscope for right Joy-Con controller */
|
||||
SDL_SENSOR_COUNT
|
||||
} SDL_SensorType;
|
||||
|
||||
|
||||
|
@@ -3426,7 +3426,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strnlen(const char *str, size_t bytes
|
||||
* Convert an integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3454,7 +3454,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_itoa(int value, char *str, int radix);
|
||||
* Convert an unsigned integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3482,7 +3482,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_uitoa(unsigned int value, char *str, int
|
||||
* Convert a long integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3510,7 +3510,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ltoa(long value, char *str, int radix);
|
||||
* Convert an unsigned long integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3540,7 +3540,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *str, int
|
||||
* Convert a long long integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3568,7 +3568,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_lltoa(long long value, char *str, int rad
|
||||
* Convert an unsigned long long integer into a string.
|
||||
*
|
||||
* This requires a radix to specified for string format. Specifying 10
|
||||
* produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2
|
||||
* produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2
|
||||
* to 36.
|
||||
*
|
||||
* Note that this function will overflow a buffer if `str` is not large enough
|
||||
@@ -3923,7 +3923,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen);
|
||||
|
||||
/**
|
||||
* Searches a string for the first occurence of any character contained in a
|
||||
* Searches a string for the first occurrence of any character contained in a
|
||||
* breakset, and returns a pointer from the string to that character.
|
||||
*
|
||||
* \param str The null-terminated string to be searched. Must not be NULL, and
|
||||
@@ -3931,7 +3931,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *st
|
||||
* \param breakset A null-terminated string containing the list of characters
|
||||
* to look for. Must not be NULL, and must not overlap with
|
||||
* `str`.
|
||||
* \returns A pointer to the location, in str, of the first occurence of a
|
||||
* \returns A pointer to the location, in str, of the first occurrence of a
|
||||
* character present in the breakset, or NULL if none is found.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
@@ -4656,7 +4656,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_atanf(float x);
|
||||
*
|
||||
* Domain: `-INF <= x <= INF`, `-INF <= y <= INF`
|
||||
*
|
||||
* Range: `-Pi/2 <= y <= Pi/2`
|
||||
* Range: `-Pi <= y <= Pi`
|
||||
*
|
||||
* This function operates on double-precision floating point values, use
|
||||
* SDL_atan2f for single-precision floats.
|
||||
@@ -4692,7 +4692,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_atan2(double y, double x);
|
||||
*
|
||||
* Domain: `-INF <= x <= INF`, `-INF <= y <= INF`
|
||||
*
|
||||
* Range: `-Pi/2 <= y <= Pi/2`
|
||||
* Range: `-Pi <= y <= Pi`
|
||||
*
|
||||
* This function operates on single-precision floating point values, use
|
||||
* SDL_atan2 for double-precision floats.
|
||||
@@ -5821,7 +5821,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
|
||||
* This function converts text between encodings, reading from and writing to
|
||||
* a buffer.
|
||||
*
|
||||
* It returns the number of succesful conversions on success. On error,
|
||||
* It returns the number of successful conversions on success. On error,
|
||||
* SDL_ICONV_E2BIG is returned when the output buffer is too small, or
|
||||
* SDL_ICONV_EILSEQ is returned when an invalid input sequence is encountered,
|
||||
* or SDL_ICONV_EINVAL is returned when an incomplete input sequence is
|
||||
|
@@ -1279,10 +1279,11 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src
|
||||
*
|
||||
* \param src the SDL_Surface structure to be copied from.
|
||||
* \param srcrect the SDL_Rect structure representing the rectangle to be
|
||||
* copied, may not be NULL.
|
||||
* copied, or NULL to copy the entire surface.
|
||||
* \param dst the SDL_Surface structure that is the blit target.
|
||||
* \param dstrect the SDL_Rect structure representing the target rectangle in
|
||||
* the destination surface, may not be NULL.
|
||||
* the destination surface, or NULL to fill the entire
|
||||
* destination surface.
|
||||
* \param scaleMode the SDL_ScaleMode to be used.
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
|
@@ -62,7 +62,7 @@ extern "C" {
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_MICRO_VERSION 14
|
||||
#define SDL_MICRO_VERSION 24
|
||||
|
||||
/**
|
||||
* This macro turns the version numbers into a numeric value.
|
||||
|
@@ -1167,6 +1167,15 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int
|
||||
* Popup windows implicitly do not have a border/decorations and do not appear
|
||||
* on the taskbar/dock or in lists of windows such as alt-tab menus.
|
||||
*
|
||||
* By default, popup window positions will automatically be constrained to keep
|
||||
* the entire window within display bounds. This can be overridden with the
|
||||
* `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN` property.
|
||||
*
|
||||
* By default, popup menus will automatically grab keyboard focus from the parent
|
||||
* when shown. This behavior can be overridden by setting the `SDL_WINDOW_NOT_FOCUSABLE`
|
||||
* flag, setting the `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN` property to false, or
|
||||
* toggling it after creation via the `SDL_SetWindowFocusable()` function.
|
||||
*
|
||||
* If a parent window is hidden or destroyed, any child popup windows will be
|
||||
* recursively hidden or destroyed as well. Child popup windows not explicitly
|
||||
* hidden will be restored when the parent is shown.
|
||||
@@ -1207,6 +1216,9 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
|
||||
* be always on top
|
||||
* - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no
|
||||
* window decoration
|
||||
* - `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN`: true if the "tooltip" and
|
||||
* "menu" window types should be automatically constrained to be entirely within
|
||||
* display bounds (default), false if no constraints on the position are desired.
|
||||
* - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the
|
||||
* window will be used with an externally managed graphics context.
|
||||
* - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should
|
||||
@@ -1321,6 +1333,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop
|
||||
|
||||
#define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top"
|
||||
#define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless"
|
||||
#define SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN "SDL.window.create.constrain_popup"
|
||||
#define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable"
|
||||
#define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context"
|
||||
#define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags"
|
||||
@@ -1460,7 +1473,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window)
|
||||
* - `SDL_PROP_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)`
|
||||
* NSWindow associated with the window
|
||||
* - `SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag
|
||||
* assocated with metal views on the window
|
||||
* associated with metal views on the window
|
||||
*
|
||||
* On OpenVR:
|
||||
*
|
||||
|
@@ -51,14 +51,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Avoid including vulkan.h, don't define VkInstance if it's already included */
|
||||
#ifdef VULKAN_H_
|
||||
/* Avoid including vulkan_core.h, don't define VkInstance if it's already included */
|
||||
#ifdef VULKAN_CORE_H_
|
||||
#define NO_SDL_VULKAN_TYPEDEFS
|
||||
#endif
|
||||
#ifndef NO_SDL_VULKAN_TYPEDEFS
|
||||
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
|
||||
|
||||
#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
|
||||
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64)
|
||||
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
|
||||
#else
|
||||
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
|
||||
|
@@ -174,6 +174,7 @@
|
||||
#cmakedefine HAVE_MEMFD_CREATE 1
|
||||
#cmakedefine HAVE_POSIX_FALLOCATE 1
|
||||
#cmakedefine HAVE_SIGACTION 1
|
||||
#cmakedefine HAVE_SIGTIMEDWAIT 1
|
||||
#cmakedefine HAVE_SA_SIGACTION 1
|
||||
#cmakedefine HAVE_ST_MTIM 1
|
||||
#cmakedefine HAVE_SETJMP 1
|
||||
|
@@ -111,6 +111,9 @@ typedef unsigned int uintptr_t;
|
||||
# define SDL_DISABLE_AVX 1
|
||||
#endif
|
||||
|
||||
#define HAVE_STDARG_H 1
|
||||
#define HAVE_STDDEF_H 1
|
||||
|
||||
/* This can be disabled to avoid C runtime dependencies and manifest requirements */
|
||||
#ifndef HAVE_LIBC
|
||||
#define HAVE_LIBC 1
|
||||
@@ -122,8 +125,6 @@ typedef unsigned int uintptr_t;
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_MATH_H 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_STDARG_H 1
|
||||
#define HAVE_STDDEF_H 1
|
||||
#define HAVE_STDIO_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
@@ -153,7 +154,6 @@ typedef unsigned int uintptr_t;
|
||||
#define HAVE_STRCMP 1
|
||||
#define HAVE_STRNCMP 1
|
||||
#define HAVE_STRPBRK 1
|
||||
#define HAVE_VSSCANF 1
|
||||
#define HAVE_VSNPRINTF 1
|
||||
#define HAVE_ACOS 1
|
||||
#define HAVE_ASIN 1
|
||||
@@ -212,9 +212,6 @@ typedef unsigned int uintptr_t;
|
||||
#define HAVE__FSEEKI64 1
|
||||
#endif
|
||||
#endif /* _MSC_VER */
|
||||
#else
|
||||
#define HAVE_STDARG_H 1
|
||||
#define HAVE_STDDEF_H 1
|
||||
#endif
|
||||
|
||||
/* Enable various audio drivers */
|
||||
|
@@ -65,7 +65,7 @@
|
||||
|
||||
// Initialization/Cleanup routines
|
||||
#include "timer/SDL_timer_c.h"
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
extern bool SDL_HelperWindowCreate(void);
|
||||
extern void SDL_HelperWindowDestroy(void);
|
||||
#endif
|
||||
@@ -317,7 +317,7 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
||||
SDL_DBus_Init();
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) {
|
||||
if (!SDL_HelperWindowCreate()) {
|
||||
goto quit_and_error;
|
||||
@@ -653,7 +653,7 @@ void SDL_Quit(void)
|
||||
SDL_bInMainQuit = true;
|
||||
|
||||
// Quit all subsystems
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
SDL_HelperWindowDestroy();
|
||||
#endif
|
||||
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
||||
|
@@ -265,6 +265,12 @@ extern "C" {
|
||||
#include "SDL_utils_c.h"
|
||||
#include "SDL_hashtable.h"
|
||||
|
||||
#define PUSH_SDL_ERROR() \
|
||||
{ char *_error = SDL_strdup(SDL_GetError());
|
||||
|
||||
#define POP_SDL_ERROR() \
|
||||
SDL_SetError("%s", _error); SDL_free(_error); }
|
||||
|
||||
// Do any initialization that needs to happen before threads are started
|
||||
extern void SDL_InitMainThread(void);
|
||||
|
||||
|
@@ -1153,7 +1153,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
|
||||
// We should have updated this elsewhere if the format changed!
|
||||
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, NULL, NULL));
|
||||
|
||||
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
|
||||
|
||||
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
|
||||
|
||||
if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow.
|
||||
failed = true;
|
||||
SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die.
|
||||
@@ -1195,6 +1198,8 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
|
||||
// We should have updated this elsewhere if the format changed!
|
||||
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, NULL, NULL));
|
||||
|
||||
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
|
||||
|
||||
/* this will hold a lock on `stream` while getting. We don't explicitly lock the streams
|
||||
for iterating here because the binding linked list can only change while the device lock is held.
|
||||
(we _do_ lock the stream during binding/unbinding to make sure that two threads can't try to bind
|
||||
@@ -1330,6 +1335,7 @@ bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
|
||||
SDL_assert(stream->src_spec.format == ((logdev->postmix || (logdev->gain != 1.0f)) ? SDL_AUDIO_F32 : device->spec.format));
|
||||
SDL_assert(stream->src_spec.channels == device->spec.channels);
|
||||
SDL_assert(stream->src_spec.freq == device->spec.freq);
|
||||
SDL_assert(stream->dst_spec.format != SDL_AUDIO_UNKNOWN);
|
||||
|
||||
void *final_buf = output_buffer;
|
||||
|
||||
@@ -1391,6 +1397,7 @@ static int SDLCALL RecordingAudioThread(void *devicep) // thread entry point
|
||||
typedef struct CountAudioDevicesData
|
||||
{
|
||||
int devs_seen;
|
||||
int devs_skipped;
|
||||
const int num_devices;
|
||||
SDL_AudioDeviceID *result;
|
||||
const bool recording;
|
||||
@@ -1406,8 +1413,14 @@ static bool SDLCALL CountAudioDevices(void *userdata, const SDL_HashTable *table
|
||||
const bool isphysical = !!(devid & (1<<1));
|
||||
if (isphysical && (devid_recording == data->recording)) {
|
||||
SDL_assert(data->devs_seen < data->num_devices);
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) value; // this is normally risky, but we hold the device_hash_lock here.
|
||||
const bool zombie = SDL_GetAtomicInt(&device->zombie) != 0;
|
||||
if (zombie) {
|
||||
data->devs_skipped++;
|
||||
} else {
|
||||
data->result[data->devs_seen++] = devid;
|
||||
}
|
||||
}
|
||||
return true; // keep iterating.
|
||||
}
|
||||
|
||||
@@ -1422,10 +1435,11 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, bool recording)
|
||||
num_devices = SDL_GetAtomicInt(recording ? ¤t_audio.recording_device_count : ¤t_audio.playback_device_count);
|
||||
result = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID));
|
||||
if (result) {
|
||||
CountAudioDevicesData data = { 0, num_devices, result, recording };
|
||||
CountAudioDevicesData data = { 0, 0, num_devices, result, recording };
|
||||
SDL_IterateHashTable(current_audio.device_hash, CountAudioDevices, &data);
|
||||
SDL_assert(data.devs_seen == num_devices);
|
||||
result[data.devs_seen] = 0; // null-terminated.
|
||||
SDL_assert((data.devs_seen + data.devs_skipped) == num_devices);
|
||||
num_devices = data.devs_seen; // might be less if we skipped any.
|
||||
result[num_devices] = 0; // null-terminated.
|
||||
}
|
||||
}
|
||||
SDL_UnlockRWLock(current_audio.device_hash_lock);
|
||||
@@ -1567,8 +1581,10 @@ int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
|
||||
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
|
||||
if (device) {
|
||||
channels = device->spec.channels;
|
||||
if (channels > 0 && device->chmap) {
|
||||
result = SDL_ChannelMapDup(device->chmap, channels);
|
||||
}
|
||||
}
|
||||
ReleaseAudioDevice(device);
|
||||
|
||||
if (count) {
|
||||
@@ -1743,13 +1759,18 @@ static bool OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
|
||||
SDL_copyp(&spec, inspec ? inspec : &device->default_spec);
|
||||
PrepareAudioFormat(device->recording, &spec);
|
||||
|
||||
/* We allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents
|
||||
something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later.
|
||||
(or some VoIP library that opens for mono output ruining your surround-sound game because it got there first).
|
||||
/* We impose a simple minimum on device formats. This prevents something low quality, like an old game using S8/8000Hz audio,
|
||||
from ruining a music thing playing at CD quality that tries to open later, or some VoIP library that opens for mono output
|
||||
ruining your surround-sound game because it got there first.
|
||||
These are just requests! The backend may change any of these values during OpenDevice method! */
|
||||
device->spec.format = (SDL_AUDIO_BITSIZE(device->default_spec.format) >= SDL_AUDIO_BITSIZE(spec.format)) ? device->default_spec.format : spec.format;
|
||||
device->spec.freq = SDL_max(device->default_spec.freq, spec.freq);
|
||||
device->spec.channels = SDL_max(device->default_spec.channels, spec.channels);
|
||||
|
||||
const SDL_AudioFormat minimum_format = device->recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT;
|
||||
const int minimum_channels = device->recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS;
|
||||
const int minimum_freq = device->recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY;
|
||||
|
||||
device->spec.format = (SDL_AUDIO_BITSIZE(minimum_format) >= SDL_AUDIO_BITSIZE(spec.format)) ? minimum_format : spec.format;
|
||||
device->spec.channels = SDL_max(minimum_channels, spec.channels);
|
||||
device->spec.freq = SDL_max(minimum_freq, spec.freq);
|
||||
device->sample_frames = SDL_GetDefaultSampleFramesFromFreq(device->spec.freq);
|
||||
SDL_UpdatedAudioDeviceFormat(device); // start this off sane.
|
||||
|
||||
@@ -1960,10 +1981,6 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
|
||||
} else if (logdev->simplified) {
|
||||
result = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream");
|
||||
} else {
|
||||
|
||||
// !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet.
|
||||
// !!! FIXME: Actually, why do we allow there to be an invalid format, again?
|
||||
|
||||
// make sure start of list is sane.
|
||||
SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL));
|
||||
|
||||
@@ -1998,9 +2015,17 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
|
||||
|
||||
if (result) {
|
||||
// Now that everything is verified, chain everything together.
|
||||
const bool recording = device->recording;
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
SDL_AudioStream *stream = streams[i];
|
||||
if (stream) { // shouldn't be NULL, but just in case...
|
||||
// if the stream never had its non-device-end format set, just set it to the device end's format.
|
||||
if (recording && (stream->dst_spec.format == SDL_AUDIO_UNKNOWN)) {
|
||||
SDL_copyp(&stream->dst_spec, &device->spec);
|
||||
} else if (!recording && (stream->src_spec.format == SDL_AUDIO_UNKNOWN)) {
|
||||
SDL_copyp(&stream->src_spec, &device->spec);
|
||||
}
|
||||
|
||||
stream->bound_device = logdev;
|
||||
stream->prev_binding = NULL;
|
||||
stream->next_binding = logdev->bound_streams;
|
||||
|
@@ -537,8 +537,10 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const U
|
||||
// behavior. However, the compiler support for this pragma is bad.
|
||||
#if defined(__clang__)
|
||||
#if __clang_major__ >= 12
|
||||
#if defined(__aarch64__)
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma fenv_access (on)
|
||||
#elif defined(__GNUC__)
|
||||
@@ -814,8 +816,10 @@ static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samp
|
||||
|
||||
#if defined(__clang__)
|
||||
#if __clang_major__ >= 12
|
||||
#if defined(__aarch64__)
|
||||
#pragma STDC FENV_ACCESS DEFAULT
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma fenv_access (off)
|
||||
#elif defined(__GNUC__)
|
||||
|
@@ -1775,6 +1775,7 @@ static bool WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uin
|
||||
int result;
|
||||
Uint32 chunkcount = 0;
|
||||
Uint32 chunkcountlimit = 10000;
|
||||
const Sint64 flen = SDL_GetIOSize(src); // this might be -1 if the IOStream can't determine the total size.
|
||||
const char *hint;
|
||||
Sint64 RIFFstart, RIFFend, lastchunkpos;
|
||||
bool RIFFlengthknown = false;
|
||||
@@ -1883,6 +1884,14 @@ static bool WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uin
|
||||
fmtchunk = *chunk;
|
||||
}
|
||||
} else if (chunk->fourcc == DATA) {
|
||||
/* If the data chunk is bigger than the file, it might be corrupt
|
||||
or the file is truncated. Try to recover by clamping the file
|
||||
size. This also means a malicious file can't allocate 4 gigabytes
|
||||
for the chunks without actually supplying a 4 gigabyte file. */
|
||||
if ((flen > 0) && ((chunk->position + chunk->length) > flen)) {
|
||||
chunk->length = (Uint32) (flen - chunk->position);
|
||||
}
|
||||
|
||||
/* Only use the first data chunk. Handling the wavl list madness
|
||||
* may require a different approach.
|
||||
*/
|
||||
@@ -2114,8 +2123,8 @@ bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8
|
||||
result = WaveLoad(src, &file, spec, audio_buf, audio_len);
|
||||
if (!result) {
|
||||
SDL_free(*audio_buf);
|
||||
audio_buf = NULL;
|
||||
audio_len = 0;
|
||||
*audio_buf = NULL;
|
||||
*audio_len = 0;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
@@ -1156,7 +1156,7 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
#if SDL_ALSA_DEBUG
|
||||
snd_pcm_uframes_t bufsize;
|
||||
ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO,
|
||||
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
|
||||
cfg_ctx.persize, cfg_ctx.periods, bufsize);
|
||||
#endif
|
||||
|
@@ -420,7 +420,8 @@ static bool UpdateAudioSession(SDL_AudioDevice *device, bool open, bool allow_pl
|
||||
|
||||
hint = SDL_GetHint(SDL_HINT_AUDIO_CATEGORY);
|
||||
if (hint) {
|
||||
if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0) {
|
||||
if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0 ||
|
||||
SDL_strcasecmp(hint, "ambient") == 0) {
|
||||
category = AVAudioSessionCategoryAmbient;
|
||||
} else if (SDL_strcasecmp(hint, "AVAudioSessionCategorySoloAmbient") == 0) {
|
||||
category = AVAudioSessionCategorySoloAmbient;
|
||||
|
@@ -206,7 +206,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
|
||||
{
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
|
||||
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording, SDL_AUDIO_UNKNOWN);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@@ -189,7 +189,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
|
||||
// limit to native freq
|
||||
device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });
|
||||
device->spec.freq = MAIN_THREAD_EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });
|
||||
device->sample_frames = SDL_GetDefaultSampleFramesFromFreq(device->spec.freq) * 2; // double the buffer size, some browsers need more, and we'll just have to live with the latency.
|
||||
|
||||
SDL_UpdatedAudioDeviceFormat(device);
|
||||
|
@@ -426,28 +426,33 @@ static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device)
|
||||
|
||||
static bool OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device)
|
||||
{
|
||||
/* If we want to add floating point audio support (requires API level 21)
|
||||
it can be done as described here:
|
||||
https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point
|
||||
*/
|
||||
/* according to https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android,
|
||||
Android's OpenSL ES only supports Uint8 and _littleendian_ Sint16.
|
||||
(and float32, with an extension we use, below.) */
|
||||
if (SDL_GetAndroidSDKVersion() >= 21) {
|
||||
const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
SDL_AudioFormat test_format;
|
||||
while ((test_format = *(closefmts++)) != 0) {
|
||||
if (SDL_AUDIO_ISSIGNED(test_format)) {
|
||||
switch (test_format) {
|
||||
case SDL_AUDIO_U8:
|
||||
case SDL_AUDIO_S16LE:
|
||||
case SDL_AUDIO_F32:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!test_format) {
|
||||
// Didn't find a compatible format :
|
||||
LOGI("No compatible audio format, using signed 16-bit audio");
|
||||
test_format = SDL_AUDIO_S16;
|
||||
LOGI("No compatible audio format, using signed 16-bit LE audio");
|
||||
test_format = SDL_AUDIO_S16LE;
|
||||
}
|
||||
device->spec.format = test_format;
|
||||
} else {
|
||||
// Just go with signed 16-bit audio as it's the most compatible
|
||||
device->spec.format = SDL_AUDIO_S16;
|
||||
device->spec.format = SDL_AUDIO_S16LE;
|
||||
}
|
||||
|
||||
// Update the fragment size as size in bytes
|
||||
|
@@ -114,7 +114,7 @@ static bool PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
|
||||
} else {
|
||||
rc = sceAudioOutputPannedBlocking(device->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, (void *) buffer);
|
||||
}
|
||||
return (rc == 0);
|
||||
return (rc >= 0);
|
||||
}
|
||||
|
||||
static bool PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
|
@@ -672,7 +672,8 @@ static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
paspec.rate = device->spec.freq;
|
||||
|
||||
// Reduced prebuffering compared to the defaults.
|
||||
paattr.fragsize = device->buffer_size; // despite the name, this is only used for recording devices, according to PulseAudio docs!
|
||||
|
||||
paattr.fragsize = device->buffer_size * 2; // despite the name, this is only used for recording devices, according to PulseAudio docs! (times 2 because we want _more_ than our buffer size sent from the server at a time, which helps some drivers).
|
||||
paattr.tlength = device->buffer_size;
|
||||
paattr.prebuf = -1;
|
||||
paattr.maxlength = -1;
|
||||
|
@@ -337,7 +337,7 @@ typedef struct
|
||||
static bool mgmtthrtask_DetectDevices(void *userdata)
|
||||
{
|
||||
mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata;
|
||||
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording);
|
||||
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording, SDL_AUDIO_F32);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -814,7 +814,7 @@ static void ANDROIDCAMERA_Deinitialize(void)
|
||||
static bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl)
|
||||
{
|
||||
// !!! FIXME: slide this off into a subroutine
|
||||
// system libraries are in android-24 and later; we currently target android-16 and later, so check if they exist at runtime.
|
||||
// system libraries are in android-24 and later; we currently target android-21 and later, so check if they exist at runtime.
|
||||
void *libcamera2 = dlopen("libcamera2ndk.so", RTLD_NOW | RTLD_LOCAL);
|
||||
if (!libcamera2) {
|
||||
SDL_Log("CAMERA: libcamera2ndk.so can't be loaded: %s", dlerror());
|
||||
|
@@ -61,7 +61,7 @@ static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, S
|
||||
|
||||
SDL3.camera.ctx2d.drawImage(SDL3.camera.video, 0, 0, w, h);
|
||||
const imgrgba = SDL3.camera.ctx2d.getImageData(0, 0, w, h).data;
|
||||
Module.HEAPU8.set(imgrgba, rgba);
|
||||
HEAPU8.set(imgrgba, rgba);
|
||||
|
||||
return 1;
|
||||
}, device->actual_spec.width, device->actual_spec.height, rgba);
|
||||
|
@@ -371,6 +371,7 @@ static jmethodID midShowTextInput;
|
||||
static jmethodID midSupportsRelativeMouse;
|
||||
static jmethodID midOpenFileDescriptor;
|
||||
static jmethodID midShowFileDialog;
|
||||
static jmethodID midGetPreferredLocales;
|
||||
|
||||
// audio manager
|
||||
static jclass mAudioManagerClass;
|
||||
@@ -660,6 +661,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||
midSupportsRelativeMouse = (*env)->GetStaticMethodID(env, mActivityClass, "supportsRelativeMouse", "()Z");
|
||||
midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I");
|
||||
midShowFileDialog = (*env)->GetStaticMethodID(env, mActivityClass, "showFileDialog", "([Ljava/lang/String;ZZI)Z");
|
||||
midGetPreferredLocales = (*env)->GetStaticMethodID(env, mActivityClass, "getPreferredLocales", "()Ljava/lang/String;");
|
||||
|
||||
if (!midClipboardGetText ||
|
||||
!midClipboardHasText ||
|
||||
@@ -691,7 +693,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||
!midShowTextInput ||
|
||||
!midSupportsRelativeMouse ||
|
||||
!midOpenFileDescriptor ||
|
||||
!midShowFileDialog) {
|
||||
!midShowFileDialog ||
|
||||
!midGetPreferredLocales) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
|
||||
}
|
||||
|
||||
@@ -1077,7 +1080,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)(
|
||||
{
|
||||
const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
|
||||
SDL_AddTouch((SDL_TouchID)touchId, SDL_TOUCH_DEVICE_DIRECT, utfname);
|
||||
SDL_AddTouch(Android_ConvertJavaTouchID(touchId),
|
||||
SDL_TOUCH_DEVICE_DIRECT, utfname);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, utfname);
|
||||
}
|
||||
@@ -2160,7 +2164,7 @@ bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *b
|
||||
mid = (*env)->GetMethodID(env, clazz,
|
||||
"messageboxShowMessageBox", "(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
|
||||
*buttonID = (*env)->CallIntMethod(env, context, mid,
|
||||
messageboxdata->flags,
|
||||
(jint)messageboxdata->flags,
|
||||
title,
|
||||
message,
|
||||
button_flags,
|
||||
@@ -2414,7 +2418,7 @@ const char *SDL_GetAndroidCachePath(void)
|
||||
// fileObj = context.getExternalFilesDir();
|
||||
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
|
||||
"getCacheDir", "()Ljava/io/File;");
|
||||
fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
|
||||
fileObject = (*env)->CallObjectMethod(env, context, mid);
|
||||
if (!fileObject) {
|
||||
SDL_SetError("Couldn't get cache directory");
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
@@ -2585,65 +2589,22 @@ bool Android_JNI_ShowToast(const char *message, int duration, int gravity, int x
|
||||
|
||||
bool Android_JNI_GetLocale(char *buf, size_t buflen)
|
||||
{
|
||||
AConfiguration *cfg;
|
||||
|
||||
SDL_assert(buflen > 6);
|
||||
|
||||
// Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED)
|
||||
Internal_Android_Destroy_AssetManager();
|
||||
|
||||
if (!asset_manager) {
|
||||
Internal_Android_Create_AssetManager();
|
||||
bool result = false;
|
||||
if (buf && buflen > 0) {
|
||||
*buf = '\0';
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
jstring string = (jstring)(*env)->CallStaticObjectMethod(env, mActivityClass, midGetPreferredLocales);
|
||||
if (string) {
|
||||
const char *utf8string = (*env)->GetStringUTFChars(env, string, NULL);
|
||||
if (utf8string) {
|
||||
result = true;
|
||||
SDL_strlcpy(buf, utf8string, buflen);
|
||||
(*env)->ReleaseStringUTFChars(env, string, utf8string);
|
||||
}
|
||||
|
||||
if (!asset_manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cfg = AConfiguration_new();
|
||||
if (!cfg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
char language[2] = {};
|
||||
char country[2] = {};
|
||||
size_t id = 0;
|
||||
|
||||
AConfiguration_fromAssetManager(cfg, asset_manager);
|
||||
AConfiguration_getLanguage(cfg, language);
|
||||
AConfiguration_getCountry(cfg, country);
|
||||
|
||||
// Indonesian is "id" according to ISO 639.2, but on Android is "in" because of Java backwards compatibility
|
||||
if (language[0] == 'i' && language[1] == 'n') {
|
||||
language[1] = 'd';
|
||||
}
|
||||
|
||||
// copy language (not null terminated)
|
||||
if (language[0]) {
|
||||
buf[id++] = language[0];
|
||||
if (language[1]) {
|
||||
buf[id++] = language[1];
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
}
|
||||
}
|
||||
|
||||
buf[id++] = '_';
|
||||
|
||||
// copy country (not null terminated)
|
||||
if (country[0]) {
|
||||
buf[id++] = country[0];
|
||||
if (country[1]) {
|
||||
buf[id++] = country[1];
|
||||
}
|
||||
}
|
||||
|
||||
buf[id++] = '\0';
|
||||
SDL_assert(id <= buflen);
|
||||
}
|
||||
|
||||
AConfiguration_delete(cfg);
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Android_JNI_OpenURL(const char *url)
|
||||
|
@@ -105,7 +105,7 @@ bool GDK_RegisterChangeNotifications(void)
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler");
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
if (_this) {
|
||||
if (constrained) {
|
||||
if (constrained && !((_this->windows) && _this->windows->text_input_active)) {
|
||||
SDL_SetKeyboardFocus(NULL);
|
||||
} else {
|
||||
SDL_SetKeyboardFocus(_this->windows);
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "SDL_fcitx.h"
|
||||
#include "../../video/SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../core/unix/SDL_appid.h"
|
||||
#include "SDL_dbus.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
@@ -53,32 +54,14 @@ typedef struct FcitxClient
|
||||
|
||||
static FcitxClient fcitx_client;
|
||||
|
||||
static char *GetAppName(void)
|
||||
static const char *GetAppName(void)
|
||||
{
|
||||
#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD)
|
||||
char *spot;
|
||||
char procfile[1024];
|
||||
char linkfile[1024];
|
||||
int linksize;
|
||||
|
||||
#ifdef SDL_PLATFORM_LINUX
|
||||
(void)SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid());
|
||||
#elif defined(SDL_PLATFORM_FREEBSD)
|
||||
(void)SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid());
|
||||
#endif
|
||||
linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
spot = SDL_strrchr(linkfile, '/');
|
||||
if (spot) {
|
||||
return SDL_strdup(spot + 1);
|
||||
} else {
|
||||
return SDL_strdup(linkfile);
|
||||
const char *exe_name = SDL_GetExeName();
|
||||
if (exe_name) {
|
||||
return exe_name;
|
||||
}
|
||||
}
|
||||
#endif // SDL_PLATFORM_LINUX || SDL_PLATFORM_FREEBSD
|
||||
|
||||
return SDL_strdup("SDL_App");
|
||||
return "SDL_App";
|
||||
}
|
||||
|
||||
static size_t Fcitx_GetPreeditString(SDL_DBusContext *dbus,
|
||||
@@ -281,7 +264,7 @@ static bool FcitxCreateInputContext(SDL_DBusContext *dbus, const char *appname,
|
||||
|
||||
static bool FcitxClientCreateIC(FcitxClient *client)
|
||||
{
|
||||
char *appname = GetAppName();
|
||||
const char *appname = GetAppName();
|
||||
char *ic_path = NULL;
|
||||
SDL_DBusContext *dbus = client->dbus;
|
||||
|
||||
@@ -290,8 +273,6 @@ static bool FcitxClientCreateIC(FcitxClient *client)
|
||||
ic_path = NULL; // just in case.
|
||||
}
|
||||
|
||||
SDL_free(appname);
|
||||
|
||||
if (ic_path) {
|
||||
SDL_free(client->ic_path);
|
||||
client->ic_path = SDL_strdup(ic_path);
|
||||
|
@@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid)
|
||||
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format)
|
||||
{
|
||||
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
|
||||
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
|
||||
@@ -162,7 +162,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
|
||||
SDL_zero(spec);
|
||||
spec.channels = (Uint8)fmt->Format.nChannels;
|
||||
spec.freq = fmt->Format.nSamplesPerSec;
|
||||
spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
|
||||
spec.format = (force_format != SDL_AUDIO_UNKNOWN) ? force_format : SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
|
||||
|
||||
device = SDL_AddAudioDevice(recording, devname, &spec, handle);
|
||||
if (!device) {
|
||||
@@ -183,6 +183,7 @@ typedef struct SDLMMNotificationClient
|
||||
{
|
||||
const IMMNotificationClientVtbl *lpVtbl;
|
||||
SDL_AtomicInt refcount;
|
||||
SDL_AudioFormat force_format;
|
||||
} SDLMMNotificationClient;
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_QueryInterface(IMMNotificationClient *client, REFIID iid, void **ppv)
|
||||
@@ -241,6 +242,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceRemoved(IMMNoti
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *iclient, LPCWSTR pwstrDeviceId, DWORD dwNewState)
|
||||
{
|
||||
SDLMMNotificationClient *client = (SDLMMNotificationClient *)iclient;
|
||||
IMMDevice *device = NULL;
|
||||
|
||||
if (SUCCEEDED(IMMDeviceEnumerator_GetDevice(enumerator, pwstrDeviceId, &device))) {
|
||||
@@ -255,7 +257,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM
|
||||
GUID dsoundguid;
|
||||
GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid);
|
||||
if (utf8dev) {
|
||||
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid);
|
||||
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format);
|
||||
SDL_free(utf8dev);
|
||||
}
|
||||
} else {
|
||||
@@ -286,7 +288,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = {
|
||||
SDLMMNotificationClient_OnPropertyValueChanged
|
||||
};
|
||||
|
||||
static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } };
|
||||
static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN };
|
||||
|
||||
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks)
|
||||
{
|
||||
@@ -363,7 +365,7 @@ bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool reco
|
||||
return true;
|
||||
}
|
||||
|
||||
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device)
|
||||
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format)
|
||||
{
|
||||
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
|
||||
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
|
||||
@@ -405,7 +407,7 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
|
||||
SDL_zero(dsoundguid);
|
||||
GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid);
|
||||
if (devname) {
|
||||
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid);
|
||||
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format);
|
||||
if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) {
|
||||
*default_device = sdldevice;
|
||||
}
|
||||
@@ -422,10 +424,12 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
|
||||
IMMDeviceCollection_Release(collection);
|
||||
}
|
||||
|
||||
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
|
||||
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format)
|
||||
{
|
||||
EnumerateEndpointsForFlow(false, default_playback);
|
||||
EnumerateEndpointsForFlow(true, default_recording);
|
||||
EnumerateEndpointsForFlow(false, default_playback, force_format);
|
||||
EnumerateEndpointsForFlow(true, default_recording, force_format);
|
||||
|
||||
notification_client.force_format = force_format;
|
||||
|
||||
// if this fails, we just won't get hotplug events. Carry on anyhow.
|
||||
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)¬ification_client);
|
||||
|
@@ -37,7 +37,7 @@ typedef struct SDL_IMMDevice_callbacks
|
||||
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks);
|
||||
void SDL_IMMDevice_Quit(void);
|
||||
bool SDL_IMMDevice_Get(struct SDL_AudioDevice *device, IMMDevice **immdevice, bool recording);
|
||||
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording);
|
||||
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format);
|
||||
LPGUID SDL_IMMDevice_GetDirectSoundGUID(struct SDL_AudioDevice *device);
|
||||
LPCWSTR SDL_IMMDevice_GetDevID(struct SDL_AudioDevice *device);
|
||||
void SDL_IMMDevice_FreeDeviceHandle(struct SDL_AudioDevice *device);
|
||||
|
@@ -53,6 +53,78 @@ typedef enum RO_INIT_TYPE
|
||||
#define WC_ERR_INVALID_CHARS 0x00000080
|
||||
#endif
|
||||
|
||||
// Fake window to help with DirectInput events.
|
||||
HWND SDL_HelperWindow = NULL;
|
||||
static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
|
||||
static const TCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
|
||||
static ATOM SDL_HelperWindowClass = 0;
|
||||
|
||||
/*
|
||||
* Creates a HelperWindow used for DirectInput.
|
||||
*/
|
||||
bool SDL_HelperWindowCreate(void)
|
||||
{
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
WNDCLASS wce;
|
||||
|
||||
// Make sure window isn't created twice.
|
||||
if (SDL_HelperWindow != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create the class.
|
||||
SDL_zero(wce);
|
||||
wce.lpfnWndProc = DefWindowProc;
|
||||
wce.lpszClassName = SDL_HelperWindowClassName;
|
||||
wce.hInstance = hInstance;
|
||||
|
||||
// Register the class.
|
||||
SDL_HelperWindowClass = RegisterClass(&wce);
|
||||
if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
|
||||
return WIN_SetError("Unable to create Helper Window Class");
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
|
||||
SDL_HelperWindowName,
|
||||
WS_OVERLAPPED, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, HWND_MESSAGE, NULL,
|
||||
hInstance, NULL);
|
||||
if (!SDL_HelperWindow) {
|
||||
UnregisterClass(SDL_HelperWindowClassName, hInstance);
|
||||
return WIN_SetError("Unable to create Helper Window");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
|
||||
*/
|
||||
void SDL_HelperWindowDestroy(void)
|
||||
{
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
|
||||
// Destroy the window.
|
||||
if (SDL_HelperWindow != NULL) {
|
||||
if (DestroyWindow(SDL_HelperWindow) == 0) {
|
||||
WIN_SetError("Unable to destroy Helper Window");
|
||||
return;
|
||||
}
|
||||
SDL_HelperWindow = NULL;
|
||||
}
|
||||
|
||||
// Unregister the class.
|
||||
if (SDL_HelperWindowClass != 0) {
|
||||
if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
|
||||
WIN_SetError("Unable to destroy Helper Window Class");
|
||||
return;
|
||||
}
|
||||
SDL_HelperWindowClass = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets an error message based on an HRESULT
|
||||
bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
|
||||
{
|
||||
|
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,2,14,0
|
||||
PRODUCTVERSION 3,2,14,0
|
||||
FILEVERSION 3,2,24,0
|
||||
PRODUCTVERSION 3,2,24,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS 0x40004L
|
||||
@@ -23,12 +23,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "SDL\0"
|
||||
VALUE "FileVersion", "3, 2, 14, 0\0"
|
||||
VALUE "FileVersion", "3, 2, 24, 0\0"
|
||||
VALUE "InternalName", "SDL\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
|
||||
VALUE "OriginalFilename", "SDL3.dll\0"
|
||||
VALUE "ProductName", "Simple DirectMedia Layer\0"
|
||||
VALUE "ProductVersion", "3, 2, 14, 0\0"
|
||||
VALUE "ProductVersion", "3, 2, 24, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <UniformTypeIdentifiers/UTType.h>
|
||||
|
||||
extern void Cocoa_SetWindowHasModalDialog(SDL_Window *window, bool has_modal);
|
||||
|
||||
static void AddFileExtensionType(NSMutableArray *types, const char *pattern_ptr)
|
||||
{
|
||||
if (!*pattern_ptr) {
|
||||
@@ -163,6 +165,9 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
||||
|
||||
if (window) {
|
||||
w = (__bridge NSWindow *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL);
|
||||
if (w) {
|
||||
Cocoa_SetWindowHasModalDialog(window, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (w) {
|
||||
@@ -186,6 +191,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
||||
callback(userdata, files, -1);
|
||||
}
|
||||
|
||||
Cocoa_SetWindowHasModalDialog(window, false);
|
||||
ReactivateAfterDialog();
|
||||
}];
|
||||
} else {
|
||||
@@ -206,6 +212,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
||||
const char *files[1] = { NULL };
|
||||
callback(userdata, files, -1);
|
||||
}
|
||||
|
||||
ReactivateAfterDialog();
|
||||
}
|
||||
}
|
||||
|
@@ -261,7 +261,7 @@ void windows_ShowFileDialog(void *ptr)
|
||||
|
||||
chosen_files_list[nfiles] = NULL;
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_folder, MAX_PATH, NULL, NULL) >= MAX_PATH) {
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_folder, MAX_PATH, NULL, NULL) == 0) {
|
||||
SDL_SetError("Path too long or invalid character in path");
|
||||
SDL_free(chosen_files_list);
|
||||
callback(userdata, NULL, -1);
|
||||
@@ -273,7 +273,7 @@ void windows_ShowFileDialog(void *ptr)
|
||||
SDL_strlcpy(chosen_file, chosen_folder, MAX_PATH);
|
||||
chosen_file[chosen_folder_size] = '\\';
|
||||
|
||||
file_ptr += SDL_strlen(chosen_folder) + 1;
|
||||
file_ptr += SDL_wcslen(file_ptr) + 1;
|
||||
|
||||
while (*file_ptr) {
|
||||
nfiles++;
|
||||
@@ -295,7 +295,7 @@ void windows_ShowFileDialog(void *ptr)
|
||||
|
||||
int diff = ((int) chosen_folder_size) + 1;
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_file + diff, MAX_PATH - diff, NULL, NULL) >= MAX_PATH - diff) {
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_file + diff, MAX_PATH - diff, NULL, NULL) == 0) {
|
||||
SDL_SetError("Path too long or invalid character in path");
|
||||
|
||||
for (size_t i = 0; i < nfiles - 1; i++) {
|
||||
@@ -308,7 +308,7 @@ void windows_ShowFileDialog(void *ptr)
|
||||
return;
|
||||
}
|
||||
|
||||
file_ptr += SDL_strlen(chosen_file) + 1 - diff;
|
||||
file_ptr += SDL_wcslen(file_ptr) + 1;
|
||||
|
||||
chosen_files_list[nfiles - 1] = SDL_strdup(chosen_file);
|
||||
|
||||
|
@@ -1077,16 +1077,11 @@ static void SDL_SendWakeupEvent(void)
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(_this->wakeup_lock);
|
||||
{
|
||||
if (_this->wakeup_window) {
|
||||
_this->SendWakeupEvent(_this, _this->wakeup_window);
|
||||
|
||||
// No more wakeup events needed until we enter a new wait
|
||||
_this->wakeup_window = NULL;
|
||||
// We only want to do this once while waiting for an event, so set it to NULL atomically here
|
||||
SDL_Window *wakeup_window = (SDL_Window *)SDL_SetAtomicPointer(&_this->wakeup_window, NULL);
|
||||
if (wakeup_window) {
|
||||
_this->SendWakeupEvent(_this, wakeup_window);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(_this->wakeup_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1524,18 +1519,7 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
|
||||
*/
|
||||
SDL_PumpEventsInternal(true);
|
||||
|
||||
SDL_LockMutex(_this->wakeup_lock);
|
||||
{
|
||||
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
|
||||
// If status == 0 we are going to block so wakeup will be needed.
|
||||
if (status == 0) {
|
||||
_this->wakeup_window = wakeup_window;
|
||||
} else {
|
||||
_this->wakeup_window = NULL;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(_this->wakeup_lock);
|
||||
|
||||
if (status < 0) {
|
||||
// Got an error: return
|
||||
break;
|
||||
@@ -1548,8 +1532,6 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
|
||||
if (timeoutNS > 0) {
|
||||
Sint64 elapsed = SDL_GetTicksNS() - start;
|
||||
if (elapsed >= timeoutNS) {
|
||||
// Set wakeup_window to NULL without holding the lock.
|
||||
_this->wakeup_window = NULL;
|
||||
return 0;
|
||||
}
|
||||
loop_timeoutNS = (timeoutNS - elapsed);
|
||||
@@ -1562,9 +1544,9 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
|
||||
loop_timeoutNS = poll_intervalNS;
|
||||
}
|
||||
}
|
||||
SDL_SetAtomicPointer(&_this->wakeup_window, wakeup_window);
|
||||
status = _this->WaitEventTimeout(_this, loop_timeoutNS);
|
||||
// Set wakeup_window to NULL without holding the lock.
|
||||
_this->wakeup_window = NULL;
|
||||
SDL_SetAtomicPointer(&_this->wakeup_window, NULL);
|
||||
if (status == 0 && poll_intervalNS != SDL_MAX_SINT64 && loop_timeoutNS == poll_intervalNS) {
|
||||
// We may have woken up to poll. Try again
|
||||
continue;
|
||||
@@ -1664,6 +1646,8 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
for (;;) {
|
||||
SDL_PumpEventsInternal(true);
|
||||
|
||||
if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -138,21 +138,25 @@ static void SDLCALL SDL_TouchMouseEventsChanged(void *userdata, const char *name
|
||||
#ifdef SDL_PLATFORM_VITA
|
||||
static void SDLCALL SDL_VitaTouchMouseDeviceChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
Uint8 vita_touch_mouse_device = 1;
|
||||
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
if (hint) {
|
||||
switch (*hint) {
|
||||
default:
|
||||
case '0':
|
||||
mouse->vita_touch_mouse_device = 1;
|
||||
vita_touch_mouse_device = 1;
|
||||
break;
|
||||
case '1':
|
||||
mouse->vita_touch_mouse_device = 2;
|
||||
vita_touch_mouse_device = 2;
|
||||
break;
|
||||
case '2':
|
||||
mouse->vita_touch_mouse_device = 3;
|
||||
vita_touch_mouse_device = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
mouse->vita_touch_mouse_device = vita_touch_mouse_device;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -371,10 +371,10 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
|
||||
/* 188, 0x0bc */ SDL_SCANCODE_F18, // XF86Launch9
|
||||
/* 189, 0x0bd */ SDL_SCANCODE_F19, // NoSymbol
|
||||
/* 190, 0x0be */ SDL_SCANCODE_F20, // XF86AudioMicMute
|
||||
/* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadToggle
|
||||
/* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOn
|
||||
/* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOff
|
||||
/* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
|
||||
/* 191, 0x0bf */ SDL_SCANCODE_F21, // XF86TouchpadToggle
|
||||
/* 192, 0x0c0 */ SDL_SCANCODE_F22, // XF86TouchpadOn
|
||||
/* 193, 0x0c1 */ SDL_SCANCODE_F23, // XF86TouchpadOff
|
||||
/* 194, 0x0c2 */ SDL_SCANCODE_F24, // NoSymbol
|
||||
/* 195, 0x0c3 */ SDL_SCANCODE_MODE, // Mode_switch
|
||||
/* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
|
||||
/* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
|
||||
|
@@ -78,7 +78,7 @@ static char *search_path_for_binary(const char *bin)
|
||||
char *envr;
|
||||
size_t alloc_size;
|
||||
char *exe = NULL;
|
||||
char *start = envr;
|
||||
char *start;
|
||||
char *ptr;
|
||||
|
||||
if (!envr_real) {
|
||||
@@ -86,7 +86,7 @@ static char *search_path_for_binary(const char *bin)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
envr = SDL_strdup(envr_real);
|
||||
start = envr = SDL_strdup(envr_real);
|
||||
if (!envr) {
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@
|
||||
}
|
||||
|
||||
#define CHECK_GRAPHICS_PIPELINE_BOUND \
|
||||
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
|
||||
if (!((RenderPass *)render_pass)->graphics_pipeline) { \
|
||||
SDL_assert_release(!"Graphics pipeline not bound!"); \
|
||||
return; \
|
||||
}
|
||||
@@ -106,7 +106,7 @@
|
||||
}
|
||||
|
||||
#define CHECK_COMPUTE_PIPELINE_BOUND \
|
||||
if (!((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->compute_pipeline_bound) { \
|
||||
if (!((ComputePass *)compute_pass)->compute_pipeline) { \
|
||||
SDL_assert_release(!"Compute pipeline not bound!"); \
|
||||
return; \
|
||||
}
|
||||
@@ -174,18 +174,132 @@
|
||||
#define RENDERPASS_DEVICE \
|
||||
((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
|
||||
|
||||
#define RENDERPASS_BOUND_PIPELINE \
|
||||
((RenderPass *)render_pass)->graphics_pipeline
|
||||
|
||||
#define COMPUTEPASS_COMMAND_BUFFER \
|
||||
((Pass *)compute_pass)->command_buffer
|
||||
|
||||
#define COMPUTEPASS_DEVICE \
|
||||
((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->device
|
||||
|
||||
#define COMPUTEPASS_BOUND_PIPELINE \
|
||||
((ComputePass *)compute_pass)->compute_pipeline
|
||||
|
||||
#define COPYPASS_COMMAND_BUFFER \
|
||||
((Pass *)copy_pass)->command_buffer
|
||||
|
||||
#define COPYPASS_DEVICE \
|
||||
((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->device
|
||||
|
||||
static bool TextureFormatIsComputeWritable[] = {
|
||||
false, // INVALID
|
||||
false, // A8_UNORM
|
||||
true, // R8_UNORM
|
||||
true, // R8G8_UNORM
|
||||
true, // R8G8B8A8_UNORM
|
||||
true, // R16_UNORM
|
||||
true, // R16G16_UNORM
|
||||
true, // R16G16B16A16_UNORM
|
||||
true, // R10G10B10A2_UNORM
|
||||
false, // B5G6R5_UNORM
|
||||
false, // B5G5R5A1_UNORM
|
||||
false, // B4G4R4A4_UNORM
|
||||
false, // B8G8R8A8_UNORM
|
||||
false, // BC1_UNORM
|
||||
false, // BC2_UNORM
|
||||
false, // BC3_UNORM
|
||||
false, // BC4_UNORM
|
||||
false, // BC5_UNORM
|
||||
false, // BC7_UNORM
|
||||
false, // BC6H_FLOAT
|
||||
false, // BC6H_UFLOAT
|
||||
true, // R8_SNORM
|
||||
true, // R8G8_SNORM
|
||||
true, // R8G8B8A8_SNORM
|
||||
true, // R16_SNORM
|
||||
true, // R16G16_SNORM
|
||||
true, // R16G16B16A16_SNORM
|
||||
true, // R16_FLOAT
|
||||
true, // R16G16_FLOAT
|
||||
true, // R16G16B16A16_FLOAT
|
||||
true, // R32_FLOAT
|
||||
true, // R32G32_FLOAT
|
||||
true, // R32G32B32A32_FLOAT
|
||||
true, // R11G11B10_UFLOAT
|
||||
true, // R8_UINT
|
||||
true, // R8G8_UINT
|
||||
true, // R8G8B8A8_UINT
|
||||
true, // R16_UINT
|
||||
true, // R16G16_UINT
|
||||
true, // R16G16B16A16_UINT
|
||||
true, // R32_UINT
|
||||
true, // R32G32_UINT
|
||||
true, // R32G32B32A32_UINT
|
||||
true, // R8_INT
|
||||
true, // R8G8_INT
|
||||
true, // R8G8B8A8_INT
|
||||
true, // R16_INT
|
||||
true, // R16G16_INT
|
||||
true, // R16G16B16A16_INT
|
||||
true, // R32_INT
|
||||
true, // R32G32_INT
|
||||
true, // R32G32B32A32_INT
|
||||
false, // R8G8B8A8_UNORM_SRGB
|
||||
false, // B8G8R8A8_UNORM_SRGB
|
||||
false, // BC1_UNORM_SRGB
|
||||
false, // BC3_UNORM_SRGB
|
||||
false, // BC3_UNORM_SRGB
|
||||
false, // BC7_UNORM_SRGB
|
||||
false, // D16_UNORM
|
||||
false, // D24_UNORM
|
||||
false, // D32_FLOAT
|
||||
false, // D24_UNORM_S8_UINT
|
||||
false, // D32_FLOAT_S8_UINT
|
||||
false, // ASTC_4x4_UNORM
|
||||
false, // ASTC_5x4_UNORM
|
||||
false, // ASTC_5x5_UNORM
|
||||
false, // ASTC_6x5_UNORM
|
||||
false, // ASTC_6x6_UNORM
|
||||
false, // ASTC_8x5_UNORM
|
||||
false, // ASTC_8x6_UNORM
|
||||
false, // ASTC_8x8_UNORM
|
||||
false, // ASTC_10x5_UNORM
|
||||
false, // ASTC_10x6_UNORM
|
||||
false, // ASTC_10x8_UNORM
|
||||
false, // ASTC_10x10_UNORM
|
||||
false, // ASTC_12x10_UNORM
|
||||
false, // ASTC_12x12_UNORM
|
||||
false, // ASTC_4x4_UNORM_SRGB
|
||||
false, // ASTC_5x4_UNORM_SRGB
|
||||
false, // ASTC_5x5_UNORM_SRGB
|
||||
false, // ASTC_6x5_UNORM_SRGB
|
||||
false, // ASTC_6x6_UNORM_SRGB
|
||||
false, // ASTC_8x5_UNORM_SRGB
|
||||
false, // ASTC_8x6_UNORM_SRGB
|
||||
false, // ASTC_8x8_UNORM_SRGB
|
||||
false, // ASTC_10x5_UNORM_SRGB
|
||||
false, // ASTC_10x6_UNORM_SRGB
|
||||
false, // ASTC_10x8_UNORM_SRGB
|
||||
false, // ASTC_10x10_UNORM_SRGB
|
||||
false, // ASTC_12x10_UNORM_SRGB
|
||||
false, // ASTC_12x12_UNORM_SRGB
|
||||
false, // ASTC_4x4_FLOAT
|
||||
false, // ASTC_5x4_FLOAT
|
||||
false, // ASTC_5x5_FLOAT
|
||||
false, // ASTC_6x5_FLOAT
|
||||
false, // ASTC_6x6_FLOAT
|
||||
false, // ASTC_8x5_FLOAT
|
||||
false, // ASTC_8x6_FLOAT
|
||||
false, // ASTC_8x8_FLOAT
|
||||
false, // ASTC_10x5_FLOAT
|
||||
false, // ASTC_10x6_FLOAT
|
||||
false, // ASTC_10x8_FLOAT
|
||||
false, // ASTC_10x10_FLOAT
|
||||
false, // ASTC_12x10_FLOAT
|
||||
false // ASTC_12x12_FLOAT
|
||||
};
|
||||
|
||||
// Drivers
|
||||
|
||||
#ifndef SDL_GPU_DISABLED
|
||||
@@ -403,6 +517,73 @@ void SDL_GPU_BlitCommon(
|
||||
SDL_EndGPURenderPass(render_pass);
|
||||
}
|
||||
|
||||
static void SDL_GPU_CheckGraphicsBindings(SDL_GPURenderPass *render_pass)
|
||||
{
|
||||
RenderPass *rp = (RenderPass *)render_pass;
|
||||
GraphicsPipelineCommonHeader *pipeline = (GraphicsPipelineCommonHeader *)RENDERPASS_BOUND_PIPELINE;
|
||||
for (Uint32 i = 0; i < pipeline->num_vertex_samplers; i += 1) {
|
||||
if (!rp->vertex_sampler_bound[i]) {
|
||||
SDL_assert_release(!"Missing vertex sampler binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->num_vertex_storage_textures; i += 1) {
|
||||
if (!rp->vertex_storage_texture_bound[i]) {
|
||||
SDL_assert_release(!"Missing vertex storage texture binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->num_vertex_storage_buffers; i += 1) {
|
||||
if (!rp->vertex_storage_buffer_bound[i]) {
|
||||
SDL_assert_release(!"Missing vertex storage buffer binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->num_fragment_samplers; i += 1) {
|
||||
if (!rp->fragment_sampler_bound[i]) {
|
||||
SDL_assert_release(!"Missing fragment sampler binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->num_fragment_storage_textures; i += 1) {
|
||||
if (!rp->fragment_storage_texture_bound[i]) {
|
||||
SDL_assert_release(!"Missing fragment storage texture binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->num_fragment_storage_buffers; i += 1) {
|
||||
if (!rp->fragment_storage_buffer_bound[i]) {
|
||||
SDL_assert_release(!"Missing fragment storage buffer binding!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_GPU_CheckComputeBindings(SDL_GPUComputePass *compute_pass)
|
||||
{
|
||||
ComputePass *cp = (ComputePass *)compute_pass;
|
||||
ComputePipelineCommonHeader *pipeline = (ComputePipelineCommonHeader *)COMPUTEPASS_BOUND_PIPELINE;
|
||||
for (Uint32 i = 0; i < pipeline->numSamplers; i += 1) {
|
||||
if (!cp->sampler_bound[i]) {
|
||||
SDL_assert_release(!"Missing compute sampler binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->numReadonlyStorageTextures; i += 1) {
|
||||
if (!cp->read_only_storage_texture_bound[i]) {
|
||||
SDL_assert_release(!"Missing compute readonly storage texture binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->numReadonlyStorageBuffers; i += 1) {
|
||||
if (!cp->read_only_storage_buffer_bound[i]) {
|
||||
SDL_assert_release(!"Missing compute readonly storage buffer binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) {
|
||||
if (!cp->read_write_storage_texture_bound[i]) {
|
||||
SDL_assert_release(!"Missing compute read-write storage texture binding!");
|
||||
}
|
||||
}
|
||||
for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) {
|
||||
if (!cp->read_write_storage_buffer_bound[i]) {
|
||||
SDL_assert_release(!"Missing compute read-write storage buffer bbinding!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Functions
|
||||
|
||||
#ifndef SDL_GPU_DISABLED
|
||||
@@ -564,7 +745,6 @@ SDL_GPUDevice *SDL_CreateGPUDeviceWithProperties(SDL_PropertiesID props)
|
||||
result = selectedBackend->CreateDevice(debug_mode, preferLowPower, props);
|
||||
if (result != NULL) {
|
||||
result->backend = selectedBackend->name;
|
||||
result->shader_formats = selectedBackend->shader_formats;
|
||||
result->debug_mode = debug_mode;
|
||||
}
|
||||
}
|
||||
@@ -753,6 +933,13 @@ bool SDL_GPUTextureSupportsFormat(
|
||||
CHECK_TEXTUREFORMAT_ENUM_INVALID(format, false)
|
||||
}
|
||||
|
||||
if ((usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
|
||||
(usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
|
||||
if (!TextureFormatIsComputeWritable[format]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return device->SupportsTextureFormat(
|
||||
device->driverData,
|
||||
format,
|
||||
@@ -1375,15 +1562,30 @@ SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer(
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||
commandBufferHeader->device = device;
|
||||
commandBufferHeader->render_pass.command_buffer = command_buffer;
|
||||
commandBufferHeader->render_pass.in_progress = false;
|
||||
commandBufferHeader->graphics_pipeline_bound = false;
|
||||
commandBufferHeader->compute_pass.command_buffer = command_buffer;
|
||||
commandBufferHeader->compute_pass.in_progress = false;
|
||||
commandBufferHeader->compute_pipeline_bound = false;
|
||||
commandBufferHeader->copy_pass.command_buffer = command_buffer;
|
||||
|
||||
if (device->debug_mode) {
|
||||
commandBufferHeader->render_pass.in_progress = false;
|
||||
commandBufferHeader->render_pass.graphics_pipeline = NULL;
|
||||
commandBufferHeader->compute_pass.in_progress = false;
|
||||
commandBufferHeader->compute_pass.compute_pipeline = NULL;
|
||||
commandBufferHeader->copy_pass.in_progress = false;
|
||||
commandBufferHeader->swapchain_texture_acquired = false;
|
||||
commandBufferHeader->submitted = false;
|
||||
commandBufferHeader->ignore_render_pass_texture_validation = false;
|
||||
SDL_zeroa(commandBufferHeader->render_pass.vertex_sampler_bound);
|
||||
SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_buffer_bound);
|
||||
SDL_zeroa(commandBufferHeader->render_pass.fragment_sampler_bound);
|
||||
SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_buffer_bound);
|
||||
SDL_zeroa(commandBufferHeader->compute_pass.sampler_bound);
|
||||
SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_buffer_bound);
|
||||
SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_buffer_bound);
|
||||
}
|
||||
|
||||
return command_buffer;
|
||||
}
|
||||
@@ -1501,30 +1703,47 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
||||
|
||||
if (color_target_infos[i].cycle && color_target_infos[i].load_op == SDL_GPU_LOADOP_LOAD) {
|
||||
SDL_assert_release(!"Cannot cycle color target when load op is LOAD!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE || color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
|
||||
if (color_target_infos[i].resolve_texture == NULL) {
|
||||
SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but resolve_texture is NULL!");
|
||||
return NULL;
|
||||
} else {
|
||||
TextureCommonHeader *resolveTextureHeader = (TextureCommonHeader *)color_target_infos[i].resolve_texture;
|
||||
if (textureHeader->info.sample_count == SDL_GPU_SAMPLECOUNT_1) {
|
||||
SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but texture is not multisample!");
|
||||
return NULL;
|
||||
}
|
||||
if (resolveTextureHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) {
|
||||
SDL_assert_release(!"Resolve texture must have a sample count of 1!");
|
||||
return NULL;
|
||||
}
|
||||
if (resolveTextureHeader->info.format != textureHeader->info.format) {
|
||||
SDL_assert_release(!"Resolve texture must have the same format as its corresponding color target!");
|
||||
return NULL;
|
||||
}
|
||||
if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) {
|
||||
SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!");
|
||||
return NULL;
|
||||
}
|
||||
if (!(resolveTextureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) {
|
||||
SDL_assert_release(!"Resolve texture usage must include COLOR_TARGET!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (color_target_infos[i].layer_or_depth_plane >= textureHeader->info.layer_count_or_depth) {
|
||||
SDL_assert_release(!"Color target layer index must be less than the texture's layer count!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (color_target_infos[i].mip_level >= textureHeader->info.num_levels) {
|
||||
SDL_assert_release(!"Color target mip level must be less than the texture's level count!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_stencil_target_info != NULL) {
|
||||
@@ -1532,10 +1751,12 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
||||
TextureCommonHeader *textureHeader = (TextureCommonHeader *)depth_stencil_target_info->texture;
|
||||
if (!(textureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
|
||||
SDL_assert_release(!"Depth target must have been created with the DEPTH_STENCIL_TARGET usage flag!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (depth_stencil_target_info->cycle && (depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD || depth_stencil_target_info->stencil_load_op == SDL_GPU_LOADOP_LOAD)) {
|
||||
SDL_assert_release(!"Cannot cycle depth target when load op or stencil load op is LOAD!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE ||
|
||||
@@ -1543,6 +1764,7 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
||||
depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE ||
|
||||
depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
|
||||
SDL_assert_release(!"RESOLVE store ops are not supported for depth-stencil targets!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1554,6 +1776,8 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
||||
depth_stencil_target_info);
|
||||
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||
|
||||
if (COMMAND_BUFFER_DEVICE->debug_mode) {
|
||||
commandBufferHeader->render_pass.in_progress = true;
|
||||
for (Uint32 i = 0; i < num_color_targets; i += 1) {
|
||||
commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
|
||||
@@ -1561,7 +1785,11 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
||||
commandBufferHeader->render_pass.num_color_targets = num_color_targets;
|
||||
if (depth_stencil_target_info != NULL) {
|
||||
commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
|
||||
} else {
|
||||
commandBufferHeader->render_pass.depth_stencil_target = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
|
||||
}
|
||||
|
||||
@@ -1569,8 +1797,6 @@ void SDL_BindGPUGraphicsPipeline(
|
||||
SDL_GPURenderPass *render_pass,
|
||||
SDL_GPUGraphicsPipeline *graphics_pipeline)
|
||||
{
|
||||
CommandBufferCommonHeader *commandBufferHeader;
|
||||
|
||||
if (render_pass == NULL) {
|
||||
SDL_InvalidParamError("render_pass");
|
||||
return;
|
||||
@@ -1584,8 +1810,10 @@ void SDL_BindGPUGraphicsPipeline(
|
||||
RENDERPASS_COMMAND_BUFFER,
|
||||
graphics_pipeline);
|
||||
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
|
||||
commandBufferHeader->graphics_pipeline_bound = true;
|
||||
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
RENDERPASS_BOUND_PIPELINE = graphics_pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_SetGPUViewport(
|
||||
@@ -1740,6 +1968,10 @@ void SDL_BindGPUVertexSamplers(
|
||||
{
|
||||
CHECK_SAMPLER_TEXTURES
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->vertex_sampler_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindVertexSamplers(
|
||||
@@ -1767,6 +1999,10 @@ void SDL_BindGPUVertexStorageTextures(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_STORAGE_TEXTURES
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->vertex_storage_texture_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindVertexStorageTextures(
|
||||
@@ -1793,6 +2029,10 @@ void SDL_BindGPUVertexStorageBuffers(
|
||||
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->vertex_storage_buffer_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindVertexStorageBuffers(
|
||||
@@ -1820,10 +2060,13 @@ void SDL_BindGPUFragmentSamplers(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
|
||||
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
|
||||
{
|
||||
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation) {
|
||||
CHECK_SAMPLER_TEXTURES
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->fragment_sampler_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindFragmentSamplers(
|
||||
@@ -1851,6 +2094,10 @@ void SDL_BindGPUFragmentStorageTextures(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_STORAGE_TEXTURES
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->fragment_storage_texture_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindFragmentStorageTextures(
|
||||
@@ -1877,6 +2124,10 @@ void SDL_BindGPUFragmentStorageBuffers(
|
||||
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((RenderPass *)render_pass)->fragment_storage_buffer_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->BindFragmentStorageBuffers(
|
||||
@@ -1902,6 +2153,7 @@ void SDL_DrawGPUIndexedPrimitives(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_GRAPHICS_PIPELINE_BOUND
|
||||
SDL_GPU_CheckGraphicsBindings(render_pass);
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->DrawIndexedPrimitives(
|
||||
@@ -1928,6 +2180,7 @@ void SDL_DrawGPUPrimitives(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_GRAPHICS_PIPELINE_BOUND
|
||||
SDL_GPU_CheckGraphicsBindings(render_pass);
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->DrawPrimitives(
|
||||
@@ -1956,6 +2209,7 @@ void SDL_DrawGPUPrimitivesIndirect(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_GRAPHICS_PIPELINE_BOUND
|
||||
SDL_GPU_CheckGraphicsBindings(render_pass);
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->DrawPrimitivesIndirect(
|
||||
@@ -1983,6 +2237,7 @@ void SDL_DrawGPUIndexedPrimitivesIndirect(
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
CHECK_GRAPHICS_PIPELINE_BOUND
|
||||
SDL_GPU_CheckGraphicsBindings(render_pass);
|
||||
}
|
||||
|
||||
RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect(
|
||||
@@ -1995,13 +2250,14 @@ void SDL_DrawGPUIndexedPrimitivesIndirect(
|
||||
void SDL_EndGPURenderPass(
|
||||
SDL_GPURenderPass *render_pass)
|
||||
{
|
||||
CommandBufferCommonHeader *commandBufferCommonHeader;
|
||||
|
||||
if (render_pass == NULL) {
|
||||
SDL_InvalidParamError("render_pass");
|
||||
return;
|
||||
}
|
||||
|
||||
CommandBufferCommonHeader *commandBufferCommonHeader;
|
||||
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
|
||||
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
CHECK_RENDERPASS
|
||||
}
|
||||
@@ -2009,7 +2265,7 @@ void SDL_EndGPURenderPass(
|
||||
RENDERPASS_DEVICE->EndRenderPass(
|
||||
RENDERPASS_COMMAND_BUFFER);
|
||||
|
||||
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
|
||||
if (RENDERPASS_DEVICE->debug_mode) {
|
||||
commandBufferCommonHeader->render_pass.in_progress = false;
|
||||
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
|
||||
{
|
||||
@@ -2017,7 +2273,14 @@ void SDL_EndGPURenderPass(
|
||||
}
|
||||
commandBufferCommonHeader->render_pass.num_color_targets = 0;
|
||||
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
|
||||
commandBufferCommonHeader->graphics_pipeline_bound = false;
|
||||
commandBufferCommonHeader->render_pass.graphics_pipeline = NULL;
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_sampler_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_buffer_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_sampler_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_buffer_bound);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute Pass
|
||||
@@ -2061,6 +2324,16 @@ SDL_GPUComputePass *SDL_BeginGPUComputePass(
|
||||
SDL_assert_release(!"Texture must be created with COMPUTE_STORAGE_WRITE or COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE flag");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (storage_texture_bindings[i].layer >= header->info.layer_count_or_depth) {
|
||||
SDL_assert_release(!"Storage texture layer index must be less than the texture's layer count!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (storage_texture_bindings[i].mip_level >= header->info.num_levels) {
|
||||
SDL_assert_release(!"Storage texture mip level must be less than the texture's level count!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: validate buffer usage?
|
||||
@@ -2074,7 +2347,19 @@ SDL_GPUComputePass *SDL_BeginGPUComputePass(
|
||||
num_storage_buffer_bindings);
|
||||
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||
|
||||
if (COMMAND_BUFFER_DEVICE->debug_mode) {
|
||||
commandBufferHeader->compute_pass.in_progress = true;
|
||||
|
||||
for (Uint32 i = 0; i < num_storage_texture_bindings; i += 1) {
|
||||
commandBufferHeader->compute_pass.read_write_storage_texture_bound[i] = true;
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < num_storage_buffer_bindings; i += 1) {
|
||||
commandBufferHeader->compute_pass.read_write_storage_buffer_bound[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return (SDL_GPUComputePass *)&(commandBufferHeader->compute_pass);
|
||||
}
|
||||
|
||||
@@ -2082,8 +2367,6 @@ void SDL_BindGPUComputePipeline(
|
||||
SDL_GPUComputePass *compute_pass,
|
||||
SDL_GPUComputePipeline *compute_pipeline)
|
||||
{
|
||||
CommandBufferCommonHeader *commandBufferHeader;
|
||||
|
||||
if (compute_pass == NULL) {
|
||||
SDL_InvalidParamError("compute_pass");
|
||||
return;
|
||||
@@ -2101,8 +2384,10 @@ void SDL_BindGPUComputePipeline(
|
||||
COMPUTEPASS_COMMAND_BUFFER,
|
||||
compute_pipeline);
|
||||
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
|
||||
commandBufferHeader->compute_pipeline_bound = true;
|
||||
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
COMPUTEPASS_BOUND_PIPELINE = compute_pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_BindGPUComputeSamplers(
|
||||
@@ -2122,6 +2407,10 @@ void SDL_BindGPUComputeSamplers(
|
||||
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
CHECK_COMPUTEPASS
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((ComputePass *)compute_pass)->sampler_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
COMPUTEPASS_DEVICE->BindComputeSamplers(
|
||||
@@ -2148,6 +2437,10 @@ void SDL_BindGPUComputeStorageTextures(
|
||||
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
CHECK_COMPUTEPASS
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((ComputePass *)compute_pass)->read_only_storage_texture_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
COMPUTEPASS_DEVICE->BindComputeStorageTextures(
|
||||
@@ -2174,6 +2467,10 @@ void SDL_BindGPUComputeStorageBuffers(
|
||||
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
CHECK_COMPUTEPASS
|
||||
|
||||
for (Uint32 i = 0; i < num_bindings; i += 1) {
|
||||
((ComputePass *)compute_pass)->read_only_storage_buffer_bound[first_slot + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
COMPUTEPASS_DEVICE->BindComputeStorageBuffers(
|
||||
@@ -2197,6 +2494,7 @@ void SDL_DispatchGPUCompute(
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
CHECK_COMPUTEPASS
|
||||
CHECK_COMPUTE_PIPELINE_BOUND
|
||||
SDL_GPU_CheckComputeBindings(compute_pass);
|
||||
}
|
||||
|
||||
COMPUTEPASS_DEVICE->DispatchCompute(
|
||||
@@ -2219,6 +2517,7 @@ void SDL_DispatchGPUComputeIndirect(
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
CHECK_COMPUTEPASS
|
||||
CHECK_COMPUTE_PIPELINE_BOUND
|
||||
SDL_GPU_CheckComputeBindings(compute_pass);
|
||||
}
|
||||
|
||||
COMPUTEPASS_DEVICE->DispatchComputeIndirect(
|
||||
@@ -2244,9 +2543,16 @@ void SDL_EndGPUComputePass(
|
||||
COMPUTEPASS_DEVICE->EndComputePass(
|
||||
COMPUTEPASS_COMMAND_BUFFER);
|
||||
|
||||
if (COMPUTEPASS_DEVICE->debug_mode) {
|
||||
commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
|
||||
commandBufferCommonHeader->compute_pass.in_progress = false;
|
||||
commandBufferCommonHeader->compute_pipeline_bound = false;
|
||||
commandBufferCommonHeader->compute_pass.compute_pipeline = NULL;
|
||||
SDL_zeroa(commandBufferCommonHeader->compute_pass.sampler_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_buffer_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_texture_bound);
|
||||
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_buffer_bound);
|
||||
}
|
||||
}
|
||||
|
||||
// TransferBuffer Data
|
||||
@@ -2304,7 +2610,11 @@ SDL_GPUCopyPass *SDL_BeginGPUCopyPass(
|
||||
command_buffer);
|
||||
|
||||
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||
|
||||
if (COMMAND_BUFFER_DEVICE->debug_mode) {
|
||||
commandBufferHeader->copy_pass.in_progress = true;
|
||||
}
|
||||
|
||||
return (SDL_GPUCopyPass *)&(commandBufferHeader->copy_pass);
|
||||
}
|
||||
|
||||
@@ -2555,7 +2865,9 @@ void SDL_EndGPUCopyPass(
|
||||
COPYPASS_DEVICE->EndCopyPass(
|
||||
COPYPASS_COMMAND_BUFFER);
|
||||
|
||||
if (COPYPASS_DEVICE->debug_mode) {
|
||||
((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_GenerateMipmapsForGPUTexture(
|
||||
|
@@ -35,7 +35,7 @@
|
||||
#define UNIFORM_BUFFER_SIZE 32768
|
||||
#define MAX_VERTEX_BUFFERS 16
|
||||
#define MAX_VERTEX_ATTRIBUTES 16
|
||||
#define MAX_COLOR_TARGET_BINDINGS 4
|
||||
#define MAX_COLOR_TARGET_BINDINGS 8
|
||||
#define MAX_PRESENT_COUNT 16
|
||||
#define MAX_FRAMES_IN_FLIGHT 3
|
||||
|
||||
@@ -47,6 +47,20 @@ typedef struct Pass
|
||||
bool in_progress;
|
||||
} Pass;
|
||||
|
||||
typedef struct ComputePass
|
||||
{
|
||||
SDL_GPUCommandBuffer *command_buffer;
|
||||
bool in_progress;
|
||||
|
||||
SDL_GPUComputePipeline *compute_pipeline;
|
||||
|
||||
bool sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
bool read_only_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
bool read_only_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
bool read_write_storage_texture_bound[MAX_COMPUTE_WRITE_TEXTURES];
|
||||
bool read_write_storage_buffer_bound[MAX_COMPUTE_WRITE_BUFFERS];
|
||||
} ComputePass;
|
||||
|
||||
typedef struct RenderPass
|
||||
{
|
||||
SDL_GPUCommandBuffer *command_buffer;
|
||||
@@ -54,15 +68,25 @@ typedef struct RenderPass
|
||||
SDL_GPUTexture *color_targets[MAX_COLOR_TARGET_BINDINGS];
|
||||
Uint32 num_color_targets;
|
||||
SDL_GPUTexture *depth_stencil_target;
|
||||
|
||||
SDL_GPUGraphicsPipeline *graphics_pipeline;
|
||||
|
||||
bool vertex_sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
bool vertex_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
bool vertex_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
bool fragment_sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
bool fragment_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
bool fragment_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
} RenderPass;
|
||||
|
||||
typedef struct CommandBufferCommonHeader
|
||||
{
|
||||
SDL_GPUDevice *device;
|
||||
|
||||
RenderPass render_pass;
|
||||
bool graphics_pipeline_bound;
|
||||
Pass compute_pass;
|
||||
bool compute_pipeline_bound;
|
||||
ComputePass compute_pass;
|
||||
|
||||
Pass copy_pass;
|
||||
bool swapchain_texture_acquired;
|
||||
bool submitted;
|
||||
@@ -75,6 +99,29 @@ typedef struct TextureCommonHeader
|
||||
SDL_GPUTextureCreateInfo info;
|
||||
} TextureCommonHeader;
|
||||
|
||||
typedef struct GraphicsPipelineCommonHeader
|
||||
{
|
||||
Uint32 num_vertex_samplers;
|
||||
Uint32 num_vertex_storage_textures;
|
||||
Uint32 num_vertex_storage_buffers;
|
||||
Uint32 num_vertex_uniform_buffers;
|
||||
|
||||
Uint32 num_fragment_samplers;
|
||||
Uint32 num_fragment_storage_textures;
|
||||
Uint32 num_fragment_storage_buffers;
|
||||
Uint32 num_fragment_uniform_buffers;
|
||||
} GraphicsPipelineCommonHeader;
|
||||
|
||||
typedef struct ComputePipelineCommonHeader
|
||||
{
|
||||
Uint32 numSamplers;
|
||||
Uint32 numReadonlyStorageTextures;
|
||||
Uint32 numReadonlyStorageBuffers;
|
||||
Uint32 numReadWriteStorageTextures;
|
||||
Uint32 numReadWriteStorageBuffers;
|
||||
Uint32 numUniformBuffers;
|
||||
} ComputePipelineCommonHeader;
|
||||
|
||||
typedef struct BlitFragmentUniforms
|
||||
{
|
||||
// texcoord space
|
||||
@@ -162,6 +209,7 @@ static inline Sint32 Texture_GetBlockWidth(
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
|
||||
@@ -279,6 +327,7 @@ static inline Sint32 Texture_GetBlockHeight(
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
|
||||
|
@@ -109,8 +109,8 @@
|
||||
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
||||
#define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface"
|
||||
#define WINDOW_PROPERTY_DATA "SDL_GPUD3D12WindowPropertyData"
|
||||
#define D3D_FEATURE_LEVEL_CHOICE D3D_FEATURE_LEVEL_11_1
|
||||
#define D3D_FEATURE_LEVEL_CHOICE_STR "11_1"
|
||||
#define D3D_FEATURE_LEVEL_CHOICE D3D_FEATURE_LEVEL_11_0
|
||||
#define D3D_FEATURE_LEVEL_CHOICE_STR "11_0"
|
||||
#define MAX_ROOT_SIGNATURE_PARAMETERS 64
|
||||
#define D3D12_FENCE_UNSIGNALED_VALUE 0
|
||||
#define D3D12_FENCE_SIGNAL_VALUE 1
|
||||
@@ -1015,26 +1015,38 @@ struct D3D12CommandBuffer
|
||||
Uint32 vertexBufferOffsets[MAX_VERTEX_BUFFERS];
|
||||
Uint32 vertexBufferCount;
|
||||
|
||||
D3D12Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE vertexSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE vertexSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE vertexStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE vertexStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
D3D12UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
|
||||
|
||||
D3D12Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE fragmentSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE fragmentSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE fragmentStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE fragmentStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
D3D12UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
|
||||
|
||||
D3D12Texture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12Sampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeReadOnlyStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeReadOnlyStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
// Track these separately because barriers can happen mid compute pass
|
||||
D3D12Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
D3D12Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeReadWriteStorageTextureDescriptorHandles[MAX_COMPUTE_WRITE_TEXTURES];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE computeReadWriteStorageBufferDescriptorHandles[MAX_COMPUTE_WRITE_BUFFERS];
|
||||
|
||||
// Track these separately because they are bound when the compute pass begins
|
||||
D3D12TextureSubresource *computeReadWriteStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
|
||||
Uint32 computeReadWriteStorageTextureSubresourceCount;
|
||||
D3D12Buffer *computeReadWriteStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
|
||||
Uint32 computeReadWriteStorageBufferCount;
|
||||
|
||||
D3D12UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
|
||||
|
||||
// Resource tracking
|
||||
@@ -1098,22 +1110,14 @@ typedef struct D3D12GraphicsRootSignature
|
||||
|
||||
struct D3D12GraphicsPipeline
|
||||
{
|
||||
GraphicsPipelineCommonHeader header;
|
||||
|
||||
ID3D12PipelineState *pipelineState;
|
||||
D3D12GraphicsRootSignature *rootSignature;
|
||||
SDL_GPUPrimitiveType primitiveType;
|
||||
|
||||
Uint32 vertexStrides[MAX_VERTEX_BUFFERS];
|
||||
|
||||
Uint32 vertexSamplerCount;
|
||||
Uint32 vertexUniformBufferCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexStorageTextureCount;
|
||||
|
||||
Uint32 fragmentSamplerCount;
|
||||
Uint32 fragmentUniformBufferCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentStorageTextureCount;
|
||||
|
||||
SDL_AtomicInt referenceCount;
|
||||
};
|
||||
|
||||
@@ -1132,16 +1136,11 @@ typedef struct D3D12ComputeRootSignature
|
||||
|
||||
struct D3D12ComputePipeline
|
||||
{
|
||||
ComputePipelineCommonHeader header;
|
||||
|
||||
ID3D12PipelineState *pipelineState;
|
||||
D3D12ComputeRootSignature *rootSignature;
|
||||
|
||||
Uint32 numSamplers;
|
||||
Uint32 numReadOnlyStorageTextures;
|
||||
Uint32 numReadOnlyStorageBuffers;
|
||||
Uint32 numReadWriteStorageTextures;
|
||||
Uint32 numReadWriteStorageBuffers;
|
||||
Uint32 numUniformBuffers;
|
||||
|
||||
SDL_AtomicInt referenceCount;
|
||||
};
|
||||
|
||||
@@ -1195,7 +1194,6 @@ struct D3D12UniformBuffer
|
||||
D3D12Buffer *buffer;
|
||||
Uint32 writeOffset;
|
||||
Uint32 drawOffset;
|
||||
Uint32 currentBlockSize;
|
||||
};
|
||||
|
||||
// Forward function declarations
|
||||
@@ -1442,6 +1440,8 @@ static void D3D12_INTERNAL_ReleaseTextureContainer(
|
||||
container->textures[i]);
|
||||
}
|
||||
|
||||
SDL_DestroyProperties(container->header.info.props);
|
||||
|
||||
// Containers are just client handles, so we can destroy immediately
|
||||
if (container->debugName) {
|
||||
SDL_free(container->debugName);
|
||||
@@ -2886,12 +2886,12 @@ static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
|
||||
|
||||
computePipeline->pipelineState = pipelineState;
|
||||
computePipeline->rootSignature = rootSignature;
|
||||
computePipeline->numSamplers = createinfo->num_samplers;
|
||||
computePipeline->numReadOnlyStorageTextures = createinfo->num_readonly_storage_textures;
|
||||
computePipeline->numReadOnlyStorageBuffers = createinfo->num_readonly_storage_buffers;
|
||||
computePipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
|
||||
computePipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
|
||||
computePipeline->numUniformBuffers = createinfo->num_uniform_buffers;
|
||||
computePipeline->header.numSamplers = createinfo->num_samplers;
|
||||
computePipeline->header.numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
|
||||
computePipeline->header.numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
|
||||
computePipeline->header.numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
|
||||
computePipeline->header.numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
|
||||
computePipeline->header.numUniformBuffers = createinfo->num_uniform_buffers;
|
||||
SDL_SetAtomicInt(&computePipeline->referenceCount, 0);
|
||||
|
||||
if (renderer->debug_mode && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING)) {
|
||||
@@ -3172,15 +3172,15 @@ static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
|
||||
|
||||
pipeline->primitiveType = createinfo->primitive_type;
|
||||
|
||||
pipeline->vertexSamplerCount = vertShader->num_samplers;
|
||||
pipeline->vertexStorageTextureCount = vertShader->numStorageTextures;
|
||||
pipeline->vertexStorageBufferCount = vertShader->numStorageBuffers;
|
||||
pipeline->vertexUniformBufferCount = vertShader->numUniformBuffers;
|
||||
pipeline->header.num_vertex_samplers = vertShader->num_samplers;
|
||||
pipeline->header.num_vertex_storage_textures = vertShader->numStorageTextures;
|
||||
pipeline->header.num_vertex_storage_buffers = vertShader->numStorageBuffers;
|
||||
pipeline->header.num_vertex_uniform_buffers = vertShader->numUniformBuffers;
|
||||
|
||||
pipeline->fragmentSamplerCount = fragShader->num_samplers;
|
||||
pipeline->fragmentStorageTextureCount = fragShader->numStorageTextures;
|
||||
pipeline->fragmentStorageBufferCount = fragShader->numStorageBuffers;
|
||||
pipeline->fragmentUniformBufferCount = fragShader->numUniformBuffers;
|
||||
pipeline->header.num_fragment_samplers = fragShader->num_samplers;
|
||||
pipeline->header.num_fragment_storage_textures = fragShader->numStorageTextures;
|
||||
pipeline->header.num_fragment_storage_buffers = fragShader->numStorageBuffers;
|
||||
pipeline->header.num_fragment_uniform_buffers = fragShader->numUniformBuffers;
|
||||
|
||||
SDL_SetAtomicInt(&pipeline->referenceCount, 0);
|
||||
|
||||
@@ -3350,7 +3350,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
||||
|
||||
if (createinfo->type != SDL_GPU_TEXTURETYPE_3D) {
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Alignment = isSwapchainTexture ? 0 : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Alignment = isSwapchainTexture ? 0 : isMultisample ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = createinfo->width;
|
||||
desc.Height = createinfo->height;
|
||||
desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
|
||||
@@ -4497,7 +4497,6 @@ static D3D12UniformBuffer *D3D12_INTERNAL_AcquireUniformBufferFromPool(
|
||||
|
||||
SDL_UnlockMutex(renderer->acquireUniformBufferLock);
|
||||
|
||||
uniformBuffer->currentBlockSize = 0;
|
||||
uniformBuffer->drawOffset = 0;
|
||||
uniformBuffer->writeOffset = 0;
|
||||
|
||||
@@ -4536,6 +4535,7 @@ static void D3D12_INTERNAL_PushUniformData(
|
||||
Uint32 length)
|
||||
{
|
||||
D3D12UniformBuffer *uniformBuffer;
|
||||
Uint32 blockSize;
|
||||
|
||||
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
|
||||
if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
|
||||
@@ -4560,13 +4560,13 @@ static void D3D12_INTERNAL_PushUniformData(
|
||||
return;
|
||||
}
|
||||
|
||||
uniformBuffer->currentBlockSize =
|
||||
blockSize =
|
||||
D3D12_INTERNAL_Align(
|
||||
length,
|
||||
256);
|
||||
|
||||
// If there is no more room, acquire a new uniform buffer
|
||||
if (uniformBuffer->writeOffset + uniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
|
||||
if (uniformBuffer->writeOffset + blockSize >= UNIFORM_BUFFER_SIZE) {
|
||||
ID3D12Resource_Unmap(
|
||||
uniformBuffer->buffer->handle,
|
||||
0,
|
||||
@@ -4596,7 +4596,7 @@ static void D3D12_INTERNAL_PushUniformData(
|
||||
data,
|
||||
length);
|
||||
|
||||
uniformBuffer->writeOffset += uniformBuffer->currentBlockSize;
|
||||
uniformBuffer->writeOffset += blockSize;
|
||||
|
||||
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
|
||||
commandBuffer->needVertexUniformBufferBind[slotIndex] = true;
|
||||
@@ -4637,14 +4637,14 @@ static void D3D12_BindGraphicsPipeline(
|
||||
d3d12CommandBuffer->needFragmentUniformBufferBind[i] = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
|
||||
for (i = 0; i < pipeline->header.num_vertex_uniform_buffers; i += 1) {
|
||||
if (d3d12CommandBuffer->vertexUniformBuffers[i] == NULL) {
|
||||
d3d12CommandBuffer->vertexUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
|
||||
d3d12CommandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
|
||||
for (i = 0; i < pipeline->header.num_fragment_uniform_buffers; i += 1) {
|
||||
if (d3d12CommandBuffer->fragmentUniformBuffers[i] == NULL) {
|
||||
d3d12CommandBuffer->fragmentUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
|
||||
d3d12CommandBuffer);
|
||||
@@ -4711,21 +4711,21 @@ static void D3D12_BindVertexSamplers(
|
||||
D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
|
||||
D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (d3d12CommandBuffer->vertexSamplers[firstSlot + i] != sampler) {
|
||||
if (d3d12CommandBuffer->vertexSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackSampler(
|
||||
d3d12CommandBuffer,
|
||||
sampler);
|
||||
|
||||
d3d12CommandBuffer->vertexSamplers[firstSlot + i] = sampler;
|
||||
d3d12CommandBuffer->vertexSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
|
||||
d3d12CommandBuffer->needVertexSamplerBind = true;
|
||||
}
|
||||
|
||||
if (d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] != container->activeTexture) {
|
||||
if (d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackTexture(
|
||||
d3d12CommandBuffer,
|
||||
container->activeTexture);
|
||||
|
||||
d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] = container->activeTexture;
|
||||
d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needVertexSamplerBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4743,10 +4743,10 @@ static void D3D12_BindVertexStorageTextures(
|
||||
D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
|
||||
D3D12Texture *texture = container->activeTexture;
|
||||
|
||||
if (d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] != texture) {
|
||||
if (d3d12CommandBuffer->vertexStorageTextureDescriptorHandles[firstSlot + i].ptr != texture->srvHandle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
|
||||
|
||||
d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] = texture;
|
||||
d3d12CommandBuffer->vertexStorageTextureDescriptorHandles[firstSlot + i] = texture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needVertexStorageTextureBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4762,12 +4762,12 @@ static void D3D12_BindVertexStorageBuffers(
|
||||
|
||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||
D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
|
||||
if (d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] != container->activeBuffer) {
|
||||
if (d3d12CommandBuffer->vertexStorageBufferDescriptorHandles[firstSlot + i].ptr != container->activeBuffer->srvDescriptor.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackBuffer(
|
||||
d3d12CommandBuffer,
|
||||
container->activeBuffer);
|
||||
|
||||
d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] = container->activeBuffer;
|
||||
d3d12CommandBuffer->vertexStorageBufferDescriptorHandles[firstSlot + i] = container->activeBuffer->srvDescriptor.cpuHandle;
|
||||
d3d12CommandBuffer->needVertexStorageBufferBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4785,21 +4785,21 @@ static void D3D12_BindFragmentSamplers(
|
||||
D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
|
||||
D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (d3d12CommandBuffer->fragmentSamplers[firstSlot + i] != sampler) {
|
||||
if (d3d12CommandBuffer->fragmentSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackSampler(
|
||||
d3d12CommandBuffer,
|
||||
sampler);
|
||||
|
||||
d3d12CommandBuffer->fragmentSamplers[firstSlot + i] = sampler;
|
||||
d3d12CommandBuffer->fragmentSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
|
||||
d3d12CommandBuffer->needFragmentSamplerBind = true;
|
||||
}
|
||||
|
||||
if (d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] != container->activeTexture) {
|
||||
if (d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackTexture(
|
||||
d3d12CommandBuffer,
|
||||
container->activeTexture);
|
||||
|
||||
d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] = container->activeTexture;
|
||||
d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needFragmentSamplerBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4817,10 +4817,10 @@ static void D3D12_BindFragmentStorageTextures(
|
||||
D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
|
||||
D3D12Texture *texture = container->activeTexture;
|
||||
|
||||
if (d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] != texture) {
|
||||
if (d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles[firstSlot + i].ptr != texture->srvHandle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
|
||||
|
||||
d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] = texture;
|
||||
d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles[firstSlot + i] = texture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needFragmentStorageTextureBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4837,12 +4837,12 @@ static void D3D12_BindFragmentStorageBuffers(
|
||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||
D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
|
||||
|
||||
if (d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] != container->activeBuffer) {
|
||||
if (d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles[firstSlot + i].ptr != container->activeBuffer->srvDescriptor.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackBuffer(
|
||||
d3d12CommandBuffer,
|
||||
container->activeBuffer);
|
||||
|
||||
d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] = container->activeBuffer;
|
||||
d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles[firstSlot + i] = container->activeBuffer->srvDescriptor.cpuHandle;
|
||||
d3d12CommandBuffer->needFragmentStorageBufferBind = true;
|
||||
}
|
||||
}
|
||||
@@ -4923,6 +4923,9 @@ static void D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
gpuBaseDescriptor->ptr = heap->descriptorHeapGPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
|
||||
|
||||
for (Uint32 i = 0; i < resourceHandleCount; i += 1) {
|
||||
// This will crash the driver if it gets a null handle! Cool!
|
||||
if (resourceDescriptorHandles[i].ptr != 0)
|
||||
{
|
||||
ID3D12Device_CopyDescriptorsSimple(
|
||||
commandBuffer->renderer->device,
|
||||
1,
|
||||
@@ -4933,6 +4936,7 @@ static void D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
heap->currentDescriptorIndex += 1;
|
||||
gpuHeapCpuHandle.ptr += heap->descriptorSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
@@ -4961,19 +4965,21 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
0,
|
||||
commandBuffer->vertexBufferCount,
|
||||
vertexBufferViews);
|
||||
|
||||
commandBuffer->needVertexBufferBind = false;
|
||||
}
|
||||
|
||||
if (commandBuffer->needVertexSamplerBind) {
|
||||
if (graphicsPipeline->vertexSamplerCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexSamplers[i]->handle.cpuHandle;
|
||||
if (graphicsPipeline->header.num_vertex_samplers > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_samplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexSamplerDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
cpuHandles,
|
||||
graphicsPipeline->vertexSamplerCount,
|
||||
graphicsPipeline->header.num_vertex_samplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -4981,15 +4987,15 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
graphicsPipeline->rootSignature->vertexSamplerRootIndex,
|
||||
gpuDescriptorHandle);
|
||||
|
||||
for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexSamplerTextures[i]->srvHandle.cpuHandle;
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_samplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexSamplerTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->vertexSamplerCount,
|
||||
graphicsPipeline->header.num_vertex_samplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5001,16 +5007,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needVertexStorageTextureBind) {
|
||||
if (graphicsPipeline->vertexStorageTextureCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexStorageTextures[i]->srvHandle.cpuHandle;
|
||||
if (graphicsPipeline->header.num_vertex_storage_textures > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_storage_textures; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexStorageTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->vertexStorageTextureCount,
|
||||
graphicsPipeline->header.num_vertex_storage_textures,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5022,16 +5028,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needVertexStorageBufferBind) {
|
||||
if (graphicsPipeline->vertexStorageBufferCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexStorageBuffers[i]->srvDescriptor.cpuHandle;
|
||||
if (graphicsPipeline->header.num_vertex_storage_buffers > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_storage_buffers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->vertexStorageBufferDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->vertexStorageBufferCount,
|
||||
graphicsPipeline->header.num_vertex_storage_buffers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5044,7 +5050,7 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
|
||||
for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
|
||||
if (commandBuffer->needVertexUniformBufferBind[i]) {
|
||||
if (graphicsPipeline->vertexUniformBufferCount > i) {
|
||||
if (graphicsPipeline->header.num_vertex_uniform_buffers > i) {
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
|
||||
commandBuffer->graphicsCommandList,
|
||||
graphicsPipeline->rootSignature->vertexUniformBufferRootIndex[i],
|
||||
@@ -5055,16 +5061,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needFragmentSamplerBind) {
|
||||
if (graphicsPipeline->fragmentSamplerCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentSamplers[i]->handle.cpuHandle;
|
||||
if (graphicsPipeline->header.num_fragment_samplers > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_samplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentSamplerDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
cpuHandles,
|
||||
graphicsPipeline->fragmentSamplerCount,
|
||||
graphicsPipeline->header.num_fragment_samplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5072,15 +5078,15 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
graphicsPipeline->rootSignature->fragmentSamplerRootIndex,
|
||||
gpuDescriptorHandle);
|
||||
|
||||
for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentSamplerTextures[i]->srvHandle.cpuHandle;
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_samplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentSamplerTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->fragmentSamplerCount,
|
||||
graphicsPipeline->header.num_fragment_samplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5092,16 +5098,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needFragmentStorageTextureBind) {
|
||||
if (graphicsPipeline->fragmentStorageTextureCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentStorageTextures[i]->srvHandle.cpuHandle;
|
||||
if (graphicsPipeline->header.num_fragment_storage_textures > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_storage_textures; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentStorageTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->fragmentStorageTextureCount,
|
||||
graphicsPipeline->header.num_fragment_storage_textures,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5113,16 +5119,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needFragmentStorageBufferBind) {
|
||||
if (graphicsPipeline->fragmentStorageBufferCount > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentStorageBuffers[i]->srvDescriptor.cpuHandle;
|
||||
if (graphicsPipeline->header.num_fragment_storage_buffers > 0) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_storage_buffers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->fragmentStorageBufferDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
graphicsPipeline->fragmentStorageBufferCount,
|
||||
graphicsPipeline->header.num_fragment_storage_buffers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
|
||||
@@ -5135,7 +5141,7 @@ static void D3D12_INTERNAL_BindGraphicsResources(
|
||||
|
||||
for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
|
||||
if (commandBuffer->needFragmentUniformBufferBind[i]) {
|
||||
if (graphicsPipeline->fragmentUniformBufferCount > i) {
|
||||
if (graphicsPipeline->header.num_fragment_uniform_buffers > i) {
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
|
||||
commandBuffer->graphicsCommandList,
|
||||
graphicsPipeline->rootSignature->fragmentUniformBufferRootIndex[i],
|
||||
@@ -5300,15 +5306,15 @@ static void D3D12_EndRenderPass(
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexBufferOffsets);
|
||||
d3d12CommandBuffer->vertexBufferCount = 0;
|
||||
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextures);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexSamplers);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexStorageTextures);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexStorageBuffers);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexSamplerDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->vertexStorageBufferDescriptorHandles);
|
||||
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextures);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentSamplers);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextures);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentStorageBuffers);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentSamplerDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles);
|
||||
}
|
||||
|
||||
// Compute Pass
|
||||
@@ -5342,6 +5348,7 @@ static void D3D12_BeginComputePass(
|
||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||
|
||||
d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i] = subresource;
|
||||
d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles[i] = subresource->uavHandle.cpuHandle;
|
||||
|
||||
D3D12_INTERNAL_TrackTexture(
|
||||
d3d12CommandBuffer,
|
||||
@@ -5360,6 +5367,7 @@ static void D3D12_BeginComputePass(
|
||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||
|
||||
d3d12CommandBuffer->computeReadWriteStorageBuffers[i] = buffer;
|
||||
d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles[i] = buffer->uavDescriptor.cpuHandle;
|
||||
|
||||
D3D12_INTERNAL_TrackBuffer(
|
||||
d3d12CommandBuffer,
|
||||
@@ -5401,7 +5409,7 @@ static void D3D12_BindComputePipeline(
|
||||
d3d12CommandBuffer->needComputeUniformBufferBind[i] = true;
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
|
||||
for (Uint32 i = 0; i < pipeline->header.numUniformBuffers; i += 1) {
|
||||
if (d3d12CommandBuffer->computeUniformBuffers[i] == NULL) {
|
||||
d3d12CommandBuffer->computeUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
|
||||
d3d12CommandBuffer);
|
||||
@@ -5411,9 +5419,9 @@ static void D3D12_BindComputePipeline(
|
||||
D3D12_INTERNAL_TrackComputePipeline(d3d12CommandBuffer, pipeline);
|
||||
|
||||
// Bind write-only resources after setting root signature
|
||||
if (pipeline->numReadWriteStorageTextures > 0) {
|
||||
for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) {
|
||||
cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i]->uavHandle.cpuHandle;
|
||||
if (pipeline->header.numReadWriteStorageTextures > 0) {
|
||||
for (Uint32 i = 0; i < pipeline->header.numReadWriteStorageTextures; i += 1) {
|
||||
cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
@@ -5429,9 +5437,9 @@ static void D3D12_BindComputePipeline(
|
||||
gpuDescriptorHandle);
|
||||
}
|
||||
|
||||
if (pipeline->numReadWriteStorageBuffers > 0) {
|
||||
for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) {
|
||||
cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageBuffers[i]->uavDescriptor.cpuHandle;
|
||||
if (pipeline->header.numReadWriteStorageBuffers > 0) {
|
||||
for (Uint32 i = 0; i < pipeline->header.numReadWriteStorageBuffers; i += 1) {
|
||||
cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
@@ -5460,21 +5468,21 @@ static void D3D12_BindComputeSamplers(
|
||||
D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
|
||||
D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (d3d12CommandBuffer->computeSamplers[firstSlot + i] != sampler) {
|
||||
if (d3d12CommandBuffer->computeSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackSampler(
|
||||
d3d12CommandBuffer,
|
||||
(D3D12Sampler *)textureSamplerBindings[i].sampler);
|
||||
|
||||
d3d12CommandBuffer->computeSamplers[firstSlot + i] = (D3D12Sampler *)textureSamplerBindings[i].sampler;
|
||||
d3d12CommandBuffer->computeSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
|
||||
d3d12CommandBuffer->needComputeSamplerBind = true;
|
||||
}
|
||||
|
||||
if (d3d12CommandBuffer->computeSamplerTextures[firstSlot + i] != container->activeTexture) {
|
||||
if (d3d12CommandBuffer->computeSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
|
||||
D3D12_INTERNAL_TrackTexture(
|
||||
d3d12CommandBuffer,
|
||||
container->activeTexture);
|
||||
|
||||
d3d12CommandBuffer->computeSamplerTextures[firstSlot + i] = container->activeTexture;
|
||||
d3d12CommandBuffer->computeSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needComputeSamplerBind = true;
|
||||
}
|
||||
}
|
||||
@@ -5511,6 +5519,7 @@ static void D3D12_BindComputeStorageTextures(
|
||||
container->activeTexture);
|
||||
|
||||
d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = container->activeTexture;
|
||||
d3d12CommandBuffer->computeReadOnlyStorageTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
|
||||
d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = true;
|
||||
}
|
||||
}
|
||||
@@ -5548,6 +5557,7 @@ static void D3D12_BindComputeStorageBuffers(
|
||||
buffer);
|
||||
|
||||
d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer;
|
||||
d3d12CommandBuffer->computeReadOnlyStorageBufferDescriptorHandles[firstSlot + i] = buffer->srvDescriptor.cpuHandle;
|
||||
d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true;
|
||||
}
|
||||
}
|
||||
@@ -5583,16 +5593,16 @@ static void D3D12_INTERNAL_BindComputeResources(
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
|
||||
|
||||
if (commandBuffer->needComputeSamplerBind) {
|
||||
if (computePipeline->numSamplers > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeSamplers[i]->handle.cpuHandle;
|
||||
if (computePipeline->header.numSamplers > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->header.numSamplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeSamplerDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
cpuHandles,
|
||||
computePipeline->numSamplers,
|
||||
computePipeline->header.numSamplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
|
||||
@@ -5600,15 +5610,15 @@ static void D3D12_INTERNAL_BindComputeResources(
|
||||
computePipeline->rootSignature->samplerRootIndex,
|
||||
gpuDescriptorHandle);
|
||||
|
||||
for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeSamplerTextures[i]->srvHandle.cpuHandle;
|
||||
for (Uint32 i = 0; i < computePipeline->header.numSamplers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeSamplerTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
computePipeline->numSamplers,
|
||||
computePipeline->header.numSamplers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
|
||||
@@ -5620,16 +5630,16 @@ static void D3D12_INTERNAL_BindComputeResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
|
||||
if (computePipeline->numReadOnlyStorageTextures > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageTextures; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextures[i]->srvHandle.cpuHandle;
|
||||
if (computePipeline->header.numReadonlyStorageTextures > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->header.numReadonlyStorageTextures; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextureDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
computePipeline->numReadOnlyStorageTextures,
|
||||
computePipeline->header.numReadonlyStorageTextures,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
|
||||
@@ -5641,16 +5651,16 @@ static void D3D12_INTERNAL_BindComputeResources(
|
||||
}
|
||||
|
||||
if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
|
||||
if (computePipeline->numReadOnlyStorageBuffers > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageBuffers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srvDescriptor.cpuHandle;
|
||||
if (computePipeline->header.numReadonlyStorageBuffers > 0) {
|
||||
for (Uint32 i = 0; i < computePipeline->header.numReadonlyStorageBuffers; i += 1) {
|
||||
cpuHandles[i] = commandBuffer->computeReadOnlyStorageBufferDescriptorHandles[i];
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_WriteGPUDescriptors(
|
||||
commandBuffer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cpuHandles,
|
||||
computePipeline->numReadOnlyStorageBuffers,
|
||||
computePipeline->header.numReadonlyStorageBuffers,
|
||||
&gpuDescriptorHandle);
|
||||
|
||||
ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
|
||||
@@ -5663,7 +5673,7 @@ static void D3D12_INTERNAL_BindComputeResources(
|
||||
|
||||
for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
|
||||
if (commandBuffer->needComputeUniformBufferBind[i]) {
|
||||
if (computePipeline->numUniformBuffers > i) {
|
||||
if (computePipeline->header.numUniformBuffers > i) {
|
||||
ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(
|
||||
commandBuffer->graphicsCommandList,
|
||||
computePipeline->rootSignature->uniformBufferRootIndex[i],
|
||||
@@ -5762,8 +5772,11 @@ static void D3D12_EndComputePass(
|
||||
}
|
||||
}
|
||||
|
||||
SDL_zeroa(d3d12CommandBuffer->computeSamplerTextures);
|
||||
SDL_zeroa(d3d12CommandBuffer->computeSamplers);
|
||||
SDL_zeroa(d3d12CommandBuffer->computeSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->computeSamplerDescriptorHandles);
|
||||
|
||||
SDL_zeroa(d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles);
|
||||
|
||||
d3d12CommandBuffer->currentComputePipeline = NULL;
|
||||
}
|
||||
@@ -7352,20 +7365,22 @@ static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer(
|
||||
SDL_zeroa(commandBuffer->vertexBufferOffsets);
|
||||
commandBuffer->vertexBufferCount = 0;
|
||||
|
||||
SDL_zeroa(commandBuffer->vertexSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->vertexSamplers);
|
||||
SDL_zeroa(commandBuffer->vertexStorageTextures);
|
||||
SDL_zeroa(commandBuffer->vertexStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->vertexSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->vertexSamplerDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->vertexStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->vertexStorageBufferDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->vertexUniformBuffers);
|
||||
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplers);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageTextures);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageBufferDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->fragmentUniformBuffers);
|
||||
|
||||
SDL_zeroa(commandBuffer->computeSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->computeSamplers);
|
||||
SDL_zeroa(commandBuffer->computeSamplerTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->computeSamplerDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->computeReadOnlyStorageTextureDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->computeReadOnlyStorageBufferDescriptorHandles);
|
||||
SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures);
|
||||
SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources);
|
||||
@@ -8338,6 +8353,7 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
|
||||
IDXGIFactory4 *factory4;
|
||||
IDXGIFactory6 *factory6;
|
||||
IDXGIAdapter1 *adapter;
|
||||
bool supports_64UAVs = false;
|
||||
|
||||
// Can we load D3D12?
|
||||
|
||||
@@ -8426,12 +8442,39 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_COMPILE_TIME_ASSERT(featurelevel, D3D_FEATURE_LEVEL_CHOICE < D3D_FEATURE_LEVEL_11_1);
|
||||
|
||||
// Check feature level 11_1 first, guarantees 64+ UAVs unlike 11_0 Tier1
|
||||
res = D3D12CreateDeviceFunc(
|
||||
(IUnknown *)adapter,
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_GUID(D3D_IID_ID3D12Device),
|
||||
(void **)&device);
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
supports_64UAVs = true;
|
||||
} else {
|
||||
res = D3D12CreateDeviceFunc(
|
||||
(IUnknown *)adapter,
|
||||
D3D_FEATURE_LEVEL_CHOICE,
|
||||
D3D_GUID(D3D_IID_ID3D12Device),
|
||||
(void **)&device);
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS featureOptions;
|
||||
SDL_zero(featureOptions);
|
||||
|
||||
res = ID3D12Device_CheckFeatureSupport(
|
||||
device,
|
||||
D3D12_FEATURE_D3D12_OPTIONS,
|
||||
&featureOptions,
|
||||
sizeof(featureOptions));
|
||||
if (SUCCEEDED(res) && featureOptions.ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_2) {
|
||||
supports_64UAVs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
ID3D12Device_Release(device);
|
||||
}
|
||||
@@ -8441,6 +8484,11 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
|
||||
SDL_UnloadObject(d3d12Dll);
|
||||
SDL_UnloadObject(dxgiDll);
|
||||
|
||||
if (!supports_64UAVs) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Tier 2 Resource binding is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(res)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not create D3D12Device with feature level " D3D_FEATURE_LEVEL_CHOICE_STR);
|
||||
return false;
|
||||
@@ -8819,6 +8867,12 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
||||
// Initialize the D3D12 debug layer, if applicable
|
||||
if (debugMode) {
|
||||
bool hasD3d12Debug = D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
|
||||
#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
||||
if (hasD3d12Debug) {
|
||||
SDL_LogInfo(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
"Validation layers enabled, expect debug level performance!");
|
||||
#else
|
||||
if (hasDxgiDebug && hasD3d12Debug) {
|
||||
SDL_LogInfo(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
@@ -8827,6 +8881,7 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
||||
SDL_LogWarn(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
"Validation layers partially enabled, some warnings may not be available");
|
||||
#endif
|
||||
} else {
|
||||
SDL_LogWarn(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
@@ -9159,8 +9214,23 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUShaderFormat shaderFormats = SDL_GPU_SHADERFORMAT_DXBC;
|
||||
|
||||
D3D12_FEATURE_DATA_SHADER_MODEL shaderModel;
|
||||
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_0;
|
||||
|
||||
res = ID3D12Device_CheckFeatureSupport(
|
||||
renderer->device,
|
||||
D3D12_FEATURE_SHADER_MODEL,
|
||||
&shaderModel,
|
||||
sizeof(shaderModel));
|
||||
if (SUCCEEDED(res) && shaderModel.HighestShaderModel >= D3D_SHADER_MODEL_6_0) {
|
||||
shaderFormats |= SDL_GPU_SHADERFORMAT_DXIL;
|
||||
}
|
||||
|
||||
ASSIGN_DRIVER(D3D12)
|
||||
result->driverData = (SDL_GPURenderer *)renderer;
|
||||
result->shader_formats = shaderFormats;
|
||||
result->debug_mode = debugMode;
|
||||
renderer->sdlGPUDevice = result;
|
||||
|
||||
|
@@ -476,33 +476,21 @@ typedef struct MetalShader
|
||||
|
||||
typedef struct MetalGraphicsPipeline
|
||||
{
|
||||
GraphicsPipelineCommonHeader header;
|
||||
|
||||
id<MTLRenderPipelineState> handle;
|
||||
|
||||
SDL_GPURasterizerState rasterizerState;
|
||||
SDL_GPUPrimitiveType primitiveType;
|
||||
|
||||
id<MTLDepthStencilState> depth_stencil_state;
|
||||
|
||||
Uint32 vertexSamplerCount;
|
||||
Uint32 vertexUniformBufferCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexStorageTextureCount;
|
||||
|
||||
Uint32 fragmentSamplerCount;
|
||||
Uint32 fragmentUniformBufferCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentStorageTextureCount;
|
||||
} MetalGraphicsPipeline;
|
||||
|
||||
typedef struct MetalComputePipeline
|
||||
{
|
||||
ComputePipelineCommonHeader header;
|
||||
|
||||
id<MTLComputePipelineState> handle;
|
||||
Uint32 numSamplers;
|
||||
Uint32 numReadonlyStorageTextures;
|
||||
Uint32 numReadWriteStorageTextures;
|
||||
Uint32 numReadonlyStorageBuffers;
|
||||
Uint32 numReadWriteStorageBuffers;
|
||||
Uint32 numUniformBuffers;
|
||||
Uint32 threadcountX;
|
||||
Uint32 threadcountY;
|
||||
Uint32 threadcountZ;
|
||||
@@ -900,6 +888,7 @@ static void METAL_INTERNAL_DestroyTextureContainer(
|
||||
container->textures[i]->handle = nil;
|
||||
SDL_free(container->textures[i]);
|
||||
}
|
||||
SDL_DestroyProperties(container->header.info.props);
|
||||
if (container->debugName != NULL) {
|
||||
SDL_free(container->debugName);
|
||||
}
|
||||
@@ -1059,12 +1048,12 @@ static SDL_GPUComputePipeline *METAL_CreateComputePipeline(
|
||||
|
||||
pipeline = SDL_calloc(1, sizeof(MetalComputePipeline));
|
||||
pipeline->handle = handle;
|
||||
pipeline->numSamplers = createinfo->num_samplers;
|
||||
pipeline->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
|
||||
pipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
|
||||
pipeline->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
|
||||
pipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
|
||||
pipeline->numUniformBuffers = createinfo->num_uniform_buffers;
|
||||
pipeline->header.numSamplers = createinfo->num_samplers;
|
||||
pipeline->header.numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
|
||||
pipeline->header.numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
|
||||
pipeline->header.numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
|
||||
pipeline->header.numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
|
||||
pipeline->header.numUniformBuffers = createinfo->num_uniform_buffers;
|
||||
pipeline->threadcountX = createinfo->threadcount_x;
|
||||
pipeline->threadcountY = createinfo->threadcount_y;
|
||||
pipeline->threadcountZ = createinfo->threadcount_z;
|
||||
@@ -1207,14 +1196,14 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
|
||||
result->depth_stencil_state = depthStencilState;
|
||||
result->rasterizerState = createinfo->rasterizer_state;
|
||||
result->primitiveType = createinfo->primitive_type;
|
||||
result->vertexSamplerCount = vertexShader->numSamplers;
|
||||
result->vertexUniformBufferCount = vertexShader->numUniformBuffers;
|
||||
result->vertexStorageBufferCount = vertexShader->numStorageBuffers;
|
||||
result->vertexStorageTextureCount = vertexShader->numStorageTextures;
|
||||
result->fragmentSamplerCount = fragmentShader->numSamplers;
|
||||
result->fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
|
||||
result->fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
|
||||
result->fragmentStorageTextureCount = fragmentShader->numStorageTextures;
|
||||
result->header.num_vertex_samplers = vertexShader->numSamplers;
|
||||
result->header.num_vertex_uniform_buffers = vertexShader->numUniformBuffers;
|
||||
result->header.num_vertex_storage_buffers = vertexShader->numStorageBuffers;
|
||||
result->header.num_vertex_storage_textures = vertexShader->numStorageTextures;
|
||||
result->header.num_fragment_samplers = fragmentShader->numSamplers;
|
||||
result->header.num_fragment_uniform_buffers = fragmentShader->numUniformBuffers;
|
||||
result->header.num_fragment_storage_buffers = fragmentShader->numStorageBuffers;
|
||||
result->header.num_fragment_storage_textures = fragmentShader->numStorageTextures;
|
||||
return (SDL_GPUGraphicsPipeline *)result;
|
||||
}
|
||||
}
|
||||
@@ -1789,7 +1778,8 @@ static void METAL_UploadToTexture(
|
||||
copyFromBuffer:bufferContainer->activeBuffer->handle
|
||||
sourceOffset:source->offset
|
||||
sourceBytesPerRow:BytesPerRow(destination->w, textureContainer->header.info.format)
|
||||
sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, destination->d)
|
||||
// sourceBytesPerImage expects the stride between 2D images (slices) of a 3D texture, not the size of the entire region
|
||||
sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, 1)
|
||||
sourceSize:MTLSizeMake(destination->w, destination->h, destination->d)
|
||||
toTexture:metalTexture->handle
|
||||
destinationSlice:destination->layer
|
||||
@@ -2412,14 +2402,14 @@ static void METAL_BindGraphicsPipeline(
|
||||
metalCommandBuffer->needFragmentUniformBufferBind[i] = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
|
||||
for (i = 0; i < pipeline->header.num_vertex_uniform_buffers; i += 1) {
|
||||
if (metalCommandBuffer->vertexUniformBuffers[i] == NULL) {
|
||||
metalCommandBuffer->vertexUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
|
||||
metalCommandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
|
||||
for (i = 0; i < pipeline->header.num_fragment_uniform_buffers; i += 1) {
|
||||
if (metalCommandBuffer->fragmentUniformBuffers[i] == NULL) {
|
||||
metalCommandBuffer->fragmentUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
|
||||
metalCommandBuffer);
|
||||
@@ -2650,11 +2640,11 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Vertex Samplers+Textures
|
||||
|
||||
if (commandBuffer->needVertexSamplerBind) {
|
||||
if (graphicsPipeline->vertexSamplerCount > 0) {
|
||||
if (graphicsPipeline->header.num_vertex_samplers > 0) {
|
||||
[commandBuffer->renderEncoder setVertexSamplerStates:commandBuffer->vertexSamplers
|
||||
withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
|
||||
withRange:NSMakeRange(0, graphicsPipeline->header.num_vertex_samplers)];
|
||||
[commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexTextures
|
||||
withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
|
||||
withRange:NSMakeRange(0, graphicsPipeline->header.num_vertex_samplers)];
|
||||
}
|
||||
commandBuffer->needVertexSamplerBind = false;
|
||||
}
|
||||
@@ -2662,10 +2652,10 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Vertex Storage Textures
|
||||
|
||||
if (commandBuffer->needVertexStorageTextureBind) {
|
||||
if (graphicsPipeline->vertexStorageTextureCount > 0) {
|
||||
if (graphicsPipeline->header.num_vertex_storage_textures > 0) {
|
||||
[commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexStorageTextures
|
||||
withRange:NSMakeRange(graphicsPipeline->vertexSamplerCount,
|
||||
graphicsPipeline->vertexStorageTextureCount)];
|
||||
withRange:NSMakeRange(graphicsPipeline->header.num_vertex_samplers,
|
||||
graphicsPipeline->header.num_vertex_storage_textures)];
|
||||
}
|
||||
commandBuffer->needVertexStorageTextureBind = false;
|
||||
}
|
||||
@@ -2673,20 +2663,20 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Vertex Storage Buffers
|
||||
|
||||
if (commandBuffer->needVertexStorageBufferBind) {
|
||||
if (graphicsPipeline->vertexStorageBufferCount > 0) {
|
||||
if (graphicsPipeline->header.num_vertex_storage_buffers > 0) {
|
||||
[commandBuffer->renderEncoder setVertexBuffers:commandBuffer->vertexStorageBuffers
|
||||
offsets:offsets
|
||||
withRange:NSMakeRange(graphicsPipeline->vertexUniformBufferCount,
|
||||
graphicsPipeline->vertexStorageBufferCount)];
|
||||
withRange:NSMakeRange(graphicsPipeline->header.num_vertex_uniform_buffers,
|
||||
graphicsPipeline->header.num_vertex_storage_buffers)];
|
||||
}
|
||||
commandBuffer->needVertexStorageBufferBind = false;
|
||||
}
|
||||
|
||||
// Vertex Uniform Buffers
|
||||
|
||||
for (Uint32 i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_uniform_buffers; i += 1) {
|
||||
if (commandBuffer->needVertexUniformBufferBind[i]) {
|
||||
if (graphicsPipeline->vertexUniformBufferCount > i) {
|
||||
if (graphicsPipeline->header.num_vertex_uniform_buffers > i) {
|
||||
[commandBuffer->renderEncoder
|
||||
setVertexBuffer:commandBuffer->vertexUniformBuffers[i]->handle
|
||||
offset:commandBuffer->vertexUniformBuffers[i]->drawOffset
|
||||
@@ -2699,11 +2689,11 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Fragment Samplers+Textures
|
||||
|
||||
if (commandBuffer->needFragmentSamplerBind) {
|
||||
if (graphicsPipeline->fragmentSamplerCount > 0) {
|
||||
if (graphicsPipeline->header.num_fragment_samplers > 0) {
|
||||
[commandBuffer->renderEncoder setFragmentSamplerStates:commandBuffer->fragmentSamplers
|
||||
withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
|
||||
withRange:NSMakeRange(0, graphicsPipeline->header.num_fragment_samplers)];
|
||||
[commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentTextures
|
||||
withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
|
||||
withRange:NSMakeRange(0, graphicsPipeline->header.num_fragment_samplers)];
|
||||
}
|
||||
commandBuffer->needFragmentSamplerBind = false;
|
||||
}
|
||||
@@ -2711,10 +2701,10 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Fragment Storage Textures
|
||||
|
||||
if (commandBuffer->needFragmentStorageTextureBind) {
|
||||
if (graphicsPipeline->fragmentStorageTextureCount > 0) {
|
||||
if (graphicsPipeline->header.num_fragment_storage_textures > 0) {
|
||||
[commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentStorageTextures
|
||||
withRange:NSMakeRange(graphicsPipeline->fragmentSamplerCount,
|
||||
graphicsPipeline->fragmentStorageTextureCount)];
|
||||
withRange:NSMakeRange(graphicsPipeline->header.num_fragment_samplers,
|
||||
graphicsPipeline->header.num_fragment_storage_textures)];
|
||||
}
|
||||
commandBuffer->needFragmentStorageTextureBind = false;
|
||||
}
|
||||
@@ -2722,20 +2712,20 @@ static void METAL_INTERNAL_BindGraphicsResources(
|
||||
// Fragment Storage Buffers
|
||||
|
||||
if (commandBuffer->needFragmentStorageBufferBind) {
|
||||
if (graphicsPipeline->fragmentStorageBufferCount > 0) {
|
||||
if (graphicsPipeline->header.num_fragment_storage_buffers > 0) {
|
||||
[commandBuffer->renderEncoder setFragmentBuffers:commandBuffer->fragmentStorageBuffers
|
||||
offsets:offsets
|
||||
withRange:NSMakeRange(graphicsPipeline->fragmentUniformBufferCount,
|
||||
graphicsPipeline->fragmentStorageBufferCount)];
|
||||
withRange:NSMakeRange(graphicsPipeline->header.num_fragment_uniform_buffers,
|
||||
graphicsPipeline->header.num_fragment_storage_buffers)];
|
||||
}
|
||||
commandBuffer->needFragmentStorageBufferBind = false;
|
||||
}
|
||||
|
||||
// Fragment Uniform Buffers
|
||||
|
||||
for (Uint32 i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) {
|
||||
for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_uniform_buffers; i += 1) {
|
||||
if (commandBuffer->needFragmentUniformBufferBind[i]) {
|
||||
if (graphicsPipeline->fragmentUniformBufferCount > i) {
|
||||
if (graphicsPipeline->header.num_fragment_uniform_buffers > i) {
|
||||
[commandBuffer->renderEncoder
|
||||
setFragmentBuffer:commandBuffer->fragmentUniformBuffers[i]->handle
|
||||
offset:commandBuffer->fragmentUniformBuffers[i]->drawOffset
|
||||
@@ -2754,38 +2744,38 @@ static void METAL_INTERNAL_BindComputeResources(
|
||||
NSUInteger offsets[MAX_STORAGE_BUFFERS_PER_STAGE] = { 0 };
|
||||
|
||||
if (commandBuffer->needComputeSamplerBind) {
|
||||
if (computePipeline->numSamplers > 0) {
|
||||
if (computePipeline->header.numSamplers > 0) {
|
||||
[commandBuffer->computeEncoder setTextures:commandBuffer->computeSamplerTextures
|
||||
withRange:NSMakeRange(0, computePipeline->numSamplers)];
|
||||
withRange:NSMakeRange(0, computePipeline->header.numSamplers)];
|
||||
[commandBuffer->computeEncoder setSamplerStates:commandBuffer->computeSamplers
|
||||
withRange:NSMakeRange(0, computePipeline->numSamplers)];
|
||||
withRange:NSMakeRange(0, computePipeline->header.numSamplers)];
|
||||
}
|
||||
commandBuffer->needComputeSamplerBind = false;
|
||||
}
|
||||
|
||||
if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
|
||||
if (computePipeline->numReadonlyStorageTextures > 0) {
|
||||
if (computePipeline->header.numReadonlyStorageTextures > 0) {
|
||||
[commandBuffer->computeEncoder setTextures:commandBuffer->computeReadOnlyTextures
|
||||
withRange:NSMakeRange(
|
||||
computePipeline->numSamplers,
|
||||
computePipeline->numReadonlyStorageTextures)];
|
||||
computePipeline->header.numSamplers,
|
||||
computePipeline->header.numReadonlyStorageTextures)];
|
||||
}
|
||||
commandBuffer->needComputeReadOnlyStorageTextureBind = false;
|
||||
}
|
||||
|
||||
if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
|
||||
if (computePipeline->numReadonlyStorageBuffers > 0) {
|
||||
if (computePipeline->header.numReadonlyStorageBuffers > 0) {
|
||||
[commandBuffer->computeEncoder setBuffers:commandBuffer->computeReadOnlyBuffers
|
||||
offsets:offsets
|
||||
withRange:NSMakeRange(computePipeline->numUniformBuffers,
|
||||
computePipeline->numReadonlyStorageBuffers)];
|
||||
withRange:NSMakeRange(computePipeline->header.numUniformBuffers,
|
||||
computePipeline->header.numReadonlyStorageBuffers)];
|
||||
}
|
||||
commandBuffer->needComputeReadOnlyStorageBufferBind = false;
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
|
||||
if (commandBuffer->needComputeUniformBufferBind[i]) {
|
||||
if (computePipeline->numUniformBuffers > i) {
|
||||
if (computePipeline->header.numUniformBuffers > i) {
|
||||
[commandBuffer->computeEncoder
|
||||
setBuffer:commandBuffer->computeUniformBuffers[i]->handle
|
||||
offset:commandBuffer->computeUniformBuffers[i]->drawOffset
|
||||
@@ -3133,7 +3123,7 @@ static void METAL_BindComputePipeline(
|
||||
metalCommandBuffer->needComputeUniformBufferBind[i] = true;
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
|
||||
for (Uint32 i = 0; i < pipeline->header.numUniformBuffers; i += 1) {
|
||||
if (metalCommandBuffer->computeUniformBuffers[i] == NULL) {
|
||||
metalCommandBuffer->computeUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
|
||||
metalCommandBuffer);
|
||||
@@ -3141,22 +3131,22 @@ static void METAL_BindComputePipeline(
|
||||
}
|
||||
|
||||
// Bind write-only resources
|
||||
if (pipeline->numReadWriteStorageTextures > 0) {
|
||||
if (pipeline->header.numReadWriteStorageTextures > 0) {
|
||||
[metalCommandBuffer->computeEncoder setTextures:metalCommandBuffer->computeReadWriteTextures
|
||||
withRange:NSMakeRange(
|
||||
pipeline->numSamplers +
|
||||
pipeline->numReadonlyStorageTextures,
|
||||
pipeline->numReadWriteStorageTextures)];
|
||||
pipeline->header.numSamplers +
|
||||
pipeline->header.numReadonlyStorageTextures,
|
||||
pipeline->header.numReadWriteStorageTextures)];
|
||||
}
|
||||
|
||||
NSUInteger offsets[MAX_COMPUTE_WRITE_BUFFERS] = { 0 };
|
||||
if (pipeline->numReadWriteStorageBuffers > 0) {
|
||||
if (pipeline->header.numReadWriteStorageBuffers > 0) {
|
||||
[metalCommandBuffer->computeEncoder setBuffers:metalCommandBuffer->computeReadWriteBuffers
|
||||
offsets:offsets
|
||||
withRange:NSMakeRange(
|
||||
pipeline->numUniformBuffers +
|
||||
pipeline->numReadonlyStorageBuffers,
|
||||
pipeline->numReadWriteStorageBuffers)];
|
||||
pipeline->header.numUniformBuffers +
|
||||
pipeline->header.numReadonlyStorageBuffers,
|
||||
pipeline->header.numReadWriteStorageBuffers)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4570,6 +4560,7 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
|
||||
SDL_GPUDevice *result = SDL_calloc(1, sizeof(SDL_GPUDevice));
|
||||
ASSIGN_DRIVER(METAL)
|
||||
result->driverData = (SDL_GPURenderer *)renderer;
|
||||
result->shader_formats = SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
renderer->sdlGPUDevice = result;
|
||||
|
||||
return result;
|
||||
|
@@ -822,13 +822,13 @@ typedef struct DescriptorSetLayout
|
||||
typedef struct GraphicsPipelineResourceLayoutHashTableKey
|
||||
{
|
||||
Uint32 vertexSamplerCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexStorageTextureCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexUniformBufferCount;
|
||||
|
||||
Uint32 fragmentSamplerCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentStorageTextureCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentUniformBufferCount;
|
||||
} GraphicsPipelineResourceLayoutHashTableKey;
|
||||
|
||||
@@ -846,18 +846,20 @@ typedef struct VulkanGraphicsPipelineResourceLayout
|
||||
DescriptorSetLayout *descriptorSetLayouts[4];
|
||||
|
||||
Uint32 vertexSamplerCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexStorageTextureCount;
|
||||
Uint32 vertexStorageBufferCount;
|
||||
Uint32 vertexUniformBufferCount;
|
||||
|
||||
Uint32 fragmentSamplerCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentStorageTextureCount;
|
||||
Uint32 fragmentStorageBufferCount;
|
||||
Uint32 fragmentUniformBufferCount;
|
||||
} VulkanGraphicsPipelineResourceLayout;
|
||||
|
||||
typedef struct VulkanGraphicsPipeline
|
||||
{
|
||||
GraphicsPipelineCommonHeader header;
|
||||
|
||||
VkPipeline pipeline;
|
||||
SDL_GPUPrimitiveType primitiveType;
|
||||
|
||||
@@ -901,6 +903,8 @@ typedef struct VulkanComputePipelineResourceLayout
|
||||
|
||||
typedef struct VulkanComputePipeline
|
||||
{
|
||||
ComputePipelineCommonHeader header;
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkPipeline pipeline;
|
||||
VulkanComputePipelineResourceLayout *resourceLayout;
|
||||
@@ -1038,25 +1042,33 @@ typedef struct VulkanCommandBuffer
|
||||
Uint32 vertexBufferCount;
|
||||
bool needVertexBufferBind;
|
||||
|
||||
VulkanTexture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanSampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanTexture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VulkanBuffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
VkImageView vertexSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkSampler vertexSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkImageView vertexStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VkBuffer vertexStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
VulkanTexture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanSampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanTexture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VulkanBuffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
VkImageView fragmentSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkSampler fragmentSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkImageView fragmentStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VkBuffer fragmentStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
VkImageView computeSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkSampler computeSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VkImageView readOnlyComputeStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VkBuffer readOnlyComputeStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
// Track these separately because barriers can happen mid compute pass
|
||||
VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
VkImageView readWriteComputeStorageTextureViewBindings[MAX_COMPUTE_WRITE_TEXTURES];
|
||||
VkBuffer readWriteComputeStorageBufferBindings[MAX_COMPUTE_WRITE_BUFFERS];
|
||||
|
||||
// Track these separately because they are barriered when the compute pass begins
|
||||
VulkanTextureSubresource *readWriteComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
|
||||
Uint32 readWriteComputeStorageTextureSubresourceCount;
|
||||
VulkanBuffer *readWriteComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
|
||||
|
||||
VulkanTexture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanSampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
|
||||
VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
|
||||
VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
|
||||
|
||||
// Uniform buffers
|
||||
|
||||
VulkanUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
|
||||
@@ -1096,6 +1108,7 @@ typedef struct VulkanCommandBuffer
|
||||
VulkanFenceHandle *inFlightFence;
|
||||
bool autoReleaseFence;
|
||||
|
||||
bool swapchainRequested;
|
||||
bool isDefrag; // Whether this CB was created for defragging
|
||||
} VulkanCommandBuffer;
|
||||
|
||||
@@ -1130,6 +1143,7 @@ struct VulkanRenderer
|
||||
VulkanExtensions supports;
|
||||
bool supportsDebugUtils;
|
||||
bool supportsColorspace;
|
||||
bool supportsPhysicalDeviceProperties2;
|
||||
bool supportsFillModeNonSolid;
|
||||
bool supportsMultiDrawIndirect;
|
||||
|
||||
@@ -1265,12 +1279,19 @@ static inline const char *VkErrorMessages(VkResult code)
|
||||
#undef ERR_TO_STR
|
||||
}
|
||||
|
||||
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
|
||||
#define SET_ERROR(fmt, msg) \
|
||||
do { \
|
||||
if (renderer->debugMode) { \
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
|
||||
} \
|
||||
SDL_SetError((fmt), (msg)); \
|
||||
} while (0)
|
||||
|
||||
#define SET_STRING_ERROR(msg) SET_ERROR("%s", msg)
|
||||
|
||||
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
|
||||
do { \
|
||||
SET_ERROR(fmt, msg); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
@@ -5126,8 +5147,8 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplers[i]->sampler;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplerBindings[i];
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -5150,7 +5171,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -5172,7 +5193,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pImageInfo = NULL;
|
||||
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBuffers[i]->buffer;
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBufferBindings[i];
|
||||
bufferInfos[bufferInfoCount].offset = 0;
|
||||
bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
|
||||
|
||||
@@ -5245,8 +5266,8 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplers[i]->sampler;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplerBindings[i];
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -5269,7 +5290,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -5291,7 +5312,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pImageInfo = NULL;
|
||||
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBuffers[i]->buffer;
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBufferBindings[i];
|
||||
bufferInfos[bufferInfoCount].offset = 0;
|
||||
bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
|
||||
|
||||
@@ -6069,7 +6090,6 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass(
|
||||
colorAttachmentReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachmentDescriptionCount += 1;
|
||||
colorAttachmentReferenceCount += 1;
|
||||
|
||||
if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
|
||||
VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
|
||||
@@ -6084,12 +6104,16 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass(
|
||||
attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
resolveReferences[resolveReferenceCount].attachment = attachmentDescriptionCount;
|
||||
resolveReferences[resolveReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
resolveReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
|
||||
resolveReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachmentDescriptionCount += 1;
|
||||
resolveReferenceCount += 1;
|
||||
} else {
|
||||
resolveReferences[colorAttachmentReferenceCount].attachment = VK_ATTACHMENT_UNUSED;
|
||||
}
|
||||
|
||||
colorAttachmentReferenceCount += 1;
|
||||
}
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
@@ -6565,6 +6589,16 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
|
||||
&nameInfo);
|
||||
}
|
||||
|
||||
// Put this data in the pipeline we can do validation in gpu.c
|
||||
graphicsPipeline->header.num_vertex_samplers = graphicsPipeline->resourceLayout->vertexSamplerCount;
|
||||
graphicsPipeline->header.num_vertex_storage_buffers = graphicsPipeline->resourceLayout->vertexStorageBufferCount;
|
||||
graphicsPipeline->header.num_vertex_storage_textures = graphicsPipeline->resourceLayout->vertexStorageTextureCount;
|
||||
graphicsPipeline->header.num_vertex_uniform_buffers = graphicsPipeline->resourceLayout->vertexUniformBufferCount;
|
||||
graphicsPipeline->header.num_fragment_samplers = graphicsPipeline->resourceLayout->fragmentSamplerCount;
|
||||
graphicsPipeline->header.num_fragment_storage_buffers = graphicsPipeline->resourceLayout->fragmentStorageBufferCount;
|
||||
graphicsPipeline->header.num_fragment_storage_textures = graphicsPipeline->resourceLayout->fragmentStorageTextureCount;
|
||||
graphicsPipeline->header.num_fragment_uniform_buffers = graphicsPipeline->resourceLayout->fragmentUniformBufferCount;
|
||||
|
||||
return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
|
||||
}
|
||||
|
||||
@@ -6659,6 +6693,14 @@ static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
|
||||
&nameInfo);
|
||||
}
|
||||
|
||||
// Track these here for debug layer
|
||||
vulkanComputePipeline->header.numSamplers = vulkanComputePipeline->resourceLayout->numSamplers;
|
||||
vulkanComputePipeline->header.numReadonlyStorageTextures = vulkanComputePipeline->resourceLayout->numReadonlyStorageTextures;
|
||||
vulkanComputePipeline->header.numReadonlyStorageBuffers = vulkanComputePipeline->resourceLayout->numReadonlyStorageBuffers;
|
||||
vulkanComputePipeline->header.numReadWriteStorageTextures = vulkanComputePipeline->resourceLayout->numReadWriteStorageTextures;
|
||||
vulkanComputePipeline->header.numReadWriteStorageBuffers = vulkanComputePipeline->resourceLayout->numReadWriteStorageBuffers;
|
||||
vulkanComputePipeline->header.numUniformBuffers = vulkanComputePipeline->resourceLayout->numUniformBuffers;
|
||||
|
||||
return (SDL_GPUComputePipeline *)vulkanComputePipeline;
|
||||
}
|
||||
|
||||
@@ -6921,6 +6963,8 @@ static void VULKAN_ReleaseTexture(
|
||||
VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textures[i]);
|
||||
}
|
||||
|
||||
SDL_DestroyProperties(vulkanTextureContainer->header.info.props);
|
||||
|
||||
// Containers are just client handles, so we can destroy immediately
|
||||
if (vulkanTextureContainer->debugName != NULL) {
|
||||
SDL_free(vulkanTextureContainer->debugName);
|
||||
@@ -7457,21 +7501,21 @@ static void VULKAN_BindVertexSamplers(
|
||||
VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
|
||||
VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (vulkanCommandBuffer->vertexSamplers[firstSlot + i] != sampler) {
|
||||
if (vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] != sampler->sampler) {
|
||||
VULKAN_INTERNAL_TrackSampler(
|
||||
vulkanCommandBuffer,
|
||||
(VulkanSampler *)textureSamplerBindings[i].sampler);
|
||||
|
||||
vulkanCommandBuffer->vertexSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
|
||||
vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] = sampler->sampler;
|
||||
vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
|
||||
}
|
||||
|
||||
if (vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
|
||||
if (vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7488,12 +7532,12 @@ static void VULKAN_BindVertexStorageTextures(
|
||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||
VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
|
||||
|
||||
if (vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] != textureContainer->activeTexture) {
|
||||
if (vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7510,12 +7554,12 @@ static void VULKAN_BindVertexStorageBuffers(
|
||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||
VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
|
||||
|
||||
if (vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] != bufferContainer->activeBuffer) {
|
||||
if (vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
|
||||
VULKAN_INTERNAL_TrackBuffer(
|
||||
vulkanCommandBuffer,
|
||||
bufferContainer->activeBuffer);
|
||||
|
||||
vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
|
||||
vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
|
||||
vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7533,21 +7577,21 @@ static void VULKAN_BindFragmentSamplers(
|
||||
VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
|
||||
VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (vulkanCommandBuffer->fragmentSamplers[firstSlot + i] != sampler) {
|
||||
if (vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] != sampler->sampler) {
|
||||
VULKAN_INTERNAL_TrackSampler(
|
||||
vulkanCommandBuffer,
|
||||
(VulkanSampler *)textureSamplerBindings[i].sampler);
|
||||
|
||||
vulkanCommandBuffer->fragmentSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
|
||||
vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] = sampler->sampler;
|
||||
vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
|
||||
}
|
||||
|
||||
if (vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
|
||||
if (vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7564,12 +7608,12 @@ static void VULKAN_BindFragmentStorageTextures(
|
||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||
VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
|
||||
|
||||
if (vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] != textureContainer->activeTexture) {
|
||||
if (vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7588,12 +7632,12 @@ static void VULKAN_BindFragmentStorageBuffers(
|
||||
for (i = 0; i < numBindings; i += 1) {
|
||||
bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
|
||||
|
||||
if (vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] != bufferContainer->activeBuffer) {
|
||||
if (vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
|
||||
VULKAN_INTERNAL_TrackBuffer(
|
||||
vulkanCommandBuffer,
|
||||
bufferContainer->activeBuffer);
|
||||
|
||||
vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
|
||||
vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
|
||||
vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -7866,15 +7910,17 @@ static void VULKAN_BeginRenderPass(
|
||||
|
||||
clearValues = SDL_stack_alloc(VkClearValue, clearCount);
|
||||
|
||||
for (i = 0; i < totalColorAttachmentCount; i += 1) {
|
||||
clearValues[i].color.float32[0] = colorTargetInfos[i].clear_color.r;
|
||||
clearValues[i].color.float32[1] = colorTargetInfos[i].clear_color.g;
|
||||
clearValues[i].color.float32[2] = colorTargetInfos[i].clear_color.b;
|
||||
clearValues[i].color.float32[3] = colorTargetInfos[i].clear_color.a;
|
||||
int clearIndex = 0;
|
||||
for (i = 0; i < numColorTargets; i += 1) {
|
||||
clearValues[clearIndex].color.float32[0] = colorTargetInfos[i].clear_color.r;
|
||||
clearValues[clearIndex].color.float32[1] = colorTargetInfos[i].clear_color.g;
|
||||
clearValues[clearIndex].color.float32[2] = colorTargetInfos[i].clear_color.b;
|
||||
clearValues[clearIndex].color.float32[3] = colorTargetInfos[i].clear_color.a;
|
||||
clearIndex += 1;
|
||||
|
||||
if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
|
||||
// Skip over the resolve texture, we're not clearing it
|
||||
i += 1;
|
||||
clearIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8107,15 +8153,15 @@ static void VULKAN_EndRenderPass(
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexBufferOffsets);
|
||||
vulkanCommandBuffer->vertexBufferCount = 0;
|
||||
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexSamplers);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextures);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexStorageTextures);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexStorageBuffers);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexSamplerBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexStorageTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->vertexStorageBufferBindings);
|
||||
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentSamplers);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextures);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextures);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentStorageBuffers);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentSamplerBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->fragmentStorageBufferBindings);
|
||||
}
|
||||
|
||||
static void VULKAN_BeginComputePass(
|
||||
@@ -8145,6 +8191,7 @@ static void VULKAN_BeginComputePass(
|
||||
VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
|
||||
|
||||
vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = subresource;
|
||||
vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings[i] = subresource->computeWriteView;
|
||||
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
@@ -8161,6 +8208,7 @@ static void VULKAN_BeginComputePass(
|
||||
VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
|
||||
|
||||
vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
|
||||
vulkanCommandBuffer->readWriteComputeStorageBufferBindings[i] = buffer->buffer;
|
||||
|
||||
VULKAN_INTERNAL_TrackBuffer(
|
||||
vulkanCommandBuffer,
|
||||
@@ -8212,21 +8260,21 @@ static void VULKAN_BindComputeSamplers(
|
||||
VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
|
||||
VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
|
||||
|
||||
if (vulkanCommandBuffer->computeSamplers[firstSlot + i] != sampler) {
|
||||
if (vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] != sampler->sampler) {
|
||||
VULKAN_INTERNAL_TrackSampler(
|
||||
vulkanCommandBuffer,
|
||||
sampler);
|
||||
|
||||
vulkanCommandBuffer->computeSamplers[firstSlot + i] = sampler;
|
||||
vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] = sampler->sampler;
|
||||
vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
|
||||
}
|
||||
|
||||
if (vulkanCommandBuffer->computeSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
|
||||
if (vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
|
||||
VULKAN_INTERNAL_TrackTexture(
|
||||
vulkanCommandBuffer,
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->computeSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -8267,6 +8315,7 @@ static void VULKAN_BindComputeStorageTextures(
|
||||
textureContainer->activeTexture);
|
||||
|
||||
vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] = textureContainer->activeTexture;
|
||||
vulkanCommandBuffer->readOnlyComputeStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
|
||||
vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -8306,6 +8355,7 @@ static void VULKAN_BindComputeStorageBuffers(
|
||||
bufferContainer->activeBuffer);
|
||||
|
||||
vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
|
||||
vulkanCommandBuffer->readOnlyComputeStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
|
||||
vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
|
||||
}
|
||||
}
|
||||
@@ -8380,8 +8430,8 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplers[i]->sampler;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplerBindings[i];
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -8404,7 +8454,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextures[i]->fullView;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -8426,7 +8476,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pImageInfo = NULL;
|
||||
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBuffers[i]->buffer;
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBufferBindings[i];
|
||||
bufferInfos[bufferInfoCount].offset = 0;
|
||||
bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
|
||||
|
||||
@@ -8461,7 +8511,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
currentWriteDescriptorSet->pBufferInfo = NULL;
|
||||
|
||||
imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureSubresources[i]->computeWriteView;
|
||||
imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureViewBindings[i];
|
||||
imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
|
||||
@@ -8483,7 +8533,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
currentWriteDescriptorSet->pTexelBufferView = NULL;
|
||||
currentWriteDescriptorSet->pImageInfo = NULL;
|
||||
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBuffers[i]->buffer;
|
||||
bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBufferBindings[i];
|
||||
bufferInfos[bufferInfoCount].offset = 0;
|
||||
bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
|
||||
|
||||
@@ -8558,7 +8608,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
|
||||
dynamicOffsetCount,
|
||||
dynamicOffsets);
|
||||
|
||||
commandBuffer->needNewVertexUniformOffsets = false;
|
||||
commandBuffer->needNewComputeUniformOffsets = false;
|
||||
}
|
||||
|
||||
static void VULKAN_DispatchCompute(
|
||||
@@ -8650,9 +8700,12 @@ static void VULKAN_EndComputePass(
|
||||
}
|
||||
}
|
||||
|
||||
// we don't need a barrier because sampler state is always the default if sampler bit is set
|
||||
SDL_zeroa(vulkanCommandBuffer->computeSamplerTextures);
|
||||
SDL_zeroa(vulkanCommandBuffer->computeSamplers);
|
||||
// we don't need a barrier for sampler resources because sampler state is always the default if sampler bit is set
|
||||
SDL_zeroa(vulkanCommandBuffer->computeSamplerTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->computeSamplerBindings);
|
||||
|
||||
SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings);
|
||||
SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageBufferBindings);
|
||||
|
||||
vulkanCommandBuffer->currentComputePipeline = NULL;
|
||||
|
||||
@@ -9358,6 +9411,8 @@ static bool VULKAN_INTERNAL_AllocateCommandBuffer(
|
||||
commandBuffer->usedUniformBuffers = SDL_malloc(
|
||||
commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
|
||||
|
||||
commandBuffer->swapchainRequested = false;
|
||||
|
||||
// Pool it!
|
||||
|
||||
vulkanCommandPool->inactiveCommandBuffers[vulkanCommandPool->inactiveCommandBufferCount] = commandBuffer;
|
||||
@@ -9468,7 +9523,8 @@ static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
|
||||
VulkanCommandBuffer *commandBuffer =
|
||||
VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(renderer, threadID);
|
||||
|
||||
commandBuffer->descriptorSetCache = VULKAN_INTERNAL_AcquireDescriptorSetCache(renderer);
|
||||
DescriptorSetCache *descriptorSetCache =
|
||||
VULKAN_INTERNAL_AcquireDescriptorSetCache(renderer);
|
||||
|
||||
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
|
||||
|
||||
@@ -9476,6 +9532,8 @@ static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
commandBuffer->descriptorSetCache = descriptorSetCache;
|
||||
|
||||
// Reset state
|
||||
|
||||
commandBuffer->currentComputePipeline = NULL;
|
||||
@@ -9518,26 +9576,29 @@ static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
|
||||
SDL_zeroa(commandBuffer->vertexBufferOffsets);
|
||||
commandBuffer->vertexBufferCount = 0;
|
||||
|
||||
SDL_zeroa(commandBuffer->vertexSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->vertexSamplers);
|
||||
SDL_zeroa(commandBuffer->vertexStorageTextures);
|
||||
SDL_zeroa(commandBuffer->vertexStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->vertexSamplerTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->vertexSamplerBindings);
|
||||
SDL_zeroa(commandBuffer->vertexStorageTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->vertexStorageBufferBindings);
|
||||
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplers);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageTextures);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->fragmentSamplerBindings);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->fragmentStorageBufferBindings);
|
||||
|
||||
SDL_zeroa(commandBuffer->readWriteComputeStorageTextureSubresources);
|
||||
commandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
|
||||
SDL_zeroa(commandBuffer->readWriteComputeStorageBuffers);
|
||||
SDL_zeroa(commandBuffer->computeSamplerTextures);
|
||||
SDL_zeroa(commandBuffer->computeSamplers);
|
||||
SDL_zeroa(commandBuffer->computeSamplerTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->computeSamplerBindings);
|
||||
SDL_zeroa(commandBuffer->readOnlyComputeStorageTextureViewBindings);
|
||||
SDL_zeroa(commandBuffer->readOnlyComputeStorageBufferBindings);
|
||||
SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
|
||||
SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);
|
||||
|
||||
commandBuffer->autoReleaseFence = true;
|
||||
|
||||
commandBuffer->swapchainRequested = false;
|
||||
commandBuffer->isDefrag = 0;
|
||||
|
||||
/* Reset the command buffer here to avoid resets being called
|
||||
@@ -9886,6 +9947,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
|
||||
SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false);
|
||||
}
|
||||
|
||||
// The command buffer is flagged for cleanup when the swapchain is requested as a cleanup timing mechanism
|
||||
vulkanCommandBuffer->swapchainRequested = true;
|
||||
|
||||
if (window->flags & SDL_WINDOW_HIDDEN) {
|
||||
// Edge case, texture is filled in with NULL but not an error
|
||||
return true;
|
||||
}
|
||||
|
||||
// If window data marked as needing swapchain recreate, try to recreate
|
||||
if (windowData->needsSwapchainRecreate) {
|
||||
Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
|
||||
@@ -9903,13 +9972,6 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
|
||||
}
|
||||
}
|
||||
|
||||
if (swapchainTextureWidth) {
|
||||
*swapchainTextureWidth = windowData->width;
|
||||
}
|
||||
if (swapchainTextureHeight) {
|
||||
*swapchainTextureHeight = windowData->height;
|
||||
}
|
||||
|
||||
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
|
||||
if (block) {
|
||||
// If we are blocking, just wait for the fence!
|
||||
@@ -9961,6 +10023,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
|
||||
}
|
||||
}
|
||||
|
||||
if (swapchainTextureWidth) {
|
||||
*swapchainTextureWidth = windowData->width;
|
||||
}
|
||||
|
||||
if (swapchainTextureHeight) {
|
||||
*swapchainTextureHeight = windowData->height;
|
||||
}
|
||||
|
||||
swapchainTextureContainer = &windowData->textureContainers[swapchainImageIndex];
|
||||
|
||||
// We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
|
||||
@@ -10338,6 +10408,7 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
|
||||
commandBuffer->presentDataCount = 0;
|
||||
commandBuffer->waitSemaphoreCount = 0;
|
||||
commandBuffer->signalSemaphoreCount = 0;
|
||||
commandBuffer->swapchainRequested = false;
|
||||
|
||||
// Reset defrag state
|
||||
|
||||
@@ -10435,11 +10506,18 @@ static bool VULKAN_Wait(
|
||||
VkResult result;
|
||||
Sint32 i;
|
||||
|
||||
SDL_LockMutex(renderer->submitLock);
|
||||
|
||||
result = renderer->vkDeviceWaitIdle(renderer->logicalDevice);
|
||||
|
||||
CHECK_VULKAN_ERROR_AND_RETURN(result, vkDeviceWaitIdle, false);
|
||||
|
||||
SDL_LockMutex(renderer->submitLock);
|
||||
if (result != VK_SUCCESS) {
|
||||
if (renderer->debugMode) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", "vkDeviceWaitIdle", VkErrorMessages(result));
|
||||
}
|
||||
SDL_SetError("%s %s", "vkDeviceWaitIdle", VkErrorMessages(result));
|
||||
SDL_UnlockMutex(renderer->submitLock);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
|
||||
commandBuffer = renderer->submittedCommandBuffers[i];
|
||||
@@ -10494,7 +10572,7 @@ static bool VULKAN_Submit(
|
||||
VulkanTextureSubresource *swapchainTextureSubresource;
|
||||
VulkanMemorySubAllocator *allocator;
|
||||
bool performCleanups =
|
||||
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->presentDataCount > 0) ||
|
||||
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->swapchainRequested) ||
|
||||
renderer->claimedWindowCount == 0;
|
||||
|
||||
SDL_LockMutex(renderer->submitLock);
|
||||
@@ -10964,7 +11042,8 @@ static Uint8 VULKAN_INTERNAL_CheckInstanceExtensions(
|
||||
const char **requiredExtensions,
|
||||
Uint32 requiredExtensionsLength,
|
||||
bool *supportsDebugUtils,
|
||||
bool *supportsColorspace)
|
||||
bool *supportsColorspace,
|
||||
bool *supportsPhysicalDeviceProperties2)
|
||||
{
|
||||
Uint32 extensionCount, i;
|
||||
VkExtensionProperties *availableExtensions;
|
||||
@@ -11003,6 +11082,12 @@ static Uint8 VULKAN_INTERNAL_CheckInstanceExtensions(
|
||||
availableExtensions,
|
||||
extensionCount);
|
||||
|
||||
// Only needed for KHR_driver_properties!
|
||||
*supportsPhysicalDeviceProperties2 = SupportsInstanceExtension(
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
||||
availableExtensions,
|
||||
extensionCount);
|
||||
|
||||
SDL_free(availableExtensions);
|
||||
return allExtensionsSupported;
|
||||
}
|
||||
@@ -11113,10 +11198,6 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
|
||||
instanceExtensionCount + 4);
|
||||
SDL_memcpy((void *)instanceExtensionNames, originalInstanceExtensionNames, instanceExtensionCount * sizeof(const char *));
|
||||
|
||||
// Core since 1.1
|
||||
instanceExtensionNames[instanceExtensionCount++] =
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
|
||||
|
||||
#ifdef SDL_PLATFORM_APPLE
|
||||
instanceExtensionNames[instanceExtensionCount++] =
|
||||
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
|
||||
@@ -11127,7 +11208,8 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
|
||||
instanceExtensionNames,
|
||||
instanceExtensionCount,
|
||||
&renderer->supportsDebugUtils,
|
||||
&renderer->supportsColorspace)) {
|
||||
&renderer->supportsColorspace,
|
||||
&renderer->supportsPhysicalDeviceProperties2)) {
|
||||
SDL_stack_free((char *)instanceExtensionNames);
|
||||
SET_STRING_ERROR_AND_RETURN("Required Vulkan instance extensions not supported", false);
|
||||
}
|
||||
@@ -11149,6 +11231,12 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
|
||||
VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
if (renderer->supportsPhysicalDeviceProperties2) {
|
||||
// Append KHR_physical_device_properties2 extension
|
||||
instanceExtensionNames[instanceExtensionCount++] =
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = createFlags;
|
||||
@@ -11647,7 +11735,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
||||
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
|
||||
if (!renderer) {
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer->debugMode = debugMode;
|
||||
@@ -11655,9 +11743,10 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
||||
renderer->allowedFramesInFlight = 2;
|
||||
|
||||
if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
|
||||
SET_STRING_ERROR("Failed to initialize Vulkan!");
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to initialize Vulkan!", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Vulkan");
|
||||
@@ -11683,16 +11772,18 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
||||
|
||||
if (!VULKAN_INTERNAL_CreateLogicalDevice(
|
||||
renderer)) {
|
||||
SET_STRING_ERROR("Failed to create logical device!");
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to create logical device!", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FIXME: just move this into this function
|
||||
result = (SDL_GPUDevice *)SDL_malloc(sizeof(SDL_GPUDevice));
|
||||
result = (SDL_GPUDevice *)SDL_calloc(1, sizeof(SDL_GPUDevice));
|
||||
ASSIGN_DRIVER(VULKAN)
|
||||
|
||||
result->driverData = (SDL_GPURenderer *)renderer;
|
||||
result->shader_formats = SDL_GPU_SHADERFORMAT_SPIRV;
|
||||
|
||||
/*
|
||||
* Create initial swapchain array
|
||||
|
@@ -1117,13 +1117,12 @@ bool SDL_SYS_HapticResume(SDL_Haptic *haptic)
|
||||
*/
|
||||
bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
|
||||
{
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
// Linux does not support this natively so we have to loop.
|
||||
for (i = 0; i < haptic->neffects; i++) {
|
||||
if (haptic->effects[i].hweffect != NULL) {
|
||||
ret = SDL_SYS_HapticStopEffect(haptic, &haptic->effects[i]);
|
||||
if (ret < 0) {
|
||||
if (!SDL_SYS_HapticStopEffect(haptic, &haptic->effects[i])) {
|
||||
return SDL_SetError("Haptic: Error while trying to stop all playing effects.");
|
||||
}
|
||||
}
|
||||
|
@@ -31,11 +31,7 @@
|
||||
/*
|
||||
* External stuff.
|
||||
*/
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
extern HWND SDL_HelperWindow;
|
||||
#else
|
||||
static const HWND SDL_HelperWindow = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Internal stuff.
|
||||
|
@@ -71,6 +71,11 @@ extern "C" {
|
||||
#define DETACH_KERNEL_DRIVER
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:5287) /* operands are different enum types */
|
||||
#endif
|
||||
|
||||
/* Uncomment to enable the retrieval of Usage and Usage Page in
|
||||
hid_enumerate(). Warning, on platforms different from FreeBSD
|
||||
this is very invasive as it requires the detach
|
||||
@@ -255,19 +260,19 @@ static int get_usage(uint8_t *report_descriptor, size_t size,
|
||||
}
|
||||
|
||||
if (key_cmd == 0x4) {
|
||||
*usage_page = get_bytes(report_descriptor, size, data_len, i);
|
||||
*usage_page = (unsigned short)get_bytes(report_descriptor, size, data_len, i);
|
||||
usage_page_found = 1;
|
||||
//printf("Usage Page: %x\n", (uint32_t)*usage_page);
|
||||
}
|
||||
if (key_cmd == 0x8) {
|
||||
if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */
|
||||
*usage_page = get_bytes(report_descriptor, size, 2, i + 2);
|
||||
*usage_page = (unsigned short)get_bytes(report_descriptor, size, 2, i + 2);
|
||||
usage_page_found = 1;
|
||||
*usage = get_bytes(report_descriptor, size, 2, i);
|
||||
*usage = (unsigned short)get_bytes(report_descriptor, size, 2, i);
|
||||
usage_found = 1;
|
||||
}
|
||||
else {
|
||||
*usage = get_bytes(report_descriptor, size, data_len, i);
|
||||
*usage = (unsigned short)get_bytes(report_descriptor, size, data_len, i);
|
||||
usage_found = 1;
|
||||
}
|
||||
//printf("Usage: %x\n", (uint32_t)*usage);
|
||||
@@ -635,7 +640,7 @@ static int hid_get_report_descriptor_libusb(libusb_device_handle *handle, int in
|
||||
/* Get the HID Report Descriptor.
|
||||
See USB HID Specification, section 7.1.1
|
||||
*/
|
||||
int res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8), interface_num, tmp, expected_report_descriptor_size, 5000);
|
||||
int res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8), (uint16_t)interface_num, tmp, expected_report_descriptor_size, 5000);
|
||||
if (res >= 0) {
|
||||
if (res > (int)buf_size)
|
||||
res = (int)buf_size;
|
||||
@@ -666,6 +671,8 @@ static void fill_device_info_usage(struct hid_device_info *cur_dev, libusb_devic
|
||||
|
||||
cur_dev->usage_page = page;
|
||||
cur_dev->usage = usage;
|
||||
|
||||
free(hid_report_descriptor);
|
||||
}
|
||||
|
||||
#ifdef INVASIVE_GET_USAGE
|
||||
@@ -918,6 +925,22 @@ static int should_enumerate_interface(unsigned short vendor_id, const struct lib
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libusb_blacklist(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
size_t i;
|
||||
static const struct { unsigned short vid; unsigned short pid; } known_bad[] = {
|
||||
{ 0x1532, 0x0227 } /* Razer Huntsman Gaming keyboard - long delay asking for device details */
|
||||
};
|
||||
|
||||
for (i = 0; i < (sizeof(known_bad)/sizeof(known_bad[0])); i++) {
|
||||
if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid || known_bad[i].pid == 0x0000)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
libusb_device **devs;
|
||||
@@ -948,7 +971,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||
unsigned short dev_pid = desc.idProduct;
|
||||
|
||||
if ((vendor_id != 0x0 && vendor_id != dev_vid) ||
|
||||
(product_id != 0x0 && product_id != dev_pid)) {
|
||||
(product_id != 0x0 && product_id != dev_pid) ||
|
||||
libusb_blacklist(dev_vid, dev_pid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1193,7 @@ static void *read_thread(void *param)
|
||||
dev->transfer = libusb_alloc_transfer(0);
|
||||
libusb_fill_interrupt_transfer(dev->transfer,
|
||||
dev->device_handle,
|
||||
dev->input_endpoint,
|
||||
(unsigned char)dev->input_endpoint,
|
||||
buf,
|
||||
(int) length,
|
||||
read_callback,
|
||||
@@ -1588,8 +1612,8 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
|
||||
res = libusb_control_transfer(dev->device_handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
|
||||
0x09/*HID Set_Report*/,
|
||||
(2/*HID output*/ << 8) | report_number,
|
||||
dev->interface,
|
||||
(uint16_t)((2/*HID output*/ << 8) | report_number),
|
||||
(uint16_t)dev->interface,
|
||||
(unsigned char *)data, (uint16_t)length,
|
||||
1000/*timeout millis*/);
|
||||
|
||||
@@ -1605,7 +1629,7 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
|
||||
/* Use the interrupt out endpoint */
|
||||
int actual_length;
|
||||
res = libusb_interrupt_transfer(dev->device_handle,
|
||||
dev->output_endpoint,
|
||||
(unsigned char)dev->output_endpoint,
|
||||
(unsigned char*)data,
|
||||
(int) length,
|
||||
&actual_length, 1000);
|
||||
@@ -1754,8 +1778,8 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char
|
||||
res = libusb_control_transfer(dev->device_handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
|
||||
0x09/*HID set_report*/,
|
||||
(3/*HID feature*/ << 8) | report_number,
|
||||
dev->interface,
|
||||
(uint16_t)((3/*HID feature*/ << 8) | report_number),
|
||||
(uint16_t)dev->interface,
|
||||
(unsigned char *)data, (uint16_t)length,
|
||||
1000/*timeout millis*/);
|
||||
|
||||
@@ -1785,8 +1809,8 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
|
||||
res = libusb_control_transfer(dev->device_handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
|
||||
0x01/*HID get_report*/,
|
||||
(3/*HID feature*/ << 8) | report_number,
|
||||
dev->interface,
|
||||
(uint16_t)((3/*HID feature*/ << 8) | report_number),
|
||||
(uint16_t)dev->interface,
|
||||
(unsigned char *)data, (uint16_t)length,
|
||||
1000/*timeout millis*/);
|
||||
|
||||
@@ -1815,8 +1839,8 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c
|
||||
res = libusb_control_transfer(dev->device_handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
|
||||
0x01/*HID get_report*/,
|
||||
(1/*HID Input*/ << 8) | report_number,
|
||||
dev->interface,
|
||||
(uint16_t)((1/*HID Input*/ << 8) | report_number),
|
||||
(uint16_t)dev->interface,
|
||||
(unsigned char *)data, (uint16_t)length,
|
||||
1000/*timeout millis*/);
|
||||
|
||||
@@ -1908,7 +1932,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
|
||||
{
|
||||
wchar_t *str;
|
||||
|
||||
str = get_usb_string(dev->device_handle, string_index);
|
||||
str = get_usb_string(dev->device_handle, (uint8_t)string_index);
|
||||
if (str) {
|
||||
wcsncpy(string, str, maxlen);
|
||||
string[maxlen-1] = L'\0';
|
||||
@@ -2096,7 +2120,7 @@ uint16_t get_usb_code_for_current_locale(void)
|
||||
/* Chop off the encoding part, and make it lower case. */
|
||||
ptr = search_string;
|
||||
while (*ptr) {
|
||||
*ptr = tolower(*ptr);
|
||||
*ptr = (char)tolower(*ptr);
|
||||
if (*ptr == '.') {
|
||||
*ptr = '\0';
|
||||
break;
|
||||
@@ -2117,7 +2141,7 @@ uint16_t get_usb_code_for_current_locale(void)
|
||||
/* Chop off the variant. Chop it off at the '_'. */
|
||||
ptr = search_string;
|
||||
while (*ptr) {
|
||||
*ptr = tolower(*ptr);
|
||||
*ptr = (char)tolower(*ptr);
|
||||
if (*ptr == '_') {
|
||||
*ptr = '\0';
|
||||
break;
|
||||
@@ -2140,6 +2164,10 @@ uint16_t get_usb_code_for_current_locale(void)
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -134,7 +134,6 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
|
||||
* Use register_error_str(NULL) to free the error message completely. */
|
||||
static void register_error_str(wchar_t **error_str, const char *msg)
|
||||
{
|
||||
free(*error_str);
|
||||
#ifdef HIDAPI_USING_SDL_RUNTIME
|
||||
/* Thread-safe error handling */
|
||||
if (msg) {
|
||||
@@ -143,6 +142,7 @@ static void register_error_str(wchar_t **error_str, const char *msg)
|
||||
SDL_ClearError();
|
||||
}
|
||||
#else
|
||||
free(*error_str);
|
||||
*error_str = utf8_to_wchar_t(msg);
|
||||
#endif
|
||||
}
|
||||
|
@@ -949,6 +949,7 @@ static int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
|
||||
{ 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset - causes deadlock asking for device details */
|
||||
{ 0x1532, 0x0109 }, /* Razer Lycosa Gaming keyboard - causes deadlock asking for device details */
|
||||
{ 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard - causes deadlock asking for device details */
|
||||
{ 0x1532, 0x0227 }, /* Razer Huntsman Gaming keyboard - long delay asking for device details */
|
||||
{ 0x1B1C, 0x1B3D }, /* Corsair Gaming keyboard - causes deadlock asking for device details */
|
||||
{ 0x1CCF, 0x0000 } /* All Konami Amusement Devices - causes deadlock asking for device details */
|
||||
};
|
||||
@@ -1398,6 +1399,11 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
if (GetLastError() == ERROR_OPERATION_ABORTED) {
|
||||
/* The read request was issued on another thread.
|
||||
This is harmless, so just ignore it. */
|
||||
return 0;
|
||||
}
|
||||
register_winapi_error(dev, L"hid_read_timeout/GetOverlappedResult");
|
||||
}
|
||||
|
||||
|
@@ -455,7 +455,8 @@ static bool SDLCALL fd_flush(void *userdata, SDL_IOStatus *status)
|
||||
result = SDL_fdatasync(iodata->fd);
|
||||
} while (result < 0 && errno == EINTR);
|
||||
|
||||
if (result < 0) {
|
||||
// We get EINVAL when flushing a pipe, just make that a no-op
|
||||
if (result < 0 && errno != EINVAL) {
|
||||
return SDL_SetError("Error flushing datastream: %s", strerror(errno));
|
||||
}
|
||||
return true;
|
||||
|
@@ -311,7 +311,7 @@ void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id)
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
if (!SDL_gamepads_initialized) {
|
||||
if (!SDL_gamepads_initialized || SDL_IsJoystickBeingAdded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -913,7 +913,7 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_GUID guid, bo
|
||||
// An exact match, including CRC
|
||||
return mapping;
|
||||
} else if (crc && exact_match_crc) {
|
||||
return NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!best_match) {
|
||||
@@ -1786,6 +1786,11 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char *
|
||||
char name_string[128];
|
||||
char mapping[1024];
|
||||
|
||||
// Remove the CRC from the GUID
|
||||
// We already know that this GUID doesn't have a mapping without the CRC, and we want newly
|
||||
// added mappings without a CRC to override this mapping.
|
||||
SDL_SetJoystickGUIDCRC(&guid, 0);
|
||||
|
||||
// Remove any commas in the name
|
||||
SDL_strlcpy(name_string, name, sizeof(name_string));
|
||||
{
|
||||
@@ -2678,8 +2683,8 @@ bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name && SDL_strcmp(name, "uinput-fpc") == 0) {
|
||||
// The Google Pixel fingerprint sensor reports itself as a joystick
|
||||
if (name && SDL_startswith(name, "uinput-")) {
|
||||
// The Google Pixel fingerprint sensor, as well as other fingerprint sensors, reports itself as a joystick
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2754,6 +2759,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
|
||||
|
||||
gamepad->joystick = SDL_OpenJoystick(instance_id);
|
||||
if (!gamepad->joystick) {
|
||||
SDL_SetObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD, false);
|
||||
SDL_free(gamepad);
|
||||
SDL_UnlockJoysticks();
|
||||
return NULL;
|
||||
@@ -2762,6 +2768,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
|
||||
if (gamepad->joystick->naxes) {
|
||||
gamepad->last_match_axis = (SDL_GamepadBinding **)SDL_calloc(gamepad->joystick->naxes, sizeof(*gamepad->last_match_axis));
|
||||
if (!gamepad->last_match_axis) {
|
||||
SDL_SetObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD, false);
|
||||
SDL_CloseJoystick(gamepad->joystick);
|
||||
SDL_free(gamepad);
|
||||
SDL_UnlockJoysticks();
|
||||
@@ -2771,6 +2778,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
|
||||
if (gamepad->joystick->nhats) {
|
||||
gamepad->last_hat_mask = (Uint8 *)SDL_calloc(gamepad->joystick->nhats, sizeof(*gamepad->last_hat_mask));
|
||||
if (!gamepad->last_hat_mask) {
|
||||
SDL_SetObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD, false);
|
||||
SDL_CloseJoystick(gamepad->joystick);
|
||||
SDL_free(gamepad->last_match_axis);
|
||||
SDL_free(gamepad);
|
||||
|
@@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = {
|
||||
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||
"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,",
|
||||
"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,",
|
||||
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,",
|
||||
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
|
||||
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,",
|
||||
"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
||||
"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||
@@ -416,12 +416,13 @@ static const char *s_GamepadMappings[] = {
|
||||
"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
|
||||
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,",
|
||||
"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,",
|
||||
"03000000853200008906000000010000,NACON Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||
"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,",
|
||||
"03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,",
|
||||
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
|
||||
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,",
|
||||
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
|
||||
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
||||
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
@@ -796,6 +797,7 @@ static const char *s_GamepadMappings[] = {
|
||||
"03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */
|
||||
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000120c0000182e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
||||
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
|
@@ -278,6 +278,7 @@ static Uint32 initial_blacklist_devices[] = {
|
||||
MAKE_VIDPID(0x26ce, 0x01a2), // ASRock LED Controller
|
||||
MAKE_VIDPID(0x20d6, 0x0002), // PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only)
|
||||
MAKE_VIDPID(0x3434, 0x0211), // Keychron K1 Pro System Control
|
||||
MAKE_VIDPID(0x04f2, 0xa13c), // HP Deluxe Webcam KQ246AA
|
||||
};
|
||||
static SDL_vidpid_list blacklist_devices = {
|
||||
SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL,
|
||||
@@ -1190,9 +1191,35 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
|
||||
|
||||
// If this joystick is known to have all zero centered axes, skip the auto-centering code
|
||||
if (SDL_JoystickAxesCenteredAtZero(joystick)) {
|
||||
int i;
|
||||
for (int i = 0; i < joystick->naxes; ++i) {
|
||||
joystick->axes[i].has_initial_value = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < joystick->naxes; ++i) {
|
||||
// We know the initial values for HIDAPI and XInput joysticks
|
||||
if ((SDL_IsJoystickHIDAPI(joystick->guid) ||
|
||||
SDL_IsJoystickXInput(joystick->guid) ||
|
||||
SDL_IsJoystickRAWINPUT(joystick->guid) ||
|
||||
SDL_IsJoystickWGI(joystick->guid)) &&
|
||||
joystick->naxes >= SDL_GAMEPAD_AXIS_COUNT) {
|
||||
int left_trigger, right_trigger;
|
||||
if (SDL_IsJoystickXInput(joystick->guid)) {
|
||||
left_trigger = 2;
|
||||
right_trigger = 5;
|
||||
} else {
|
||||
left_trigger = SDL_GAMEPAD_AXIS_LEFT_TRIGGER;
|
||||
right_trigger = SDL_GAMEPAD_AXIS_RIGHT_TRIGGER;
|
||||
}
|
||||
for (int i = 0; i < SDL_GAMEPAD_AXIS_COUNT; ++i) {
|
||||
int initial_value;
|
||||
if (i == left_trigger || i == right_trigger) {
|
||||
initial_value = SDL_MIN_SINT16;
|
||||
} else {
|
||||
initial_value = 0;
|
||||
}
|
||||
joystick->axes[i].value = initial_value;
|
||||
joystick->axes[i].zero = initial_value;
|
||||
joystick->axes[i].initial_value = initial_value;
|
||||
joystick->axes[i].has_initial_value = true;
|
||||
}
|
||||
}
|
||||
@@ -2117,6 +2144,7 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
|
||||
SDL_JoystickDriver *driver;
|
||||
int device_index;
|
||||
int player_index = -1;
|
||||
bool is_gamepad;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
@@ -2151,9 +2179,12 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
|
||||
}
|
||||
}
|
||||
|
||||
// This might create an automatic gamepad mapping, so wait to send the event
|
||||
is_gamepad = SDL_IsGamepad(instance_id);
|
||||
|
||||
SDL_joystick_being_added = false;
|
||||
|
||||
if (SDL_IsGamepad(instance_id)) {
|
||||
if (is_gamepad) {
|
||||
SDL_PrivateGamepadAdded(instance_id);
|
||||
}
|
||||
}
|
||||
|
@@ -328,6 +328,10 @@ void Android_AddJoystick(int device_id, const char *name, const char *desc, int
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(vendor_id, product_id, 0, name)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats", name, desc, vendor_id, product_id, naxes, nhats);
|
||||
#endif
|
||||
|
@@ -300,9 +300,15 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
* struct, and ARC doesn't work with structs. */
|
||||
device->controller = (__bridge GCController *)CFBridgingRetain(controller);
|
||||
|
||||
if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
|
||||
if (controller.productCategory) {
|
||||
name = controller.productCategory.UTF8String;
|
||||
}
|
||||
} else {
|
||||
if (controller.vendorName) {
|
||||
name = controller.vendorName.UTF8String;
|
||||
}
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = "MFi Gamepad";
|
||||
|
@@ -21,7 +21,6 @@
|
||||
|
||||
static const ControllerDescription_t arrControllers[] = {
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x1844 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xcad1 ), k_eControllerType_PS3Controller, NULL }, // Logitech Chillstream
|
||||
@@ -96,6 +95,7 @@ static const ControllerDescription_t arrControllers[] = {
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x2e18 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x020a ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS4 mode)
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "SDL_iokitjoystick_c.h"
|
||||
#include "../hidapi/SDL_hidapijoystick_c.h"
|
||||
#include "../../haptic/darwin/SDL_syshaptic_c.h" // For haptic hot plugging
|
||||
#include "../usb_ids.h"
|
||||
|
||||
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
|
||||
|
||||
@@ -213,6 +214,29 @@ static bool GetHIDScaledCalibratedState(recDevice *pDevice, recElement *pElement
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(recDevice *pDevice, recElement *pElement, SInt32 min, SInt32 max, SInt32 *pValue)
|
||||
{
|
||||
if (pElement->minReport == 0 && pElement->maxReport == 255) {
|
||||
return GetHIDScaledCalibratedState(pDevice, pElement, min, max, pValue);
|
||||
}
|
||||
|
||||
// This device thumbstick axes have an unusual axis range that
|
||||
// doesn't work with GetHIDScaledCalibratedState() above.
|
||||
//
|
||||
// See https://github.com/libsdl-org/SDL/issues/13143 for details
|
||||
if (GetHIDElementState(pDevice, pElement, pValue)) {
|
||||
if (*pValue >= 0) {
|
||||
// Negative axis values range from 32767 (at rest) to 0 (minimum)
|
||||
*pValue = -32767 + *pValue;
|
||||
} else if (*pValue < 0) {
|
||||
// Positive axis values range from -32768 (at rest) to 0 (maximum)
|
||||
*pValue = 32768 + *pValue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
|
||||
{
|
||||
recDevice *device = (recDevice *)ctx;
|
||||
@@ -506,6 +530,11 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0);
|
||||
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
|
||||
|
||||
if (vendor == USB_VENDOR_NACON_ALT &&
|
||||
product == USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT) {
|
||||
pDevice->nacon_revolution_x_unlimited = true;
|
||||
}
|
||||
|
||||
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
|
||||
if (array) {
|
||||
AddHIDElements(array, pDevice);
|
||||
@@ -957,7 +986,11 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick)
|
||||
i = 0;
|
||||
|
||||
while (element) {
|
||||
if (device->nacon_revolution_x_unlimited) {
|
||||
goodRead = GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(device, element, -32768, 32767, &value);
|
||||
} else {
|
||||
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
|
||||
}
|
||||
if (goodRead) {
|
||||
SDL_SendJoystickAxis(timestamp, joystick, i, value);
|
||||
}
|
||||
|
@@ -72,6 +72,7 @@ struct joystick_hwdata
|
||||
int instance_id;
|
||||
SDL_GUID guid;
|
||||
int steam_virtual_gamepad_slot;
|
||||
bool nacon_revolution_x_unlimited;
|
||||
|
||||
struct joystick_hwdata *pNext; // next device
|
||||
};
|
||||
|
@@ -305,6 +305,7 @@ static SDL_JoystickID EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index)
|
||||
static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
{
|
||||
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
|
||||
bool rumble_available = false;
|
||||
|
||||
if (!item) {
|
||||
return SDL_SetError("No such device");
|
||||
@@ -323,6 +324,22 @@ static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
joystick->nbuttons = item->nbuttons;
|
||||
joystick->naxes = item->naxes;
|
||||
|
||||
rumble_available = EM_ASM_INT({
|
||||
let gamepads = navigator['getGamepads']();
|
||||
if (!gamepads) {
|
||||
return 0;
|
||||
}
|
||||
let gamepad = gamepads[$0];
|
||||
if (!gamepad || !gamepad['vibrationActuator']) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}, item->index);
|
||||
|
||||
if (rumble_available) {
|
||||
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -390,7 +407,29 @@ static SDL_GUID EMSCRIPTEN_JoystickGetDeviceGUID(int device_index)
|
||||
|
||||
static bool EMSCRIPTEN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||
|
||||
// clang-format off
|
||||
bool result = EM_ASM_INT({
|
||||
let gamepads = navigator['getGamepads']();
|
||||
if (!gamepads) {
|
||||
return 0;
|
||||
}
|
||||
let gamepad = gamepads[$0];
|
||||
if (!gamepad || !gamepad['vibrationActuator']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
gamepad['vibrationActuator']['playEffect']('dual-rumble', {
|
||||
'startDelay': 0,
|
||||
'duration': 3000,
|
||||
'weakMagnitude': $1 / 0xFFFF,
|
||||
'strongMagnitude': $2 / 0xFFFF,
|
||||
});
|
||||
return 1;
|
||||
}, item->index, low_frequency_rumble, high_frequency_rumble);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool EMSCRIPTEN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
|
||||
|
||||
// Define this if you want to log all packets from the controller
|
||||
// #define DEBUG_GAMECUBE_PROTOCOL
|
||||
#if 0
|
||||
#define DEBUG_GAMECUBE_PROTOCOL
|
||||
#endif
|
||||
|
||||
#define MAX_CONTROLLERS 4
|
||||
|
||||
@@ -119,22 +121,15 @@ static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
device->context = ctx;
|
||||
|
||||
ctx->joysticks[0] = 0;
|
||||
ctx->joysticks[1] = 0;
|
||||
ctx->joysticks[2] = 0;
|
||||
ctx->joysticks[3] = 0;
|
||||
ctx->rumble[0] = rumbleMagic;
|
||||
ctx->useRumbleBrake = false;
|
||||
|
||||
if (device->vendor_id != USB_VENDOR_NINTENDO) {
|
||||
ctx->pc_mode = true;
|
||||
}
|
||||
|
||||
if (ctx->pc_mode) {
|
||||
for (i = 0; i < MAX_CONTROLLERS; ++i) {
|
||||
ResetAxisRange(ctx, i);
|
||||
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
|
||||
}
|
||||
ResetAxisRange(ctx, 0);
|
||||
HIDAPI_JoystickConnected(device, &ctx->joysticks[0]);
|
||||
} else {
|
||||
// This is all that's needed to initialize the device. Really!
|
||||
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
|
||||
@@ -204,22 +199,14 @@ static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device
|
||||
{
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size)
|
||||
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick)
|
||||
{
|
||||
SDL_Joystick *joystick;
|
||||
Uint8 i, v;
|
||||
const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index
|
||||
Uint8 v;
|
||||
Sint16 axis_value;
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
|
||||
if (size != 10) {
|
||||
return; // How do we handle this packet?
|
||||
}
|
||||
|
||||
i = packet[0] - 1;
|
||||
if (i >= MAX_CONTROLLERS) {
|
||||
return; // How do we handle this packet?
|
||||
}
|
||||
|
||||
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
|
||||
if (!joystick) {
|
||||
// Hasn't been opened yet, skip
|
||||
@@ -232,26 +219,26 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device
|
||||
joystick, \
|
||||
button, \
|
||||
((packet[off] & flag) != 0));
|
||||
READ_BUTTON(1, 0x02, 0) // A
|
||||
READ_BUTTON(1, 0x04, 1) // B
|
||||
READ_BUTTON(1, 0x08, 3) // Y
|
||||
READ_BUTTON(1, 0x01, 2) // X
|
||||
READ_BUTTON(2, 0x80, 4) // DPAD_LEFT
|
||||
READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT
|
||||
READ_BUTTON(2, 0x40, 6) // DPAD_DOWN
|
||||
READ_BUTTON(2, 0x10, 7) // DPAD_UP
|
||||
READ_BUTTON(2, 0x02, 8) // START
|
||||
READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER
|
||||
READ_BUTTON(0, 0x02, 0) // A
|
||||
READ_BUTTON(0, 0x04, 1) // B
|
||||
READ_BUTTON(0, 0x08, 3) // Y
|
||||
READ_BUTTON(0, 0x01, 2) // X
|
||||
READ_BUTTON(1, 0x80, 4) // DPAD_LEFT
|
||||
READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT
|
||||
READ_BUTTON(1, 0x40, 6) // DPAD_DOWN
|
||||
READ_BUTTON(1, 0x10, 7) // DPAD_UP
|
||||
READ_BUTTON(1, 0x02, 8) // START
|
||||
READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER
|
||||
/* These two buttons are for the bottoms of the analog triggers.
|
||||
* More than likely, you're going to want to read the axes instead!
|
||||
* -flibit
|
||||
*/
|
||||
READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT
|
||||
READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT
|
||||
READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT
|
||||
READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT
|
||||
#undef READ_BUTTON
|
||||
|
||||
#define READ_AXIS(off, axis, invert) \
|
||||
v = invert ? (0xff - packet[off]) : packet[off]; \
|
||||
v = (invert) ? (0xff - packet[off]) : packet[off]; \
|
||||
if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
|
||||
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
|
||||
if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
|
||||
@@ -261,12 +248,12 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device
|
||||
timestamp, \
|
||||
joystick, \
|
||||
axis, axis_value);
|
||||
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0)
|
||||
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1)
|
||||
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0)
|
||||
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1)
|
||||
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
|
||||
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
|
||||
READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0)
|
||||
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1)
|
||||
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0)
|
||||
READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1)
|
||||
READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
|
||||
READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
|
||||
#undef READ_AXIS
|
||||
}
|
||||
|
||||
@@ -365,7 +352,18 @@ static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
|
||||
#endif
|
||||
if (ctx->pc_mode) {
|
||||
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size);
|
||||
if (size == 10) {
|
||||
// This is the older firmware
|
||||
// The first byte is the index of the connected controller
|
||||
// The C stick has an inverted value range compared to the left stick
|
||||
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true);
|
||||
} else if (size == 9) {
|
||||
// This is the newer firmware (version 0x7)
|
||||
// The C stick has the same value range compared to the left stick
|
||||
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false);
|
||||
} else {
|
||||
// How do we handle this packet?
|
||||
}
|
||||
} else {
|
||||
HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size);
|
||||
}
|
||||
|
@@ -1003,8 +1003,8 @@ static bool HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device
|
||||
|
||||
static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet, int size)
|
||||
{
|
||||
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
|
||||
static const float TOUCHPAD_SCALEY = 1.0f / 920; // This is noted as being 944 resolution, but 920 feels better
|
||||
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
|
||||
static const float TOUCHPAD_SCALEY = 1.08695652e-3f; // 1.0f / 920 // This is noted as being 944 resolution, but 920 feels better
|
||||
Sint16 axis;
|
||||
bool touchpad_down;
|
||||
int touchpad_x, touchpad_y;
|
||||
|
@@ -251,6 +251,7 @@ typedef struct
|
||||
Uint64 last_packet;
|
||||
int player_index;
|
||||
bool player_lights;
|
||||
bool enhanced_rumble;
|
||||
Uint8 rumble_left;
|
||||
Uint8 rumble_right;
|
||||
bool color_set;
|
||||
@@ -432,6 +433,14 @@ static bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
}
|
||||
|
||||
if (device->vendor_id == USB_VENDOR_SONY) {
|
||||
if (device->product_id == USB_PRODUCT_SONY_DS5_EDGE ||
|
||||
ctx->firmware_version == 0 || // Assume that it's updated firmware over Bluetooth
|
||||
ctx->firmware_version >= 0x0224) {
|
||||
ctx->enhanced_rumble = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the device capabilities
|
||||
if (device->vendor_id == USB_VENDOR_SONY) {
|
||||
ctx->sensors_supported = true;
|
||||
@@ -684,17 +693,17 @@ static bool HIDAPI_DriverPS5_UpdateEffects(SDL_DriverPS5_Context *ctx, int effec
|
||||
|
||||
if (ctx->vibration_supported) {
|
||||
if (ctx->rumble_left || ctx->rumble_right) {
|
||||
if (ctx->firmware_version < 0x0224) {
|
||||
if (ctx->enhanced_rumble) {
|
||||
effects.ucEnableBits3 |= 0x04; // Enable improved rumble emulation on 2.24 firmware and newer
|
||||
|
||||
effects.ucRumbleLeft = ctx->rumble_left;
|
||||
effects.ucRumbleRight = ctx->rumble_right;
|
||||
} else {
|
||||
effects.ucEnableBits1 |= 0x01; // Enable rumble emulation
|
||||
|
||||
// Shift to reduce effective rumble strength to match Xbox controllers
|
||||
effects.ucRumbleLeft = ctx->rumble_left >> 1;
|
||||
effects.ucRumbleRight = ctx->rumble_right >> 1;
|
||||
} else {
|
||||
effects.ucEnableBits3 |= 0x04; // Enable improved rumble emulation on 2.24 firmware and newer
|
||||
|
||||
effects.ucRumbleLeft = ctx->rumble_left;
|
||||
effects.ucRumbleRight = ctx->rumble_right;
|
||||
}
|
||||
effects.ucEnableBits1 |= 0x02; // Disable audio haptics
|
||||
} else {
|
||||
@@ -812,14 +821,19 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx
|
||||
}
|
||||
|
||||
if (ctx->sensors_supported) {
|
||||
// Standard DualSense sensor update rate is 250 Hz over USB
|
||||
float update_rate = 250.0f;
|
||||
|
||||
if (ctx->device->is_bluetooth) {
|
||||
// Bluetooth sensor update rate appears to be 1000 Hz
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 1000.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 1000.0f);
|
||||
} else {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 250.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 250.0f);
|
||||
update_rate = 1000.0f;
|
||||
} else if (SDL_IsJoystickDualSenseEdge(ctx->device->vendor_id, ctx->device->product_id)) {
|
||||
// DualSense Edge sensor update rate is 1000 Hz over USB
|
||||
update_rate = 1000.0f;
|
||||
}
|
||||
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, update_rate);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, update_rate);
|
||||
}
|
||||
|
||||
ctx->report_battery = true;
|
||||
@@ -1033,6 +1047,9 @@ static bool HIDAPI_DriverPS5_InternalSendJoystickEffect(SDL_DriverPS5_Context *c
|
||||
if (!ctx->enhanced_mode) {
|
||||
if (application_usage) {
|
||||
HIDAPI_DriverPS5_UpdateEnhancedModeOnApplicationUsage(ctx);
|
||||
|
||||
// Wait briefly before sending additional effects
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
@@ -1355,8 +1372,8 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
|
||||
|
||||
static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet, Uint64 timestamp)
|
||||
{
|
||||
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
|
||||
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
|
||||
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
|
||||
static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070
|
||||
bool touchpad_down;
|
||||
int touchpad_x, touchpad_y;
|
||||
|
||||
@@ -1406,8 +1423,8 @@ static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
|
||||
|
||||
static void HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketAlt_t *packet, Uint64 timestamp)
|
||||
{
|
||||
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
|
||||
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
|
||||
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
|
||||
static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070
|
||||
bool touchpad_down;
|
||||
int touchpad_x, touchpad_y;
|
||||
|
||||
|
@@ -1038,6 +1038,11 @@ static bool HIDAPI_DriverSteam_IsSupportedDevice(SDL_HIDAPI_Device *device, cons
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device) {
|
||||
// Might be supported by this driver, enumerate and find out
|
||||
return true;
|
||||
}
|
||||
|
||||
if (device->is_bluetooth) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -58,9 +58,7 @@
|
||||
#define SWITCH_GYRO_SCALE 14.2842f
|
||||
#define SWITCH_ACCEL_SCALE 4096.f
|
||||
|
||||
#define SWITCH_GYRO_SCALE_OFFSET 13371.0f
|
||||
#define SWITCH_GYRO_SCALE_MULT 936.0f
|
||||
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
|
||||
#define SWITCH_ACCEL_SCALE_MULT 4.0f
|
||||
|
||||
enum
|
||||
@@ -930,13 +928,14 @@ static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
|
||||
|
||||
static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
{
|
||||
Uint8 *pLeftStickCal;
|
||||
Uint8 *pRightStickCal;
|
||||
Uint8 *pLeftStickCal = NULL;
|
||||
Uint8 *pRightStickCal = NULL;
|
||||
size_t stick, axis;
|
||||
SwitchSubcommandInputPacket_t *user_reply = NULL;
|
||||
SwitchSubcommandInputPacket_t *factory_reply = NULL;
|
||||
SwitchSPIOpData_t readUserParams;
|
||||
SwitchSPIOpData_t readFactoryParams;
|
||||
Uint8 userParamsReadSuccessCount = 0;
|
||||
|
||||
// Read User Calibration Info
|
||||
readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
|
||||
@@ -949,14 +948,33 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
|
||||
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
|
||||
|
||||
// Automatically select the user calibration if magic bytes are set
|
||||
if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
|
||||
userParamsReadSuccessCount += 1;
|
||||
pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
|
||||
}
|
||||
|
||||
if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
|
||||
userParamsReadSuccessCount += 1;
|
||||
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
|
||||
}
|
||||
|
||||
// Only read the factory calibration info if we failed to receive the correct magic bytes
|
||||
if (userParamsReadSuccessCount < 2) {
|
||||
// Read Factory Calibration Info
|
||||
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
|
||||
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
|
||||
|
||||
const int MAX_ATTEMPTS = 3;
|
||||
for (int attempt = 0; ; ++attempt) {
|
||||
for (int attempt = 0;; ++attempt) {
|
||||
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
|
||||
// We successfully read the calibration data
|
||||
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
|
||||
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -964,18 +982,12 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically select the user calibration if magic bytes are set
|
||||
if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
|
||||
pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
|
||||
} else {
|
||||
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
|
||||
}
|
||||
|
||||
if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
|
||||
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
|
||||
} else {
|
||||
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
|
||||
// If we still don't have calibration data, return false
|
||||
if (pLeftStickCal == NULL || pRightStickCal == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Stick calibration values are 12-bits each and are packed by bit
|
||||
@@ -1044,6 +1056,8 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) {
|
||||
Uint8 *pIMUScale;
|
||||
Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
|
||||
Sint16 sAccelSensCoeffX, sAccelSensCoeffY, sAccelSensCoeffZ;
|
||||
Sint16 sGyroSensCoeffX, sGyroSensCoeffY, sGyroSensCoeffZ;
|
||||
|
||||
// IMU scale gives us multipliers for converting raw values to real world values
|
||||
pIMUScale = reply->spiReadData.rgucReadData;
|
||||
@@ -1052,10 +1066,18 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
sAccelRawY = (pIMUScale[3] << 8) | pIMUScale[2];
|
||||
sAccelRawZ = (pIMUScale[5] << 8) | pIMUScale[4];
|
||||
|
||||
sAccelSensCoeffX = (pIMUScale[7] << 8) | pIMUScale[6];
|
||||
sAccelSensCoeffY = (pIMUScale[9] << 8) | pIMUScale[8];
|
||||
sAccelSensCoeffZ = (pIMUScale[11] << 8) | pIMUScale[10];
|
||||
|
||||
sGyroRawX = (pIMUScale[13] << 8) | pIMUScale[12];
|
||||
sGyroRawY = (pIMUScale[15] << 8) | pIMUScale[14];
|
||||
sGyroRawZ = (pIMUScale[17] << 8) | pIMUScale[16];
|
||||
|
||||
sGyroSensCoeffX = (pIMUScale[19] << 8) | pIMUScale[18];
|
||||
sGyroSensCoeffY = (pIMUScale[21] << 8) | pIMUScale[20];
|
||||
sGyroSensCoeffZ = (pIMUScale[23] << 8) | pIMUScale[22];
|
||||
|
||||
// Check for user calibration data. If it's present and set, it'll override the factory settings
|
||||
readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
|
||||
readParams.ucLength = k_unSPIIMUUserScaleLength;
|
||||
@@ -1072,14 +1094,14 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
|
||||
}
|
||||
|
||||
// Accelerometer scale
|
||||
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
|
||||
|
||||
// Gyro scale
|
||||
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * SDL_PI_F / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * SDL_PI_F / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
|
||||
|
||||
} else {
|
||||
// Use default values
|
||||
@@ -1101,14 +1123,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
|
||||
{
|
||||
sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter;
|
||||
|
||||
if (sRawValue >= 0) {
|
||||
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
|
||||
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
|
||||
}
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
|
||||
} else {
|
||||
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
|
||||
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
|
||||
}
|
||||
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
|
||||
@@ -1118,14 +1143,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt
|
||||
|
||||
sRawValue -= usJoystickCenter;
|
||||
|
||||
if (sRawValue >= 0) {
|
||||
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
|
||||
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
|
||||
}
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
|
||||
} else {
|
||||
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
|
||||
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
|
||||
}
|
||||
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
|
||||
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
|
||||
|
@@ -751,11 +751,12 @@ bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoysti
|
||||
|
||||
++SDL_HIDAPI_numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickAdded(joystickID);
|
||||
|
||||
if (pJoystickID) {
|
||||
*pJoystickID = joystickID;
|
||||
}
|
||||
|
||||
SDL_PrivateJoystickAdded(joystickID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1051,6 +1052,11 @@ static bool HIDAPI_CreateCombinedJoyCons(void)
|
||||
info.usage = USB_USAGE_GENERIC_GAMEPAD;
|
||||
info.manufacturer_string = L"Nintendo";
|
||||
info.product_string = L"Switch Joy-Con (L/R)";
|
||||
if (children[0]->is_bluetooth || children[1]->is_bluetooth) {
|
||||
info.bus_type = SDL_HID_API_BUS_BLUETOOTH;
|
||||
} else {
|
||||
info.bus_type = SDL_HID_API_BUS_USB;
|
||||
}
|
||||
|
||||
combined = HIDAPI_AddDevice(&info, 2, children);
|
||||
if (combined && combined->driver) {
|
||||
|
@@ -84,6 +84,7 @@
|
||||
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17
|
||||
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18
|
||||
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19
|
||||
#define USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT 0x0689
|
||||
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
|
||||
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
|
||||
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
|
||||
|
@@ -471,7 +471,7 @@ bool SDL_SendJoystickVirtualSensorDataInner(SDL_Joystick *joystick, SDL_SensorTy
|
||||
return false;
|
||||
}
|
||||
hwdata->sensor_events = sensor_events;
|
||||
hwdata->max_sensor_events = hwdata->max_sensor_events;
|
||||
hwdata->max_sensor_events = new_max_sensor_events;
|
||||
}
|
||||
|
||||
VirtualSensorEvent *event = &hwdata->sensor_events[hwdata->num_sensor_events++];
|
||||
|
@@ -40,11 +40,7 @@
|
||||
#define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF)
|
||||
|
||||
// external variables referenced.
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
extern HWND SDL_HelperWindow;
|
||||
#else
|
||||
static const HWND SDL_HelperWindow = NULL;
|
||||
#endif
|
||||
|
||||
// local variables
|
||||
static bool coinitialized = false;
|
||||
|
@@ -1030,7 +1030,7 @@ static bool RAWINPUT_JoystickInit(void)
|
||||
{
|
||||
SDL_assert(!SDL_RAWINPUT_inited);
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, true)) {
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -585,7 +585,7 @@ static bool WGI_JoystickInit(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, true)) {
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,17 @@ static SDLIosMainCallbacksDisplayLink *globalDisplayLink;
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(appIteration:)];
|
||||
// Enable high refresh rates on iOS
|
||||
// To enable this on phones, you should add the following line to Info.plist:
|
||||
// <key>CADisableMinimumFrameDurationOnPhone</key> <true/>
|
||||
// If main callbacks are used then this CADisplayLink will affect framerate, not one in SDL_uikitviewcontroller.
|
||||
if (@available(iOS 15.0, tvOS 15.0, *)) {
|
||||
const SDL_DisplayMode *mode = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
|
||||
if (mode && mode->refresh_rate > 60.0f) {
|
||||
int frame_rate = (int)mode->refresh_rate;
|
||||
self.displayLink.preferredFrameRateRange = CAFrameRateRangeMake((frame_rate * 2) / 3, frame_rate, frame_rate);
|
||||
}
|
||||
}
|
||||
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
return self;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user